連載
» 2017年07月20日 05時00分 公開

Selenium WebDriverのブラウザ自動テストを実践するSelenium WebDriverでWebアプリのテストが変わる(後編)(2/3 ページ)

[後藤正規,ビーブレイクシステムズ]

テスト手順の整理

 一般的にWebアプリケーションのテストでは、「Webページ内の要素に対して、まず操作を行い、そして操作結果を想定値と比較する」形をとります。そのため、テストクラスの実装は下記のような処理の手順を踏むことになります。

【1】Webブラウザの初期化処理

 org.openqa.selenium.WebDriverの実体オブジェクトを作成し、メソッド「get(String url)」を使用し、テスト対象のURLを読み込みます。

【2】対象要素の取得

 「【1】Webブラウザの初期化処理」で読み込んだテスト対象のURLに対し、WebDriverのメソッド「findElement(By by)またはfindElements(By by)」を使用し、操作対象の要素を取得します。

【3】対象要素に対する操作

 「【2】対象要素の取得」で取得した要素に対して操作を行います(入力用の要素の場合、値を入力します。ボタンなどイベントトリガ用の部品の場合、クリック処理を行います)。

【4】操作結果と想定値との比較

 「【3】対象要素に対する操作」で操作を行った結果と、テストで想定される結果とを比較します。APIが用意されており、操作結果を簡単に取得できる場合はJUnitなどでテスト結果を自動で出力します。

 操作結果が簡単に取得できない場合は、画面のキャプチャーを撮り、後で目視確認します。

【5】終処理

 テスト操作対象の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 EmployeeManagerEdit#editInvalidTest_21char_20char()

 それぞれの処理は下記のようになっています。

  1. 従業員一覧画面を開き、従業員一覧の上から2番目の従業員のIDをクリック
  2. 従業員情報変更時にエラーとなる情報を入力し、変更ボタンを押す
  3. 変更ボタン押下後、確認ダイアログが出るので、確認ダイアログに対して、OKを押す
  4. 従業員情報変更画面にエラーメッセージが出るので、エラーメッセージをアサート。画面キャプチャーも取得しておく
  5. 従業員情報にエラーとならない値を入力し、変更処理を行う。変更後、変更完了のメッセージをアサートし、画面キャプチャーも取得しておく
  6. 変更処理終了後従業員一覧画面に遷移

 サンプルコード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();
    }
(中略)
}
サンプルコード2 CaputureUtils(一部)

 サンプルコード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);
    }
 
}
サンプルコード3 Firefox用の従業員検索画面のテストクラス

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。