Seleniumの自動テストをCI環境(Jenkins)で快適に実施する
Ruby Advent Calendar 2011 16日目の記事です。
Webアプリの画面テストにはやはりその利便性からSeleniumを使うことが多いだろう。
ちょっとした変更でも問題ないと高をくくっていても、リリース後にリンクやボタンをクリックした途端に500や404が発生した日には目も当てられない。
そうならないために、定期的にSeleniumのテストを流す--自動テスト環境を構築して--ことで、問題をいち早く検知することが大切だ。
今回は、Webアプリにおける画面の自動テスト環境を、Selenium+Ruby(RSpec)+Jenkinsで構築する一例を紹介する。
Seleniumで画面テストを書くときにRSpecの恩恵を得たいので、現在Javaで開発しているプロジェクトも画面テストはRubyでSeleniumテストコードを書いている。
用意するもの
SeleniumをCI環境で実施するために以下のものを用意しておこう。
- Seleniumのテストコードおよびgem
- Jenkinsサーバ
- テスト用クライアントマシン
- selenium-server-standalone.jar(http://code.google.com/p/selenium/downloads/list)
- chromedriver(http://code.google.com/p/chromium/downloads/list)
Seleniumのテストコード
まずは、Seleniumのテストコードを作成することろから始めよう。
Seleniumテストの構成
依存するgemを定義しておくことでプロジェクトメンバ全体で共有できるので、テストコードのディレクトリにGemfileを用意しておき、bundlerを必ず使うように周知する。
source "http://rubygems.org" gem "rspec", "~> 2" gem "selenium-webdriver" gem "watir-webdriver" gem "pry"
ちなみに、現プロジェクトのSeleniumテストのディレクトリ構成は、
#{PROJECT_ROOT}/test/selenium | `- Rakefile `- Gemfile `- bin/ # テストデータ生成するスクリプト等が置いてある `- conf/ # 設定ファイル置き場。各テストクライアントマシンへのホスト名等も一ファイル一環境として作成している `- lib/ # selenium-webdriverにモンキーパッチしたものや、DBアクセスやutility系が置いてある `- spec/ # specファイル
のようになっている。
# pryを使用しているのはテストを書いているときに、binding.pryで途中で止めてDOMを確認するときに便利だからだ。
watir-webdriverを使う
さらに、watir-webdriverを使う。
これはwebdriverのAPIをラップしたライブラリで、より直観的にRubyでSeleniumテストコードが書けるようになっている。
たとえば、selenium-webdriverだけで、画面テストを書くと
require 'selenium-webdriver' @driver = Selenium::Webdriver.new @driver.navigate.to "http://www.example.com/path/to/test/page" @driver.find_element(:tag_name => 'div').find_element(:class => 'hoge'). find_element(:tag_name => 'a'). click
このように少しコードが冗長になってしまうが、watir-webdriverで書くと、
require 'watir-driver' @browser = Watir::Browser.new @browser.goto "www.example.com/path/to/test/page" @browser.div(:class => 'hoge'). a. click
とWatir::Element等便利なラッパーが用意されていることで直観的に書ける。
Jenkins側でのコントロール
Jenkins側で、SeleniumテストをRakeでキックするためにRakeプラギンを導入しておこう。
Rakeで各テストのキックをコントロールするためだ。Rakeプラギンを使うことで、JenkinsからRakeの実行が簡単になる。
Rakeプラギンをインストールすると、Seleniumテストを実施するjobの設定項目の'ビルド'でビルド手順の追加プルダウンから'Invoke Rake'が追加されている。
Rakeプラギンで設定できる項目として、
- Rakeのバージョン
- Rakeのタスク
- Rakefile
- Rakeライブラリのディレクトリ
- Rakeを実行するディレクトリ
がある。
また、Rakeプラギンが1.7からrvmに対応したので、RakeプラギンをいれておくとJenkinsのシステム設定でrvmのパスを指定できるようになり、簡単にRakeのバージョンを切り替えられるようになっている。
Rakeタスクをいろいろ用意しておくことで、さまざまなクライアントの環境毎や、テストしたいページ毎に実行できる点が重要だ。
僕が現在開発しているプロジェクトでは次のようなタスクを用意している。
$ rake -T rake all # Run all selenium rake ie6_test # IE6 test rake ie7_test # IE7 test rake ie8_test # IE8 test rake regression_test # regression test ...
これらのタスクを登録しておけば、Jenkinsのjobが起動したときに各Rakeタスクを実行してくれる。テストの粒度をRakeタスクで調整できるので便利だと思う。
余談だが、JenkinsについてのtipsはJenkins Advent Calendar 2011に詰まっているので各エントリを一読しておこう。
リモート実行環境を整える
次に、selenium-webdriverをリモートの各クライアント環境でテストを実施する環境を整えよう。 selenium-webdriverの利点として、リモート実行環境の構築が簡単になることだ。 selenium-server-standalone.jarをダウンロードして、各テスト用クライアントマシンに配置する。 Windowsであれば、selenium-server-standalone.bat、Unix環境ならselenium-server-standalone.shを作成して、
java -jar selenium-server-standalone-*
という起動スクリプトを作成しておいて、クライアントマシンが起動するときにこの起動スクリプトを実行するように仕込んでおけばいつでもSeleniumテストをリモート実行できる。
# なぜ起動スクリプトを自動化しておく必要があるのかというと、クライアントマシンでテストを続けると、とくにWindowsだと重たくなったりするので定期的にクライアント自体を再起動するため