【初心者向け】Seleniumをまわしてみよう⑤

  • 2017年4月24日
  • by 
【初心者向け】Seleniumをまわしてみよう⑤

ソフトバンク・au・ドコモの方は、公式のオンラインショップを利用すれば頭金不要で通常のショップよりお得に購入できます。

こんにちは。M.Sです。
今回の第5回目は、なんとこの「初心者向けSelenium講座」の最終回です。
<bitWave関連記事『【初心者向け】Seleniumをまわしてみよう①』>
<bitWave関連記事『【初心者向け】Seleniumをまわしてみよう②』>
<bitWave関連記事『【初心者向け】Seleniumをまわしてみよう③』>
<bitWave関連記事『【初心者向け】Seleniumをまわしてみよう④』>

最終回ではメンテナンスしやすいSeleniumのコーディング方法についてご紹介します。

Seleniumの弱点

第2回目の記事でもご紹介したとおり、Seleniumの弱点はズバリ “Webサイトのデザイン変更等で要素が取得できなくなる場合があること” です。
「なんでページ変更するの!!」と内心では思ってしまうこともありますが、とはいえSeleniumありきでページ変更・修正をしているわけではないというのもまた事実。

ここは慌てず、そして他人を責めず。
Webサイトの更新を想定し、プログラムの修正が少なくて済むようなコーディングを行っていくことで、被害を最小限に食い止めることが重要になっています。

ではソースを見てみましょう。

<ソース(※macを使用しています)>
package com.html.sample;

import java.io.File;
import java.io.IOException;

import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class SampleTest {
private WebDriver driver;

//アクセスするURL
private static String domainUrl = "http://www.showcase-tv.com/";

//取得する要素を定義
By menuInquiry = By.xpath("//*[@id='header']/div[2]/nav[1]/ul/li[5]/ol/li[1]/a");

//入力項目を定義
By inputName = By.name("name1");
By inputCampany = By.name("campany");
By inputMail = By.name("mail");
By inputTel = By.name("tel");
By inputZip = By.name("zip");
By inputAddress = By.name("address2");
By inputProduct = By.name("shouhin[F002]");
By inputInquiry = By.name("naiyou[F002]");
By inputKnow = By.cssSelector("input[name='enc'][value='以前サービスを使用していた']");
By buttonSubmit = By.name("submit1");

//ここからテスト

@Before
public void SetUp() {
System.setProperty("webdriver.chrome.driver","./driver/chromedriver");
driver = new ChromeDriver();
}

@Test
public void showcaseForm() throws IOException {
//ショーケースtvのページを開く
driver.get(domainUrl);

//スクリーンショット
TakeScreenShot("1.ショーケース・ティービーTopページ開く", driver);

//画面上にid(header)が表示されるまで待機
WebDriverWait wait = new WebDriverWait(driver,30);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("header")));

//メニュー「お問い合わせ」をクリックする
driver.findElement(menuInquiry).click();

//hiddenのname値subjectのvalueがお問い合わせフォームになるまで待機
wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//input[@value='お問い合わせフォーム']")));

//フォームアシストのナビゲーションウィンドウが表示されるまで待機
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("FA_Window")));

//お名前に入力する
driver.findElement(inputName).sendKeys("ショーケース花子");

//会社名に入力する
driver.findElement(inputCampany).sendKeys("ショーケースtv");

//メールアドレスに入力する
driver.findElement(inputMail).sendKeys("showcase@aaa.com");

//TELを入力する
driver.findElement(inputTel).sendKeys("03-1111-2222");

//入力後待機
sleep(1000);

//郵便番号を入力する
//郵便番号一覧表示のチェック
driver.findElement(inputZip).sendKeys("107-0");

//郵便番号一覧が表示されるまで待機する
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("FormAssist_zip_list1")));

//スクリーンショット
TakeScreenShot("2.郵便番号.png", driver);

//住所一覧から港区赤坂を選択する
//自動住所入力のチェック
driver.findElement(By.partialLinkText("東京都港区赤坂")).click();

//所在地を入力する
driver.findElement(inputAddress).sendKeys("昭栄赤坂ビル4F");

//入力後待機
sleep(3000);

//スクロールする
WebElement rest = driver.findElement(By.id("rest"));
scroll(rest);

//お問い合わせの対象商品
driver.findElement(inputProduct).click();

//お問い合わせ内容
driver.findElement(inputInquiry).click();

//製品を知った理由
driver.findElement(inputKnow).click();

//ナビゲーションウィンドウの文言が変わるまで待機
WebDriverWait wait3 = new WebDriverWait(driver,3);
wait3.until(ExpectedConditions.textToBePresentInElement(By.id("FA_Window_txt2"),"入力が完了しました、確認画面へお進みください。"));

//フォーム・アシストの送信ボタンが非表示になるまで待機
wait3.until(ExpectedConditions.invisibilityOfElementLocated(By.id("FormAssist_submit_err")));

//スクロールする
WebElement submit = driver.findElement(By.id("FormAssist_submit"));
scroll(submit);

sleep(3000);
}

@After
public void tearDown() {
driver.quit();
}

