うさぎ組

ソフトウェア開発、チームによる製品開発、アジャイル、ソフトウェアテスト

Geb 0.10の新機能紹介 #gadvent

はじめに

これはG* Advent Calendarの5日目の記事です。今日はGeb0.10の新機能について書きます。明日はid:grimrose さんのRatpackについて です。

概要

GebはWebアプリケーションのGUIテストライブラリで、Selenium WebDriverのGroovyラッパーになっています。 最近Geb 0.10がリリースされたので、言語面における新機能を紹介します。ビルドツール連携やBrowserStack連携が強化されていますが、その紹介はまた別の機会に。

Geb 0.10の新機能

  • CSSへのアクセスが容易になった
  • 兄弟要素や子要素へのアクセスが容易になった
  • クリック後に非同期処理が実行されるオブジェクトにwaitを指定できるようになった

CSSへのアクセスが容易になった

PageObjectだったり、直接取得したようなNavigator(いわゆるDOM要素)に適用されているcssの値を取得できるようになりました。 基本的には

Navigator.css("cssのプロパティ名")

のような感じです。 下記のイメージ。

    def "対象のDOMに適用されているCSSにアクセスする"(){
        given:"Topページにアクセスする"
        to TopPage
        when:"適用されているCSSを取得する"
        def font = $("input", name:"j_username").css("font-family")
        def color = $("input", name:"j_username").css("background-color")
        then:"ヘッダ用のフォントと色が適用されている"
        // 実際にはこういったものは共通化しておくけど、説明のために
        font == "\"Helvetica Neue\",Helvetica,Arial,sans-serif"
        color == "rgba(255, 255, 255, 1)"
    }

この遷移をしたら、このような見た目があたっていてほしい。というのは共通的に書いておくと、ちょこっと便利です。

兄弟要素や子要素へのアクセスが容易になった

PageObjectだったり、直接取得したようなNavigator(いわゆるDOM要素)の隣や子要素を取得するのが容易になりました。また、ある条件に合致する子要素という感じの取得もできます。 基本的には

  • Navigator.next()
  • Navigator.next("条件的な")
  • Navigator.nextAll()
  • Navigator.children()

のような感じです。詳細はNavigatorクラスのAPI一覧を見るとよいでしょう。

下記のイメージ。

    def "対象のDOMの兄弟にアクセスする"(){
        given:"Topページにアクセスする"
        to TopPage
        when:"兄弟要素を取得する"
        def userNameSiblings = $("input", id:"remember_me").next()
        then:"隣にはテキストで表示がある"
        userNameSiblings.text() == "Remember me"
    }

クリック後に非同期処理が実行されるオブジェクトにwaitを指定できるようになった

ボタンをクリックしたあとにはwaitFor {//処理}としたり、sleep();//処理としたりしていることがあると思いますが、これをPageObject側の定義に移す選択肢ができました。

object_name(toWait:true) { Navigator } のような感じで、toWaitとつけるとwaitします。toWaitにはwaitに指定するのと同じような値を指定できます。(trueとかGebConfig.groovyで指定したカテゴリなど)

class ExamplePage extends Page {
    static content = {
        helpButton(to: HelpPage, toWait: true) { $("button#help") } //page change is asynchronous, e.g. an ajax call is involved
    }
}

こうするとテストコード側で例えば、

    to ExamplePage
    helpButton.click()
    waitFor { at HelpPage }

だったのが、こうなります。

    to ExamplePage
    helpButton.click()

どちらでもいいとは思うので、好みの問題でしょうかね。でも、テストコード側だとDRYにならないという話もあるので、toWaitのほうがいいかもしれません。

まとめ

HTML系のテストは個人的には最近はもうaltJS的なやつで書いたほうがいいよなーとは思うのですが、Geb+Spockの便利さに負ける日々なので、こういった細かいテクニックをつかっていくのもいいかと思います。