概要
初めまして。Qiita初投稿になります。
Selenium練習サイトを使って、テストケース記述言語(Gherkin / Gauge)を試してみましたので導入に至るまでの注意点や慣れるまでの感想など述べたいと思います。
導入
- Gherkinの場合
- 基本、本家Cucumberのサイトを参照してinstallを試みますが、何故か自分の環境(Eclipse [Version: 2020-12 (4.18.0)] です)では、Mavenのpom.xmlにgroupIDをio.cucumberを指定しても旨くJavaプロジェクトが作成できず、Mavenリポジトリで「cucumber」で検索して出現したものから、info.cukesのものを指定して旨くプロジェクトを作成できました。
他はSeleniumで必要なものを記述して、こんな感じ(dependenciesの中だけ)
- 基本、本家Cucumberのサイトを参照してinstallを試みますが、何故か自分の環境(Eclipse [Version: 2020-12 (4.18.0)] です)では、Mavenのpom.xmlにgroupIDをio.cucumberを指定しても旨くJavaプロジェクトが作成できず、Mavenリポジトリで「cucumber」で検索して出現したものから、info.cukesのものを指定して旨くプロジェクトを作成できました。
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-api</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm-deps</artifactId>
<version>1.0.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>1.2.6</version>
<scope>test</scope>
</dependency>
</dependencies>
次にマーケットプレイスで、Cucumber eclipse Pluginをインストールしておきます。
以上で、Eclipse環境下でGerkinを用いたテスト環境ができあがりました。
- Gaugeの場合
テストケースの作成
- GherkinではDSL、GaugeではMarkdownを書式として用いますので、いずれにしてもある程度の慣れは必要な点で、どちらが有利とは一概に言えないのではと感じました。
今回、Selenium練習サイトでテストする上での目的として、連泊数と人数、土日は週末料金の適用あり、場合によっては朝食やオプションプランを付けた上での合計宿泊料金が正しいかどうかの検証としてみました。
この手のe2eテストを自動化する上でのテスト目的設定は必要な事だと思います。
宿泊初日の曜日と連泊数とで週末への引っかかり方が決まると思いましたので、初日の曜日 / 連泊数 / 人数 / オプション(朝食・Early Check in / 観光プラン)の組み合わせ網羅を各書式(GherkinとGauge)でシナリオアウトライン(Gherkin)あるいはテーブル(Gauge)で記述する試みをしました。
組み合わせはPictmasterを用いて生成してから、各テーブルにチマチマ書き直しましたが、このあたりは自動化の余地ありですね。 - Gherkinでは、Featureファイルにこんな感じで記述します。(抜粋)
シナリオアウトライン: 宿泊料金検証テストケース
もし 宿泊初日の曜日を<宿泊初日>として
もし "1"秒待つ
もし 連泊数選択をクリックして
もし 連泊数を<連泊数>にして
もし 宿泊人数を<宿泊人数>にして
もし 朝食バイキング有無を<朝食>にして
もし 昼からチェックインプランを<昼からチェックインプラン>にして
もし お得な観光プランを<お得な観光プラン>にして
もし 氏名を<氏名>として
もし 予約内容を記録して
もし 利用規約に同意して次へボタンをクリックする
ならば 合計金額は<合計金額>となり
ならば 宿泊期間の表示が正しく
ならば 宿泊人数の表示が<宿泊人数>名様となり
ならば 追加プランが<朝食>または<昼からチェックインプラン>または<お得な観光プラン>で正しく
ならば 氏名の表示が<氏名>様となり
もし 確定ボタンをクリックする
ならば ポップアップ表示に"ご来館、心よりお待ちしております。"が表示され
もし HOMEボタンをクリックする
例:
|宿泊初日 |連泊数|宿泊人数|朝食 |昼からチェックインプラン|お得な観光プラン|氏名 |合計金額|
|"Monday" |"1" |"1" |"off"|"off" |"off" |"武田晴信"|"7000"|
|"Monday" |"2" |"8" |"on" |"on" |"on" |"真田昌虎"|"144000"|
|"Monday" |"3" |"9" |"off"|"off" |"on" |"山本寛太"|"198000"|
|"Monday" |"5" |"2" |"on" |"on" |"off" |"上杉景虎"|"82000"|
|"Monday" |"9" |"2" |"on" |"on" |"off" |"直江愛子"|"153000"|
|"Tuesday" |"1" |"9" |"on" |"on" |"on" |"武田晴信"|"90000"|
|"Tuesday" |"2" |"2" |"off"|"on" |"on" |"真田昌虎"|"32000"|
|"Tuesday" |"3" |"1" |"on" |"off" |"off" |"山本寛太"|"24000"|
|"Tuesday" |"5" |"9" |"off"|"off" |"off" |"上杉景虎"|"330750"|
|"Tuesday" |"9" |"8" |"off"|"off" |"on" |"直江愛子"|"540000"|
|"Wednesday"|"1" |"2" |"on" |"on" |"on" |"武田晴信"|"20000"|
|"Wednesday"|"2" |"2" |"on" |"on" |"off" |"真田昌虎"|"34000"|
|"Wednesday"|"3" |"8" |"on" |"off" |"on" |"山本寛太"|"200000"|
|"Wednesday"|"5" |"1" |"off"|"on" |"off" |"上杉景虎"|"39500"|
|"Wednesday"|"9" |"9" |"on" |"on" |"on" |"直江愛子"|"697500"|
|"Thursday" |"1" |"2" |"off"|"off" |"on" |"武田晴信"|"16000"|
|"Thursday" |"2" |"1" |"on" |"on" |"off" |"真田昌虎"|"17000"|
|"Thursday" |"3" |"8" |"off"|"off" |"off" |"山本寛太"|"182000"|
|"Thursday" |"5" |"9" |"on" |"on" |"off" |"上杉景虎"|"400500"|
|"Thursday" |"9" |"8" |"on" |"off" |"on" |"直江愛子"|"612000"|
|"Friday" |"1" |"8" |"off"|"off" |"on" |"武田晴信"|"64000"|
|"Friday" |"2" |"9" |"off"|"off" |"off" |"真田昌虎"|"141750"|
|"Friday" |"3" |"2" |"on" |"on" |"on" |"山本寛太"|"59000"|
|"Friday" |"5" |"8" |"off"|"off" |"off" |"上杉景虎"|"308000"|
|"Friday" |"9" |"1" |"on" |"on" |"on" |"直江愛子"|"79250"|
|"Saturday" |"1" |"1" |"off"|"off" |"off" |"武田晴信"|"8750"|
|"Saturday" |"2" |"2" |"off"|"off" |"off" |"真田昌虎"|"35000"|
|"Saturday" |"3" |"8" |"off"|"on" |"off" |"山本寛太"|"204000"|
|"Saturday" |"5" |"2" |"on" |"off" |"on" |"上杉景虎"|"89000"|
|"Saturday" |"9" |"9" |"on" |"on" |"on" |"直江愛子"|"729000"|
|"Sunday" |"1" |"9" |"on" |"on" |"on" |"武田晴信"|"105750"|
|"Sunday" |"2" |"1" |"on" |"off" |"off" |"真田昌虎"|"17750"|
|"Sunday" |"3" |"1" |"on" |"on" |"on" |"山本寛太"|"27750"|
|"Sunday" |"5" |"8" |"on" |"off" |"on" |"上杉景虎"|"342000"|
|"Sunday" |"9" |"2" |"off"|"off" |"off" |"直江愛子"|"136500"|
GherkinのFeatureファイルには、シナリオを幾つも記述できますが、「例: 」と記述する部分はシナリオアウトラインの最後に記述するお作法のようです。
- Gaugeでは、specファイルにこんな感じで記述します。
# 予約ページ
==========================
宿泊初日の曜日と連泊数によって、週末料金アップ適用が異なる。オプションは別料金。連泊数・宿泊人数・オプションでトータル料金が決まる。
|宿泊初日 |連泊数|宿泊人数|朝食 |昼からチェックインプラン|お得な観光プラン|氏名 |合計金額|
|----------|------|-------|-----|-----------------------|---------------|----------|-------|
|Monday |1 |1 |off|off |off |武田晴信|7000|
|Monday |1 |1 |off|off |off |武田晴信|6000|
|Monday |2 |8 |on |on |on |真田昌虎|144000|
|Monday |3 |9 |off|off |on |山本寛太|198000|
|Monday |5 |2 |on |on |off |上杉景虎|82000|
|Monday |9 |2 |on |on |off |直江愛子|153000|
|Tuesday |1 |9 |on |on |on |武田晴信|90000|
|Tuesday |2 |2 |off|on |on |真田昌虎|32000|
|Tuesday |3 |1 |on |off |off |山本寛太|24000|
|Tuesday |5 |9 |off|off |off |上杉景虎|330750|
|Tuesday |9 |8 |off|off |on |直江愛子|540000|
|Wednesday|1 |2 |on |on |on |武田晴信|20000|
|Wednesday|2 |2 |on |on |off |真田昌虎|34000|
|Wednesday|3 |8 |on |off |on |山本寛太|200000|
|Wednesday|5 |1 |off|on |off |上杉景虎|39500|
|Wednesday|9 |9 |on |on |on |直江愛子|697500|
|Thursday |1 |2 |off|off |on |武田晴信|16000|
|Thursday |2 |1 |on |on |off |真田昌虎|17000|
|Thursday |3 |8 |off|off |off |山本寛太|182000|
|Thursday |5 |9 |on |on |off |上杉景虎|400500|
|Thursday |9 |8 |on |off |on |直江愛子|612000|
|Friday |1 |8 |off|off |on |武田晴信|64000|
|Friday |2 |9 |off|off |off |真田昌虎|141750|
|Friday |3 |2 |on |on |on |山本寛太|59000|
|Friday |5 |8 |off|off |off |上杉景虎|308000|
|Friday |9 |1 |on |on |on |直江愛子|79250|
|Saturday |1 |1 |off|off |off |武田晴信|8750|
|Saturday |2 |2 |off|off |off |真田昌虎|35000|
|Saturday |3 |8 |off|on |off |山本寛太|204000|
|Saturday |5 |2 |on |off |on |上杉景虎|89000|
|Saturday |9 |9 |on |on |on |直江愛子|729000|
|Sunday |1 |9 |on |on |on |武田晴信|105750|
|Sunday |2 |1 |on |off |off |真田昌虎|17750|
|Sunday |3 |1 |on |on |on |山本寛太|27750|
|Sunday |5 |8 |on |off |on |上杉景虎|342000|
|Sunday |9 |2 |off|off |off |直江愛子|136500|
## テスト開始
* 予約サイトを表示する
* Windowを最大化する
## テスト
-----------
* 宿泊初日の曜日を<宿泊初日>として
* "1"秒待つ
* 連泊数選択をクリックして
* 連泊数を<連泊数>にして
* 宿泊人数を<宿泊人数>にして
* 朝食バイキング有無を<朝食>にして
* 昼からチェックインプランを<昼からチェックインプラン>にして
* お得な観光プランを<お得な観光プラン>にして
* 氏名を<氏名>として
* 予約内容を記録して
* 利用規約に同意して次へボタンをクリックする
* 合計金額は<合計金額>となり
* 宿泊期間の表示が正しく
* 宿泊人数の表示が<宿泊人数>名様となり
* 追加プランが<朝食>または<昼からチェックインプラン>または<お得な観光プラン>で正しく
* 氏名の表示が<氏名>様となり
* 確定ボタンをクリックする
* ポップアップ表示に"ご来館、心よりお待ちしております。"が表示され
* HOMEボタンをクリックする
テーブルを記述する場所がGherkinと違っているのが判ります。
Gaugeでは、最初の見出し(# 予約ページ)と次の見出し(## テスト開始)との間に置きます。
あと、「""」で括るGherkin、括らないGauge、|--------|--------| こんな仕切り線みたいのが不要なGherkin、必要なGauge と、微妙な仕様の違いが認められました。慣れれば特に問題にはならないかと考えます。
Gherkinでは、検証自体を「ならば」で始まるテストケース記述をしましたが、Gaugeでは、パッと見わからないです。全テストケースの内、テストに至るまでの過程なのかテストそのものなのかをメトリクス収集する場合には、Gaugeでは末尾に「期待通り」とか書き添えるといいように思います。
テストコードの作成
共にJavaでテストコードを書きましたが、GherkinではStepDefinition.javaにFeatureファイルに記載したテストケースに対応したコードを全て記述する仕様なのに対して、GaugeではStepImplementation.javaにテストに至るまでの操作、VerifyImplementation.javaに検証だけ、specファイルの内容に対応した記述を、それぞれ分けて記述できる点で、Gaugeは良く出来ている感あります。
アノテーションもspecファイル前後・specファイル内の個々のScenario前後など、用意されています。(あまり使いこなせていません。)
- Gherkinの場合はテストコードは、(StepDefinition.javaから抜粋)こんなふうです。
@ならば("宿泊人数の表示が\"([^\"]*)\"名様となり$")
public void testHeadCount(String headcount) throws InterruptedException {
String selector = "//*[@id=\"hc\"]";
assertTrue(connector.testTextX(selector, headcount));
}
ならば 宿泊人数の表示が<宿泊人数>名様となり
というFeatureファイル内のシナリオ実行に対する部分です。
実際にボタンをクリックしたり、画面から文字を取得して評価するようなテストコードは、別にテストクラスを記述して生成したインスタンス(connectorインスタンス)のメソッドで実行します。
"([^\"]*)" で、テストケースから変数 <宿泊人数> を受け取るお作法です。
SeleniumでWebDriverを用いたり、Appiumを使ったり、ChromeでMobile Emulatorを使ったり、英語モードにしたりは、テストクラスで自在に実装できて、StepDefinition.javaとテストクラスというシンプルな構成です。
- Gaugeの場合は、VS codeでSeleniumプロジェクトを作成した段階でDriver.java と Driverfactory.javaが作成され、ここにGherkin側で実装していたテストクラスを追加し、テストケースに呼応したStepImplementationとVerifyImplementationを実装することになります。
@Step("宿泊人数の表示が<headcount>名様となり")
public void testHeadCount(String headcount) throws InterruptedException {
String selector = "//*[@id=\"hc\"]";
assertTrue(connector.testTextX(selector, headcount));
}
こちらも* 宿泊人数の表示が<宿泊人数>名様となり
に対応した部分です。
「ならば」というのが「Step」になってしまいましたが、記述自体はVerifyImplementationに記述しますので、”検証”ということになります。
変数のやりとりも、テストケース・テストコード共に <宿泊人数> とか \ と記述することになり判りやすくなったと思います。
テスト実行と結果の確認
GherkinはEclipseでJUnitを利用、Gaugeはテストケースにテスト実行のリンクが付くのでそれを利用します。
Eclipseで利用するJUnitはお馴染みの successは緑・failは赤なのに対して、Gaugeでは実行中はどうなのか判りません。このあたり、IDEとしてはよくできているEclipseはさすがと思いますが、自動テスト中の経過観察が必須かと聞かれれば、VS codeでも良いような気がします。
EclipseもALL in ONEとかあるので、導入に際しての壁はさほど高くないように思うのですが、開発環境・IDEと言っただけで敬遠されるような場合、エディタならばVS codeから入るのも良いのかもしれません。
Gaugeには、Gherkinには無い(工夫次第で本当はできます)スクショの内包とレポート作成機能があります。
JUnitが使えないから結果を確認する手段は当然必要なのですが、デフォルトで用意されている点は、ちょっと驚きました。
こんなテスト結果がhtmlドキュメントとして生成されます。
テストケース内のテーブルの内、成功したテストは緑、エラーは赤。ここは同じですね。ありがたい。
緑色の部分をクリックして、下の方を見ると、
合計金額が間違っていなかったことが判ります。
意図的に違う金額を期待値とした場合は、赤色部分で確認できて、
その時のスクショもエラーメッセージと共に記録されています。
Gherkinの場合、JUnitでAssertエラーになって検出できるのですが、静止画はSeleniumのsnapshot機能をテストコードに記述する必要があるのと、エラーでスクショ撮るように仕込む必要がありますので、デフォルトで備わっているGaugeはよくできていると思いました。
総括
EclipseでもGaugeが使えるようになって欲しい。。。
だいぶ端折って比較評価の紹介となったこと申し訳ありません。
Gherkin Gauge それぞれ自動テストで使いたいFrameworkだと思います。Gauge歴が短いので、例えばAppiumで使うのはどうしたものか とか、まだまだ調査の余地有りと感じました。
Gherkin vs Gaugeと言うより、Eclipse vs VS codeの評価だったような気もしています。
スポーツカーと大衆車を比較するみたいなこと、そもそも必要なのか???
JiiraのようなツールではCucumberのサポートがあるようですし、一方、GaugeはTaikoと組み合わせて使い勝手よくなるような話も聞きます。
テスト現場で解決したいたこと、現場のスキル、手段を選ぶ際の材料は、Framework選択だけでは済まないのですが、本投稿がきっかけになれば幸いです。