Shoeisha Technology Media

CodeZine(コードジン)

記事種別から探す

Groovy製のSeleniumラッパーライブラリ「Geb」で、可読性の高いテストを書いてみよう

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2017/10/06 14:00

 今回はSeleniumのラッパーライブラリであるGebの紹介です。Gebは前回のSelenideと同様、Seleniumのラッパーライブラリの一つです。JVM上で動作する動的言語のGroovyで記述されており、Groovyの機能を利用した簡潔な記述が可能です。本記事では、Gebのメリットを簡単に紹介し、サンプルコードを利用しながら、Gebの基本的な記述、最近の動向やベストプラクティスをご紹介していきたいと思います。

目次
illustration by iwasawa
illustration by iwasawa

Geb概略

Gebの強み

 Gebは、前述の通りGroovyの言語機能を利用した簡潔な記述が強みです。GebのWebサイトにあるサンプルコードを見てみましょう。基本的な文法はJavaとほぼ同様です。

import geb.Browser

Browser.drive {
    go "http://myapp.com/login" // ①

    assert $("h1").text() == "Please Login" // ②
    $("form.login").with {  // ③
        username = "admin"
        password = "password"
        login().click()
    }

    assert $("h1").text() == "Admin Section"  // ④
}

 このサンプルコードは、次の処理を実装しています。

  1. http://myapp.com/login に遷移する。
  2. 遷移先のページのヘッダー(h1)のテキストが「Please Login」になっているかをチェックする。
  3. 画面上のログインフォームに、ユーザー名とパスワードを入力して、クリックする。
  4. 遷移先のページが「Admin Section」になっていることをチェックする。

 コードの簡潔さに驚く方もいらっしゃるかもしれません。このような簡潔な記述がGebのウリです。

 それぞれの要素をもう少し詳しく見ていきましょう。

jQueryのようにエレメントを取得できるNavigation API

 サンプル中の$("form.login")のとおり、jQueryのようにエレメントを取得できるAPIが用意されています。

 エレメントの指定の仕方も柔軟で、下記のように取得できます。

// CSS3のセレクタ
$("div.some-class p:first[title='something']")

// 要素、アトリビュート、インデックスを指定
$("h1", 2, class: "heading")

 また、取得したエレメントは、Javaに比べ簡単に加工することができます。

 例えば下記の例では、複数のdiv要素の中で、bというクラス名が付いているエレメントをフィルターしています。

$("div").find(".b")

柔軟なwait処理

 今はAjaxを利用した非同期通信が一般的になっていますが、その中で非同期に表示されるエレメントなどをSeleniumでwaitすることは骨が折れます。

 Gebでは下記のように簡潔にwaitを書くことができます。

 waitForに続く{}内に、waitの条件を記述します。なおGroovyでは、{}で囲まれた部分はクロージャーと呼び、処理のまとまりを記述することができます。

waitFor {
    $("p.status").text() == "非同期処理で表示される"
}

 waitの処理は変数に代入でき、同じwaitの処理を他でも使い回すことができます。下記の例では、waitしたエレメントを定義して、そこから次にテキストを取得して検証しています。

def dynamicParagraph = waitFor { $("p.dynamically-added") }
dynamicParagraph.text() == "Added dynamically!"

テスティングフレームワークとの親和性

 Gebは「ブラウザの自動化のフレームワーク」なので、テストで利用する際にはテスティングフレームワークとの統合が必要です。JUnitやTestNGだけでなく、CucumberやSpockと組み合わせて利用することができます。中でもSpockとの親和性は非常に高いので、Gebを利用する際にはぜひSpockの利用を合わせて検討するべきです。Spockを利用したコード例は下記になります。

import geb.Page
import geb.spock.GebSpec

class LoginSpec extends GebSpec {
    def "login to admin section"() {
        given: "ログインページに遷移していて"
        to LoginPage

        when: "ログインフォームに、ユーザー名とパスワードを入力し"
        loginForm.with {
            username = "admin"
            password = "password"
        }

        and: "ログインボタンをクリックすると"
        loginButton.click()

        then: "管理者ページに遷移する"
        at AdminPage
    }
}

 より表現力の増した読みやすいコードになっていると思います。このようなメリットがあることから、本記事の後半のサンプルコードもSpockで記述していきます。

マルチブラウザでの利用

 Gebはマルチブラウザでの利用を想定しており、Chrome、Firefox、Edgeをはじめとした様々なブラウザをサポートしています。また、リモートマシンでのテスト実行を行うリモートドライバーや、HTMLUnit with WebDriverといったヘッドレスブラウザもサポートしています。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 高橋 陽太郎(タカハシ ヨウタロウ)

     人材採用に関するサービスを提供する会社でプロセス改善やテスティングに邁進中の開発リーダー。その傍ら副業で企業へのSelenium導入をお手伝いしています。 Twitter: @PoohSunny GitHub: https://github.com/...

バックナンバー

連載:「日本Seleniumユーザーコミュニティ」のエキスパートが教えるSelenium最新事情
All contents copyright © 2005-2017 Shoeisha Co., Ltd. All rights reserved. ver.1.5