WebDriverを統合したSelenium 2を使ってみる
Seleniumとは
Seleniumとは、Webアプリケーションのテストを自動化するためのフレームワークです。Seleniumが提供するコマンドやAPIを用いることで、実際にWebブラウザを動かしながらWebアプリケーションの動作を検証することができます。これにより、従来手動で行っていたWebアプリケーションにおける回帰テストの多くを自動化することが可能になります。
Selenium 2(Selenium WebDriver)とは
Selenium 2は、先月の8日に正式版がリリースされた、Seleniumプロジェクトの新しいプロダクトです。Selenium 2の最大の特徴は、やはりWebDriverとの統合でしょう。これについては、WebDriverの開発者であるSimon Stewart氏の話も含めた詳しい内容が以下の記事に載っているので、そちらを参照してください。
Selenium 2 (別名 Selenium WebDriver) がリリース
この統合により、WebDriver APIを用いたテストが作成できるようになりました。今回は、このWebDriver APIを使ってテストを作成してみます。WebDriver APIは、Java、Python、Ruby、C#による実装がありますが、今回はJavaからWebDriver APIを使ってみます。
準備
Selenium 2を利用するためには、Selenium 2のライブラリを参照できるようにする必要があります。Mavenを利用している場合は、pom.xml
のdependencies
に以下を追加するだけです(x
には最新バージョンの番号を入れてください)。
<dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>2.x.0</version> </dependency>
Mavenを利用しない場合は、以下のURLにアクセスして、selenium-java-2.x.0.zip
をダウンロードしてきます。
Downloads - selenium - Browser automation framework - Google Project Hosting
ダウンロードしたものを解凍し、その中にあるselenium-java-2.x.0.jar
と、libs
フォルダ以下のjarファイルを全てクラスパスに追加します。
動かしてみる
まずは簡単なプログラムを動かしてみます。以下のようなクラスを作成します。
import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; public class GoogleTest { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); driver.get("http://www.google.co.jp/"); driver.quit(); } }
プログラムを実行すると、Firefoxが起動してGoogleのトップページが表示されます。
FirefoxDriver
というのが、Firefoxを動かすためのWebDriver
の実装クラスです。FirefoxDriver
以外にも、以下のようなDriverが提供されています。
- InternetExplorerDriver(Windowsのみ)
- ChromeDriver
- OperaDriver
- AndroidDriver
- IPhoneDriver
- HtmlUnitDriver
ほとんどが直接ブラウザを動かすものですが、実際のWebブラウザを起動せずにWebブラウザの動きをシミュレートするHtmlUnitDriver
というものもあります。Webブラウザを起動する必要がないため、他のDriverよりも実行速度が早いという特徴があります。内部ではRhinoを使っているようです。
ここでは、FirefoxDriver
のインスタンスを生成することでWebブラウザを起動し、そのインスタンスのget
メソッドを呼び出すことで、Googleのトップページを開いています。get
メソッドは、引数で指定したURLに対してGETリクエストを送ります。トップページを開いた後は、quit
メソッドでWebブラウザを閉じています。このように、ごく簡単な記述で、ブラウザの起動から、操作、終了までを制御することができます。
次は、Googleのトップページを開いた後に、「selenium」というキーワードでの検索を行ってみます。
import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; public class GoogleTest { private static WebDriver driver; public static void main(String[] args) { driver = new FirefoxDriver(); driver.get("http://www.google.co.jp/"); searchFor("selenium"); driver.quit(); } private static void searchFor(String keyword) { WebElement searchBox = driver.findElement(By.name("q")); searchBox.sendKeys(keyword); searchBox.sendKeys("\n"); try { Thread.sleep(3000); } catch (InterruptedException e) { /* ignore */ } } }
新たにsearchFor
というメソッドを作成しました。このメソッドは、引数に指定されたキーワードを用いてGoogle検索を行うためのメソッドです。プログラムを実行すると、「selenium」というキーワードが検索ボックスに入力され、インスタント検索による検索結果が表示されます。
searchFor
メソッドの中では、検索ボックスの要素を探し、その要素に対して入力キー情報を送るといった処理をしています。Thread.sleep()
を行っているのは、インスタント検索によるAjax通信および検索結果のレンダリングを待機するためです。もしも待機せずに、検索結果からさらに別の要素を探したりしようとすると、要素が見つからないといった例外が発生してしまう場合があります。
JUnitと組み合わせる
実際に自動テストを実現するためには、Webブラウザを動かすだけでなく、動作結果を検証する必要があります。検証には、JUnitやTestNGなどのテスティングフレームワークを用いることができます。今回は、JUnitと組み合わせてテストを作成してみます。
先程のクラスを以下のように書き換えます。
import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; public class GoogleTest { private static WebDriver driver; @Test public void searchForSeleniumWebsite() throws Exception { driver = new FirefoxDriver(); driver.get("http://www.google.co.jp/"); searchFor("selenium"); assertThat(driver.getTitle(), is("selenium - Google 検索")); driver.quit(); } private static void searchFor(String keyword) throws InterruptedException { WebElement searchBox = driver.findElement(By.name("q")); searchBox.sendKeys(keyword); searchBox.sendKeys("\n"); Thread.sleep(3000); } }
基本的な構成はそのままに、JUnit 4形式のテストクラスへと書き換えました。
@Test
アノテーションが付いたsearchForSeleniumWebsite
メソッドが、検索後の画面遷移を検証するためのテストメソッドです。ここでは、検索後に正しく画面が遷移していることを、ページのタイトルを見て確認しています。assertThat
メソッドを呼び出しているのがその部分です。
このテストの問題点として、テストメソッドが増えた際に、メソッド毎に毎回ブラウザを起動してしまうという点があります。動作としては問題ないのですが、テストメソッドが増えるごとに時間が余計にかかってしまいます。また、テストが途中で失敗した場合に、ブラウザが起動しっぱなしになってしまうという問題もあります。これらの問題を解決するためには、以下のような書き換えを行います。
import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; public class GoogleTest { private static WebDriver driver; @BeforeClass public static void setUpBeforeClass() { driver = new FirefoxDriver(); } @AfterClass public static void tearDownAfterClass() { driver.quit(); } @Test public void searchForSeleniumWebsite() throws Exception { driver.get("http://www.google.co.jp/"); searchFor("selenium"); assertThat(driver.getTitle(), is("selenium - Google 検索")); } private static void searchFor(String keyword) throws InterruptedException { WebElement searchBox = driver.findElement(By.name("q")); searchBox.sendKeys(keyword); searchBox.sendKeys("\n"); Thread.sleep(3000); } }
JUnit 4の@BeforeClass
と@AfterClass
アノテーションを使って、テストの実行前と実行後にWebブラウザの起動と終了の処理を入れています。実行前にFirefoxDriver
のインスタンスを生成し、それを全てのテストメソッドで使い回せる形にしています。テスト終了後は、テストの成功・失敗に関わらず、Webブラウザは正しく終了されます。
おわりに
今回はSelenium 2の基本的な部分を使ってみましたが、他にも色々な機能があります。詳しくは参考資料を参照してください。
洗練されたWebDriver APIを用いることで、可読性の高いWebブラウザベースでの自動テストを簡単に作成できるようになりました。これからプロジェクトで自動テストを導入しようと考えてる方は、是非一度試してみてください。