一般的にWebアプリケーションのテストでは、「Webページ内の要素に対して、まず操作を行い、そして操作結果を想定値と比較する」形をとります。そのため、テストクラスの実装は下記のような処理の手順を踏むことになります。
org.openqa.selenium.WebDriverの実体オブジェクトを作成し、メソッド「get(String url)」を使用し、テスト対象のURLを読み込みます。
「【1】Webブラウザの初期化処理」で読み込んだテスト対象のURLに対し、WebDriverのメソッド「findElement(By by)またはfindElements(By by)」を使用し、操作対象の要素を取得します。
「【2】対象要素の取得」で取得した要素に対して操作を行います(入力用の要素の場合、値を入力します。ボタンなどイベントトリガ用の部品の場合、クリック処理を行います)。
「【3】対象要素に対する操作」で操作を行った結果と、テストで想定される結果とを比較します。APIが用意されており、操作結果を簡単に取得できる場合はJUnitなどでテスト結果を自動で出力します。
操作結果が簡単に取得できない場合は、画面のキャプチャーを撮り、後で目視確認します。
テスト操作対象のWebブラウザウィンドウを全て閉じます。テスト実行処理前の状態に戻す場合は、テスト操作前の状態に戻す処理を行い、その後、テスト操作対象のWebブラウザウィンドウを全て閉じます。
ここからは、この手順を踏んだ形でテストケースの中身を抜粋して見ていきましょう。
サンプルコード1は「表2 テストケース一覧」のテストケース6とテストケース7を合わせたテストケースを実装したものです。
// ユーザ名21文字でのエラーを発生させた後、20文字で入力して変更を成功させる private void editInvalidTest_21char_20char() { driver.get(initialURL); // 【1】 編集画面に遷移 driver.findElement(By.xpath("//table[@id='emptable']/tbody/tr[2]/td/a")).click(); // 【2】始まり // ユーザー名など入力 driver.findElement(By.xpath("//table[@id='edittable']/tbody/tr[2]/td[2]/input")).clear(); driver.findElement(By.xpath("//table[@id='edittable']/tbody/tr[2]/td[2]/input")) .sendKeys("テスト変更_XX#?1234567890+"); new Select(driver.findElement(By.xpath("//table[@id='edittable']/tbody/tr[3]/td[2]/select"))) .selectByVisibleText("開発部1部"); driver.findElement(By.xpath("//table[@id='edittable']/tbody/tr[4]/td[2]/input[2]")).click(); driver.findElement(By.xpath("//table[@id='edittable']/tbody/tr[5]/td[2]/input")).click(); // 変更ボタンクリック driver.findElement(By.xpath("//div[@id='editpanel']/form/input[6]")).click(); // 【2】終わり // 【3】 確認ダイログでOKを押す driver.switchTo().alert().accept(); // 【4】始まり // エラーメッセージのアサート assertThat(driver.findElement(By.xpath("//div[@id='editpanel']//ul/li")).getText(), is(containsString("社員名は20文字以内で入力してください。"))); // 画面キャプチャーも撮っておく String filePath_20over = CaputureUtils.getFilePath(getClass().getName(), browserName, "editInvalidTest_21char_20char_1st"); CaputureUtils.getScreenshot((TakesScreenshot) driver, filePath_20over); Logger logger = Logger.getLogger(getClass()); logger.info(filePath_20over + "のキャプチャー内エラー文言が「・社員名は20文字以内で入力してください。 」となっていることを確認してください。"); // 【4】終わり // 【5】始まり // 20文字で入力 driver.findElement(By.xpath("//table[@id='edittable']/tbody/tr[2]/td[2]/input")).clear(); driver.findElement(By.xpath("//table[@id='edittable']/tbody/tr[2]/td[2]/input")) .sendKeys("テスト変更_X#?1234567890+"); // 変更ボタンクリック driver.findElement(By.xpath("//div[@id='editpanel']/form/input[6]")).click(); // 確認ダイログでOKを押す driver.switchTo().alert().accept(); // メッセージのアサート assertThat(driver.findElement(By.xpath("//center")).getText(), is(containsString("テスト変更_X#?1234567890+の情報を変更しました。"))); // 画面キャプチャーも撮っておく String filePath_20 = CaputureUtils.getFilePath(getClass().getName(), browserName, "editInvalidTest_21char_20char_2nd"); CaputureUtils.getScreenshot((TakesScreenshot) driver, filePath_20); logger.info(filePath_20 + "のキャプチャー内文言が「テスト変更_X#?1234567890+の情報を変更しました。 」となっていることを確認してください。"); // 【5】終わり // 【6】一覧画面に戻る driver.findElement(By.linkText("検索")).click(); }
それぞれの処理は下記のようになっています。
サンプルコード1ではキャプチャーを保存する際に、「CaputureUtils」というクラスを使用していますが、これは独自で作成したユーティリティークラスです。
処理内容はサンプルコード2を参照してください。下記【1】のようにしてWebブラウザのdriver(TakesScreenshot)を使用することで、キャプチャーを保存できます。
public class CaputureUtils { public static void getScreenshot(TakesScreenshot driver, String filePath) { // 【1】 File scrFile = driver.getScreenshotAs(OutputType.FILE); try { FileUtils.copyFile(scrFile, new File(filePath)); } catch (IOException e) { Logger logger = Logger.getLogger(CaputureUtils.class); logger.warn(e); } } public static String getFilePath(String... params) { StringBuilder builder = new StringBuilder(); builder.append("c:\\tmp\\"); builder.append(getYYYYMMDD()); builder.append("\\screenshot\\"); builder.append(getYYYYMMDD()); for (String param : params) { builder.append("_"); builder.append(param); } builder.append(".png"); return builder.toString(); } (中略) }
サンプルコード1は一切Webブラウザに依存しない部分についてのみ記述しています。Webブラウザごとに異なる実装をする必要がある場合には、それぞれのWebブラウザ用のテストケースでテストコードを実装することになります。
例えば、Firefox用の従業員検索画面テストクラスのコード(下記サンプルコード3)は、ファイルダウンロードに関するテストは独自で実装しています。
またサンプルコード3に関しては、ファイルダウンロードに関するテスト以外、「共通のテスト実行用の処理のみ」のテストが可能となっていることに注目してください。
Selenium WebDriverでは、テストコードにおいてWebブラウザごとに異なる記述をする場面が少なくなるようにAPIが設計されていることが実感できる例といえるでしょう。
package employeeManager.firefox.search; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.firefox.FirefoxDriver; import employeeManager.common.search.EmployeeManagerSearch; import employeeManager.firefox.EmployeeManagerFirefoxDriver; /** * Firefoxの従業員一覧画面テスト */ public class EmployeeManagerFirefoxSearch extends EmployeeManagerFirefoxDriver { private EmployeeManagerSearch employeeManagerSearch; @Override protected void setupProfile() { } @Override public void preTest() { super.preTest(); employeeManagerSearch = new EmployeeManagerSearch("Firefox", getDriver(), getinitialURL()); } // 遷移テスト @Test public void transitionTest() throws InterruptedException { employeeManagerSearch.transitionTest(); } // ダウンロードテスト @Test public void downloadTest() throws InterruptedException { if (driver != null) { driver.quit(); } // NOTE Firefoxはダウンロードリンクをクリックするだけだと、そのまま開くか、どこにダウンロードするかのダイアログが開かれてしまう // このダイアログを回避するため、profileの設定を行い直接ダウンロードできるようにする // ダウンロードするファイルの保存先フォルダを指定 0:デスクトップ 1:ダウンロードフォルダ 2:ダウンロードに指定された最後のフォルダ profile.setPreference("browser.download.folderList", 0); // ダウンロードするファイルの保存先フォルダが指定してあればそれを使う profile.setPreference("browser.download.useDownloadDir", true); // 指定したmimeタイプは有無を言わさずダウンロードする profile.setPreference("browser.helperApps.neverAsk.saveToDisk", "application/octet-stream;"); // 作成したプロファイルでFirefox(のドライバ)を起動する driver = new FirefoxDriver(profile); driver.get(getinitialURL()); driver.findElement(By.xpath("//div[@id='downloadpanel']/form/input")).click(); Thread.sleep(3000); } }
Copyright © ITmedia, Inc. All Rights Reserved.