//スクリーンショットを取る関数
private void TakeScreenShot(String FileNames, WebDriver driver){
sleep(0);
File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
try {
FileUtils.copyFile(srcFile, new File("./SampleTestScreenshot/"+FileNames+".png"));
} catch (IOException e) {
//エラーの場合、詳細を出力する
e.printStackTrace();
}
}

//スリープを取る関数
private void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

//スクロール
public void scroll(WebElement element) {
((JavascriptExecutor)driver).executeScript("arguments[0].scrollIntoView(true);",element);
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("javascript:window.scrollBy(0,-80)");
try {
long m = 0;
Thread.sleep(m);
} catch (InterruptedException ignroe) {}
}
}

何度も使う要素などはあらかじめ定義する

第3回目の記事では、トップページのデザインが変更されたことで、[お問い合わせ] ボタンをクリックするプログラムで要素を取得できなくなり、Seleniumがエラー終了してしまいました。

上記のプログラムでは、[お問い合わせ] ボタンをクリックする動作は1度しかないため、したがって1カ所だけで修正をしてしまえばOKです。
当然ながら、このクリックする動作が2回ある場合は、プログラムの修正箇所は2カ所になってしまいます。つまり、プログラムの修正箇所は[お問い合わせ] をクリックする動作と同じ数だけ修正が必要になってしまうんですね。
同じアクションなのに面倒くさい……、ということで修正を1カ所で済ませるため、下記のように定義してみましょう。

By menuInquiry = By.xpath("//*[@id='header']/div[2]/nav[1]/ul/li[5]/ol/li[1]/a");

そして、[お問い合わせ] をクリックするプログラムを下記のようにします。

driver.findElement(menuInquiry).click();

このようにしておくことで、知らぬ間にWebサイトのデザイン変更され、かつ、[お問い合わせ] をクリックするプログラムが複数箇所あったとしても、下記のプログラムのxpathを変更するだけで、複数箇所の修正が完了したことになるんです!
By menuInquiry = By.xpath("//*[@id='header']/div[2]/nav[1]/ul/li[5]/ol/li[1]/a");

お問い合せフォームの入力項目に「name値」が変更された場合のことも想定し、あらかじめ「name値」に対しても定義してみましょう。
先ほど同様、1つの「name値」に何度もアクションを実施するプログラムがあったとしても、プログラムの修正箇所はわずか1カ所で完了!
知らぬ間に「name値」が改修されていたとしても、これなら改修作業も最低限のもので済みます!!

By inputName = By.name("name1");
By inputCampany = By.name("campany");
By inputMail = By.name("mail");
By inputTel = By.name("tel");
By inputZip = By.name("zip");
By inputAddress = By.name("address2");
By inputProduct = By.name("shouhin[F002]");
By inputInquiry = By.name("naiyou[F002]");
By inputKnow = By.cssSelector("input[name='enc'][value='以前サービスを使用していた']");
By buttonSubmit = By.name("submit1");

項目名「お名前」に入力するプログラムは下記のように変更します。
driver.findElement(inputName).sendKeys("ショーケース花子");

アクセスするURLも定義します。
private static String domainUrl = "http://www.showcase-tv.com/";

アクセスするプログラムは下記のように変更します。
driver.get(domainUrl);

今回の第5回目はテスト対象ページの可変に備え、メンテナンスしやすいコーディング方法をご紹介しました。
内容はスクリーンショットも関数に変更。そして、要素を定義したのでプログラム自体をすっきりさせることができました。

冒頭でもお伝えしたとおり、今回で「初心者向けSelenium講座」は終わりになります。

今後はよりページの可変に強く、どんなテストをしているのか他の人がみても分かりやすいSeleniumを目指し、さらに勉強を続けていきたいと思います!

ソフトバンク・au・ドコモの方は、公式のオンラインショップを利用すれば頭金不要で通常のショップよりお得に購入できます。

【週刊bitWave】(メルマガ)始めました!

登録はこちらからメールアドレスを入力してお申込みください。

ご登録いただいたメールアドレスは 【週刊bitWave】の更新情報の配信にのみ使用します。

個人情報の取扱いに関しては、「プライバシーポリシー」をご確認ください。解除はいつでもこちらから行うことが可能です。

あなたにおすすめ

  • 【初心者向け】Seleniumをまわしてみよう④ こんにちは。M.Sです。 今回は初心者向けSelenium講座の第4回目です。早いものでこの連載を開始してから1カ月が経ちました。 <bitWave関連記事『【初心者向け】Seleniumをまわしてみよう①』> <b …
  • SeleniumでMicrosoft Edgeブラウザを動かす方法 こんにちは。M.Sです。 前回は「SeleniumでIE11を動かす方法」についてご紹介しました。 今回はMicrosoft Edgeを動かしてみようと思います。 EdgeとはMicrosoftの最新ブラウザです。まだ …
  • 【初心者向け】Seleniumをまわしてみよう③ こんにちは。2月は毎日筋トレを欠かさなかったM.Sです。 ちなみに、持続のコツは短時間で集中して行うことです。筋トレは10分間と決めています。 このSelenium講座も継続して連載できていますねw 早速ですが、 …
  • 【初心者向け】Seleniumをまわしてみよう② こんにちは。M.Sです。 初心者向けSelenium講座の第2回目です。 <bitWave関連記事『【初心者向け】Seleniumをまわしてみよう①』> 今回は対象の要素の取得、取得した要素をクリックする …