Selenium WebDriver を利用して Webアプリケーションのテストをしてみる
以前から気になっていた Selenium WebDriver を使ってWebアプリの自動テストを試してみたので忘れないうちにメモ。
WebDriverに惹かれたのは以下の理由
- ブラウザの操作がJavaで簡単に書ける(学習コストが低い)
- 記述するコードが簡潔で分かりやすい(コードのメンテナンスがしやすい)
- JUnitからも実行できる(Jenkinsから実行して自動化したり)
- ブラウザのスクリーンショットが撮れる(エビデンス作成)
導入準備
ここから Selenium Client Drivers(Java) をダウンロードしてjarにクラスパスを通すだけ。
Mavenを利用する場合、pom.xmlに selenium-java を追加するだけでOKです。
ブラウザ操作の機能のみを利用するだけなら selenium-htmlunit-driver は不要なのでexclusionを指定しておくと余計な依存jarを減らせます。
<dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>2.5.0</version> <scope>test</scope> <exclusions> <exclusion> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-htmlunit-driver</artifactId> </exclusion> </exclusions> </dependency>
さっそくWebDriverを利用してブラウザを操作する
Seleniumの本家ドキュメントに載っているサンプルです。お手軽。コードを見れば処理の内容もなんとなくわかります。
実行するとFirefoxが起動し、ブラウザの操作が自動でおこなわれます。
public class Main { public static void main(String[] args) { // ブラウザ(Firefox)を起動 WebDriver driver = new FirefoxDriver(); // URLを開く driver.get("http://www.google.co.jp"); // name が "q" の要素を取得 WebElement element = driver.findElement(By.name("q")); // 文字をタイプ element.sendKeys("selenium"); // submit element.submit(); // ブラウザを閉じる driver.quit(); } }
JUnitからWebDriverを利用する
WebDriverはJUnit上でも問題なく動作します。
以下のコードはJUnitのBeforeClassを利用しテスト前処理にブラウザの起動処理を入れています。
その後テストメソッドの中で Yahoo!のTOP画面を開き、検索フィールドに『selenium』とタイプし、検索ボタンを押下しています。
テスト後の後処理はAfterClassを利用しブラウザを閉じています。
(Googleで検索をおこなうと検索フィールドにタイプした瞬間に検索結果画面が表示されてしまうので動作が分かりにくいと思ったので…。)
public class YahooSearchTest { private static WebDriver driver; @BeforeClass public static void setUpBeforeClass() throws Exception { driver = new FirefoxDriver(); // driver = new InternetExplorerDriver(); // driver = new ChromeDriver( // new ChromeDriverService.Builder() // .usingChromeDriverExecutable(new File("resources\\chromedriver.exe")) // .usingAnyFreePort() // .build()); } @AfterClass public static void tearDownAfterClass() throws Exception { driver.quit(); } @Test public void Yahoo検索() throws Exception { driver.get("http://www.yahoo.co.jp"); driver.findElement(By.name("p")).sendKeys("selenium"); driver.findElement(By.id("srchbtn")).click(); assertThat(driver.getTitle(), is("「selenium」の検索結果 - Yahoo!検索")); }
起動するブラウザを変更するには最初に生成しているDriverクラスを変更するだけです。簡単。
ただしChromeを利用する場合は以下のURLから chromedriver.exe をダウンロードし、上記サンプルのようにusingChromeDriverExecutableメソッドでexeファイルを指定する必要があります。
スクリーンショットの保存
スクリーンショットを保存するには TakesScreenshotインターフェース のgetScreenshotAsメソッドを実行すれば良いみたいです。
InternetExplolerDriverもFirefoxDriver、ChromeDriverもTakesScreenshotの実装クラスになっているためスクリーンショットの保存が可能です。
private void saveScreenshot(File saveFile){ try { if(driver instanceof TakesScreenshot) { File tmpFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); FileHandler.copy(tmpFile, saveFile); } } catch(Exception e) { throw new RuntimeException(e); } }
要素を読み込むまで待機する処理
Ajaxなどの処理でJavaScriptからDOMを更新している場合は待機処理を入れないとうまく動作しない場合があったりしたので
指定したエレメントが表示されるまでの待機処理メソッドも作っておいたほうが良いです。
private void waitForElementToLoad(final By locator, int timeOutInSeconds) { new WebDriverWait(driver, timeOutInSeconds).until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver driver) { return driver.findElement(locator).isDisplayed(); } }); }
ブラウザの操作処理 - クリック処理、文字のタイプ処理、プルダウンの選択処理
本家サイトにも載っているのですがよく使う操作をメソッドにまとめておくと便利。
/** * クリック処理 * * @param locator */ public void click(By locator) { driver.findElement(locator).click(); } /** * フォームのサブミット処理 * * @param locator */ public void submit(By locator) { driver.findElement(locator).submit(); } /** * テキストフィールドの入力処理 * * @param locator * @param text */ public void type(By locator, String text) { WebElement element = driver.findElement(locator); element.sendKeys(text); } /** * プルダウンの選択処理 * * @param locator * @param label */ public void select(By locator, String label) { Select element = new Select(driver.findElement(locator)); element.selectByVisibleText(label); } /** * sleep処理 * * @param millis */ public void sleep(long millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { throw new RuntimeException(e); } }