テスト自動化の様々
な道具を使ってみた
四方山話
Selenium Webdriver, fuluentlenium, geb, gebspec
自己紹介
twitter: @haljik
もうすぐフリーのプログラマーです。
JVM言語や、Java周りのエコシステムが好きで
す。
関西Javaエンジニアの会,Devlove関西,京都アジ
ャイル勉強会とかちらほらと参加
今日紹介するツール
4 Selenium Webdriver
4 Fluentlenium
4 Geb/GebSpec
全部WEBブラウザ
の操作を自動化する
ツールですが
どれも出来ることは
変わらない
違いは書きやすさと
表現力
ということでそれぞ
れ書くと
Selenium WebDriver
一番低レベルな実装でこれでできない操作は他の
でもできない
public class BingTest {//ドライバーのセットアップとかは省略
@Test
public void title_of_bing_should_contain_search_query_name() throws Exception {
driver.get("http://www.bing.com");
driver.findElement(By.id("sb_form_q")).sendKeys("automation");
driver.findElement(By.id("sb_form_go")).click();
assertThat(driver.getTitle(), containsString("automation"));
}
}
(´・ω・`)
Fluentlenium
Javaで書ける範囲で頑張ったAPI。WebDriver
のラッパー
public class BingTest extends FluentTest {
@Test
public void title_of_bing_should_contain_search_query_name() {
goTo("http://www.bing.com");
fill("#sb_form_q").with("automation");
submit("#sb_form_go");
assertThat(title()).contains("automation");
}
}
(`・ω・´)
Geb (「じぇぶ」と読む)
Groovyで書ける。Spockで書ける。 WebDriver
のラッパー
class BingSpec extends GebSpec {
def "title_of_bing_should_contain_search_query_name"() {
when:
go "http://www.bing.com"
$("#sb_form_q").value "automation"
$("#sb_form_go").click()
then:
title.contains("automation")
}
}
(・ ・)イイ!! ※但しIDEAに限る…
で
実際の開発で使って
みた話
Context
4 大規模エンタープライズプロジェクト向けの
WEBアプリケーションフレームワーク
4 言語はJava
やりたいこと
4 いつまでもリファクタリングし続けたい
4 要望へスピーディーに対応してリリースしたい
でも大規模プロジェクトの
基盤って
4 一旦リリースした後の変更は膨大なテストをパ
スさせないかぎり無理
4 基本的に嫌がられる
でも変更し続けたい
どうしよう
前例を作ろう
膨大なテストを自動
化し、リリース実績
を積んでゴリ押しす
る感じでやってみま
した
テスト構成
4 ユニットテスト&コンポーネントテスト
Junitで個々のコンポーネントをテスト
4 結合テスト
Junit&Fluentleniumを使った機能別マルチ
ブラウザテスト
4 総合テスト
Junit&Fluentleniumを使ったブラウザテス
トで実業務アプリを模したアプリのシナリオテ
スト
さらにこれらを
Jenkinsで常時実行
する
ブラウザテストを常
時実行する環境って
Selenium Grid vs
Jenkins Slave
Selenium Grid
Selenium Gridの構成
メリット
4 消費するクライアントリソースが少ない
4 テストが速い
デメリット
4 ブラウザ実行ホストのアドレスをサーバが知っ
ている必要がある
4 ブラウザ実行ホストにサーバを常駐させる必要
がある
Jenkins Slave
Jenkins Slaveの構成
メリット
4 CIサーバはブラウザ実行ホストのアドレスを知
らなくても良い
4 WebBrowser実行ホスト側にサーバをセット
アップしなくて良い
デメリット
4 JenkinsのJobそのものを実行するため消費リ
ソースが多い
構成の簡単さで今回
はJenkins Slaveを選
択
いざテストを始める
と
テストが不安定
原因
1. CIサーバとWebBrowser実行ホスト間のネッ
トワーク
2. WebBrowser実行ホストの物理的故障
3. タイミングに依存したテスト
1. CIサーバ、WebBrowser実行ホス
ト間のネットワーク
4 ネットワークが切れやすくテストが失敗する
connection resetが頻発とか
4 ネットワークが遅すぎてテストが失敗する
time outとか
2. WebBrowser実行ホストの物理
的故障
4 電源周りとか壊れやすい
4 クライアントマシン(PC)は常時可動するよう
に作られていない
1.と2.の解決策
仮想化
ネットワーク的に近い場所でJenkins Slaveや、
Seleniumサーバ複数を常時起動させられるため、
仮想化するのが理想
4 課題
WindowsやLinuxは簡単に仮想化できるが…
Mac/IOSは…
3. タイミングに依存したテスト
4 Thread.sleep()を使っている
1. シンプルに作ったテストケースで何故か失
敗する場所をThread.sleep()を入れてごま
かす
2. 成功したり失敗したりで安定しない
3. sleepする量や場所を増やす
4. 2と3を繰り返すも安定しないうえに、ひた
すら遅いテストになる
本当の原因
DOM構造の変わらない画面操作
例
4 一覧表のページング
4 Ajaxによる値の書き換え
解決策
アサートの成功を待つ
アサートの成功を待つ
4 何らかの画面操作の後は必ず何らかの値のアサ
ートを行っている
4 DOMの構造が変わらなくてもアサート対象の
値は変わっている
なので…
値が期待する値に変
わるのをタイムアウ
ト値を指定して待ち
タイムアウトしたら
AssertionErrorとみ
なす!
どーやって待つのか
Selenium WebDriverの場合
driver.findElement(By.id("updateButton")).click()
new WebDriverWait(driver, 3).until(
ExpectedConditions
.textToBePresentInElementLocated(By.id("message"), "更新しました")
);
Timeout時のメッセージ
org.openqa.selenium.TimeoutException:Timed out after 3 seconds waiting
for text ('更新しました') to be present in element found by By.id:
message
思ったより良い感じ
Fluentleniumの場合
click("#updateButton");
await().atMost(3, TimeUnit.SECONDS).until("#message").hasText("更新しました");
Timeout時のメッセージ
org.openqa.selenium.TimeoutException: Timed out after 3 seconds:
Selector #message has not the text 更新しました.
やっぱりこっちのが良い
Gebの場合
$("#updateButton").click();
waitFor(3) { assert $("#message").text() == "更新しました" }
Timeout時のメッセージ
assert $("#message").text() == "更新しました"
| | |
| "" false
[[[[[FirefoxDriver: firefox on MAC (ry
PowerAssertすごい ※但しIDEAに限る
※PowerAssertはGebというよりSpockの特徴
こんな感じでやって
みて大体のテストは
安定し、現時点では
1日でリリースがで
きるようになった
残る問題
1. 画面のテストは変更がめんどくさい
2. ファイルアップロードの自動化
1. 変更が面倒
Page Object Pattern
で画面と対になる
Page Objectに画面構
造を隠 し、テスト
を守る
2. ファイルアップロ
ード…
最近のブラウザはセ
キュリティが厳しく
てプログラムからフ
ァイル指定させてく
れない
ファイルアップロードの解決
策の候補たち
4 Wsh (Windowsでは定番っぽい?)
4 Sikuli (安定を望む)
4 java.awt.Robotで座標指定クリック (...なつ
かしい)
4 アプリ側をHTML5のFileAPIとAjaxで実装す
る (IEが…)
※試せていません…
現状決定打になるも
のがないのではと勝
手に思っている
まとめ
sleepダメ絶対

テスト自動化の様々な道具を使ってみた四方山話