Geb はじめました

Web アプリケーションの受け入れテストを行うフレームワークとして、Geb が Groovy のエコシステムのひとつとしてリリースされています。
有名な Selenium を Geb は内部で使用していて、色々なことができる上に、比較的少ないコードで簡潔にテストコードを実装できそうなので、採用してみたいと考えていました。

The Book Of Geb - Table of Contents - 0.7.2

Geb のマニュアルサイト(英語)を根気強く読めば、Geb のことは理解できると思います。わかりやすいサイトです。ですが、動かすまで時間がかかったので備忘録的にまとめてみます。

Gradle で依存関係を設定する

ビルドツールとして、Gradle を使っています。build.gradle は次のように設定しました。

apply plugin: 'groovy'
apply plugin: 'eclipse'

repositories {
    mavenCentral()
}

dependencies {
    groovy 'org.codehaus.groovy:groovy:1.8.8'
    
    testCompile'org.spockframework:spock-core:0.6-groovy-1.8'
    testCompile'org.codehaus.geb:geb-core:0.7.2'
    testCompile'org.codehaus.geb:geb-spock:0.7.2'
            
    testCompile'org.seleniumhq.selenium:selenium-chrome-driver:2.25.0'
    testRuntime'org.seleniumhq.selenium:selenium-support:2.25.0'
}

Spock のバージョンは 0.6 を指定しています。現時点での最新バージョンは 0.7 なのですが、geb 0.7.2 とマッチングしていないようです。
どういう仕組みでエラーが発生したのか不明ですが、テストコードで Eclipse がエラーを発しました。org.spockframework.mock.MockController クラスが 0.7 になってパッケージ移動していることが原因のようです。

Groovy は 1.8 をいつも使っているので 1.8 をバージョン指定しています。バージョン 2.0 にして Spock もバージョンをそれに合わせれば(spock-core:0.6-groovy-2.0)動作するはずです。

Geb のサイトに Gradle の設定サンプルがあるので、そちらも参照してください。
Gradle - The Book Of Geb

テストコードを書く

テストフレームワークは Spock を使用していますので、Spock を使用した Geb の実装をします。
最もシンプルなのは geb.spock.GebSpec を継承する方法なのですが、画面キャプチャを残してくれる geb.spock.GebReportingSpec を継承します。

package geb.sample

import geb.spock.GebReportingSpec

class GoogleGeb extends GebReportingSpec {

    def "Google ホームページに遷移する"() {

        given:
        to GoogleHomePage

        expect:
        at GoogleHomePage
    }
}


テスト対象の画面を Page クラスとして独立してクラス定義することができます。
そうすることで、再利用性も高まります。また、テストコードで表すふるまいと独立して、画面の定義ができるのでコードの可読性もよいです。

package geb.sample

import geb.Page;

class GoogleHomePage extends Page {

    static url = "http://www.google.com"
    
    static at = { title == "Google" }
}

このテストコードは Geb のサイトのサンプルとほとんど同じなので、詳しくはそちらを参照してください。
Testing - The Book Of Geb

WebDriver を用意する

WebDriver とは、ブラウザを操作するためのドライバモジュールです(おそらく)。ブラウザごとに WebDriver が用意されています。

テスト実行する際に使用する WebDriver をシステムプロパティでパス指定する必要があります。指定しなかった場合はテスト実行時に次のような例外が発生します。

java.lang.IllegalStateException: The path to the driver executable must be set by the webdriver.chrome.driver system property; for more information, see http://code.google.com/p/selenium/wiki/ChromeDriver. The latest version can be downloaded from http://code.google.com/p/chromedriver/downloads/list

例外メッセージにしたがって、http://code.google.com/p/chromedriver/downloads/list にアクセスすると、Chrome の WebDriver がダウンロードできます。ダウンロードした WebDriver のモジュールを任意の場所において、システムプロパティ webdriver.chrome.driver で指定します。

テストコードの setup メソッドでシステムプロパティを指定することができますが、すべてのテストコードで指定するのは冗長的です。後述する GebConfig.groovy で指定します。

reportsDir を指定する

画面キャプチャを出力するディレクトリのパスを指定します。システムプロパティ geb.build.reportsDir で指定します。

上記のシステムプロパティ webdriver.chrome.driver は setup メソッドで指定することができたのですが、この geb.build.reportsDir は setup メソッドよりも前で参照されています。setup メソッドでシステムプロパティを設定してもテスト実行時に例外が発生します。(setupSpec メソッドあたりをオーバーライドすれば、テストコードでも指定できるかもしれません)

したがって、実行時の JVM 引数として -Dgeb.build.reportsDir=/xxx/yyy/zzz という形で指定するのが最も簡単な方法になります。

今回は、webdriver.chrome.driver と同様で、geb.build.reportsDir もすべてのテストコードで指定したくないので、GebConfig.groovy で指定する方法を取ります。

GebConfig.groovy

Geb の共通設定を書いておくファイルの位置づけでしょうか。デフォルトパッケージに配置するということなので、src/test/resources の直下に GebConfig.groovy を実装します。

reportsDir = "${System.properties['user.home']}/Desktop/geb"

System.setProperty("webdriver.chrome.driver", "/Applications/groovy/webdriver/chromedriver")

environments {

    // -Dgeb.env=integration を指定したときの個別設定
    integration {
        reportsDir = "/test/report/geb"
    }
}

reportsDir で画面キャプチャの出力ディレクトリを指定しています。ユーザのホームディレクトリをシステムプロパティから取得して、Desktop 上に出力されるようにしています。
また、システムプロパティで WebDriver のモジュールパスを指定しています。

単純なものであれば、最初のこの2行だけで終わりです。

environments 以下で、テスト実行環境ごとで異なる設定を上書き設定することができます。ここでは、integration という個別設定を追加して、画面キャプチャの出力ディレクトリを変更できるようにしています。結合テスト環境では所定の決められたディレクトリに出力させたいという想定です。

GebConfig.groovy についても、Geb のサイトに詳しく書かれています。
Configuration - The Book Of Geb

これで準備おわり♪

あとは GoogleGeb を JUnit などで実行すれば、勝手に Chrome が立ち上がってテストが実行されます。画面キャプチャも自動的に残してくれます。

画面キャプチャのファイル名が文字化けする

ひとつ課題が残っています。

画面キャプチャのファイル名が「001-001-Google ___________-homepage.png」という感じに文字化けします。
このファイル名はテストケース名、つまりテストコードのメソッド名が使用されるのですが、日本語がメソッド名に含まれているとこのように文字化けします。

まあ、なんとかできそうな予感はするので追々、回避策を見つけたいと思います。

[11/8 追記]
なんとかしました。次のエントリーに書きました。

Geb のレポート出力で日本語ファイル名をエスケープさせないようにする