地味だけどGebをgroovyにしている5Tips #SWTestAdvent


# はじめに

このエントリーは [ソフトウェアテストあどべんとかれんだー 2014](http://connpass.com/event/9500/) の9日目のエントリーです。
前日は[@urasandesu](https://twitter.com/urasandesu)さんの 『[非公開メソッドの入れ替え - from "Prig: Open Source Alternative to Microsoft Fakes" Wiki -](http://urasandesu.blogspot.jp/2014/12/from-prig-open-source-alternative-to.html)』でした。記事内の「迂廻路生成？と思われるかも」という言葉通り私も最初は？となりましたが、読み進めて行くとなるほど納得、以前レガシーコードと格闘していた私にはとても参考になるエントリーでした！

そして初めましての方は初めまして！ [@PoohSunny](https://twitter.com/PoohSunny)と言います。TDD、スクラム、ソフトウェアテスト、G*、AngularJSあたりに興味があります。現在は[カエルのマークの人事管理Saas](http://ja.huubhr.com/)作りに奮闘中です。
今日はGebというツールについて書きます。

# 前置き：Geb紹介
## Gebとは

![Screen Shot 2014-12-09 at 14.35.23.png](https://qiita-image-store.s3.amazonaws.com/0/5180/201891f4-d798-4e3b-8323-e600989f676e.png)

[プログラミング言語Groovy](http://groovy.codehaus.org/)を用いたWebアプリケーション向けの機能テストライブラリで、「じぇぶ」と読みます（「げぶ」ではない）。[本家のページ（英語）](http://www.gebish.org/testing)には、「とてもgroovyなブラウザオートメーション」と書かれてします(groovyって単語には、「魅惑的な」とか「すばらしい」などの意味があります。以下本エントリー中のgroovyという単語は同じ意味で使っています)。さまざまな説明やサンプルコードも本家のページにあります。ライセンスは[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html)です。

## 日本語の紹介記事
日本語でも既に紹介エントリーやスライドが多数あります。ここではリンクの紹介だけしておきます。

* [GebではじめるWebテスト 〜第1回 導入編〜](http://beta.mybetabook.com/showpage/4f27c8cc0cf26106dca875c8)
* [脱・独自改造！ GebでWebDriverをもっとシンプルに](http://www.slideshare.net/hirokotamagawa/20141018-2selenium-40423299)
* [【入門】Geb+SpockではじめるWebテスト](http://yfj2.hateblo.jp/entry/2014/10/26/164629)

# 今日のテーマ
Gebのホームページや上記エントリーを見ただけでも、「あ、Gebって良さそう！」って感じるかもしれませんが、実際使ってみると他にもいろいろとGebには地味な？便利機能があります。
今年一年、仕事でそこそこGebテストを書いてきた中で、いろんな「あーこれ地味だけどgroovyだわー」というのに出会ったので、それらを紹介します。
Gebを導入しようと思えたり、導入した際に使って見ようと思えたりしていただけるとハッピーです。

# 地味だけどGebをgroovyにしている5Tips
## 1.attribute取得時にマッチャーが使える

Gebの説明で真っ先に上がる良い点は、下記のようにJQueryライクな簡潔なAPIでwebのエレメントを取得できることです。

```Groovy
$("h1", text: "All about Geb")
$("div").find(".b")
```

で、この```text:XXX```の部分には、ただテキストを入れるだけではなく、マッチャーを使うことができます([参考リンク](http://www.gebish.org/manual/current/all.html#using_patterns))。
例えば、

```Groovy
$("p", text: contains("Geb"))
```

上記コードの場合は、テキストに「Geb」と入っているエレメントが全て取得されます。他にもcontainsとか、startWithがあり、時々お世話になります。ちなみに下記のように、

```Groovy
$("p", text: ~/p./).size() == 2
```
といったように正規表現も使うことができます。
とても便利ですが、反面意図しないエレメントを取得してしまう可能性があるので、その点ご注意ください。

Gebのドキュメントでは下記のような例を見つけました。

```Groovy
class GoogleResultsPage extends Page {
    static at = { waitFor { title.endsWith("Google Search") } }
...
```


## 2.waitの記述が楽
Gebでの基本的なwaitは

```Groovy
waitFor { 
    $("p.status").text() == "Asynchronous operation complete!"
}
```
というように```waitFor{ 条件 }```で記述できます。
私以前はJava - WebDriverで書いていたのですが、

```Java
wait.until(visibilityOfElementLocated(By.id("hoge"));
```
とか書いていた気がします。Gebだと同じことは

```Groovy
waitFor { $("div", id: "hoge").isDisplayed() } 
```
と書けます。見た目だいぶシンプルになったと思います。

もし[ページオブジェクトパターン](http://www.gebish.org/manual/current/intro.html#the_page_object_pattern)で記述しているのであれば、下記のように書くこともできます。

```Groovy
class IndexPage extends Page {
  static at = {
    title == "Top Page"
  }
  static content = {
    saveButton(wait: true) { $("button", class: "btn") }
  }
}
```
```saveButton```を利用する際、まだ表示されていなければ表示を待ってくれます。タイムアウトはGebConfigで設定したり、```(wait: 30)```のように引数で設定することもできます。

## 3.Cookieの自動クリア
Geb + Spockで使う時は、各メソッドの実行毎にCookieをクリアしてくれます([参考リンク](http://www.gebish.org/manual/current/configuration.html#auto_clearing_cookies))。変にキャッシュが残っていると、意図しない動作をすることがあるためです。
もちろん、自動でクリアをしてくれない方がいい場合もあって、その時は```GebCongif.groovy```にパラメーターを追加すればOKです。

```Groovy:GebConfig.groovy
autoClearCookies = false
```

さらに、Spockの```@Stepwise```アノテーションをテストにつけると、Cookieはクリアされなくなります。@Stepwiseをつけるということは、各ステップ毎に連続してテストをしたいケースでしょうから、こういった細かい気遣いは嬉しいです。

## 4.シンタックスシュガー
続いて、本当に地味だったけど、使って嬉しかったシンタックスシュガー２選。
### ボタンのdisableを取得
たとえば、ボタンのエレメントのdisableを取りたい！というときに、

```groovy
deleteSelectedButton.@disabled == 'true'
```

上記コードでとれます([参考リンク](http://stackoverflow.com/questions/6268575/how-to-use-geb-to-check-element-attribute-value-after-page-event))。

### sendkey

WebDriverで書くと、

```Java
driver.FindElement(By.Id("firstname"));
textbox1.SendKeys("Hello World");
```

と書くSendKeyイベントは、Gebだと

```groovy
$("input", id: "firstName").value("hoge")
```

と書けます。もっとサボるなら

```groovy
$("input", name: "firstName") << "hoge"
```
Groovyのファイルへの書き込みとかと一緒です([参考リンク](http://www.gebish.org/manual/current/navigator.html#sending_keystrokes))。

## 5.Cloud Browser Testing対応
Gebは各種WebDriverに対応しており、マルチブラウザ対応しています。それだけでなく、リモートドライバー対応しているので、リモートマシンでテスト実行が可能です([参考リンク](http://www.gebish.org/crossbrowser))。ここで面倒になるのが環境の構築やメンテです。その面倒を軽減するため、[SauceLabs](https://saucelabs.com/)や[BrowserStack](http://www.browserstack.com/)といった「remote web browsers as a service」があります。Gebはこれらのサービスを、```GebConfig.groovy```に追記して、Gradle pluginを入れることで比較的簡単に導入することができます([参考リンク](http://www.gebish.org/manual/current/cloud-browsers.html#cloud_browser_testing))。

弊社の場合、もう少し手抜きをしていて、[CloudBeesのDEV@cloud](https://www.cloudbees.com/products/dev)の、[Sauce OnDemand](https://www.cloudbees.com/documentation/sauce-ondemand-service-run-selenium-tests-devcloud)というサービスを使っています。```Build.gradle```に数行追加するだけ(+DEV@cloud側で設定が必要)ですが、テストの画面キャプチャ取得や実行動画の録画！を自動でしてるのでとても便利です。

# まとめに代えて
## いかがでした？
以上、結構マニアックなものを含めましたが、紹介してみました。Gebは細かいところに粋な気遣いがあったりするので、まだ未体験の人は是非一度触ってみてください！

## 明日は!?
[@shin_semiya](https://twitter.com/shin_semiya)さんです。「テストの量と重点化の方針について」とのことでわくわくしています。よろしくお願いします。