はじめに
これはGeb Advent Calendar 2016の17日目の記事です。
前日はGebでいきいき塾のページを自動化してみたでした。
Gebのアンチパターン
Seleniumもそうですが、何事も使う上ではアンチパターンと呼ばれるものがあります。今回は私がGebで書かれたコードを見る中で感じるアンチパターンをまとめてみました。
Seleniumというか、ブラウザ操作全般についてのアンチパターンといったものは省いています。Seleniumについてであれば、下記のエントリーが参考になります。
エレメントが隠蔽されずテストケースで利用されすぎる
例えばログインの自動化で、下記のようなコードがあったとします。1
Browser.drive {
to LoginPage
username.value("admin")
password.value("p4sw0rd")
loginButton.click()
assert page instanceof AdminPage
}
こちら、ログインするにはユーザーの入力欄と、パスワードの入力欄が必要で〜といった、ログイン画面の内容そのものをテストしたいのであれば話は別なのですが、ただ単にログインという処理は途中経過で、他の前提条件になるような場合であれば、まとまった処理はページオブジェクト内に隠蔽し下記のように書いたほうが良いです。
Browser.drive {
to LoginPage
login("admin", "p4sw0rd")
assert page instanceof AdminPage
}
こうすると、ログイン画面に何か変更があった際にも影響が少なくて済みます。
Gebはcontentが簡潔に書けてしまうので、ページオブジェクト内のcontentをついテストケース側で呼びがちになってしまうのですが、まとまった処理はなるべく隠蔽した方が良いですね。下記のスライドも参考になると思います。
パラメタライズの件数が多すぎる
例えばこんなケース、ログインに失敗した時にエラーメッセージが正しく出るかをチェックしています。
class LoginFailureSpec extends GebReportingSpec {
def "ログインに失敗した時に#errorMessageが表示される"() {
given: "ログインページにいる"
to LoginPage
at LoginPage
when: "ログインに失敗すると"
login("user-id", failurePassword)
then: "ページ遷移せず"
at LoginPage
and: "${errorMessage}というエラーメッセージが表示される"
message == errorMessage
where:
failurePassword || errorMessage
"wrong" || "ユーザーIDもしくはパスワードが間違っています"
"expired" || "パスワードの有効期間が切れています"
"locked" || "アカウントがロックされています"
}
}
これはGebと言うよりSpockの話なのですが、Unrollの昨日が強力すぎで、ついついパターンをUnrollでいっぱい書いてしまいがちになるのです。
ただ、当然ブラウザの自動化は実行時間がかかりますし、その他のレベルのテスト(ユニットテストなど)で担保したいものが満たせるのであれば、そちらでテストを書くことも検討しましょう。
Textでエレメント取得してしまう
これは古いバージョンだとって感じですが、過去エントリーで詳しく書きました。
画面のユニットテストになってしまう
これはコンテクストに強く依存するのでアンチパターンというかというと微妙だと思うのですが、例えば何かのボタンを押した際に、エレメントのクラス属性が変化するよね、みたいなテストをすることです。
近年だと、テストを標準装備で考えられたフロントエンドのフレームワークは山ほどあるので、そちらのテストでカバーできることはそちらでしたほうが良いと思います。
かくいう私も昔AngularJSでフロントエンドのコードを書いていて、細かい画面制御のテストをGebで書いて後で後悔したことがあります(のちに大部分はフロント側のユニットテストに移した)。Geb慣れてるしー、エレメント取得しやすいしー、Angular習得コスト高いし、とか言ってました本当にすいませんでした(懺悔)
まとめ
こう見てくると、目的をきちんと意識して、それにGebが一番フィットするときに使いましょうって話な気がしますね。
やってみないと気づかないことも多々あると思いますので、たまに自分たちのGebコードを振り返ってみてもいいかもしれません。