
はじめに
前回は、自動販売機を題材にして、BDDを用いたプロセスの「定式化(Formulation)」の部分までを説明しました。
今回は、「自動化(Automation)」の部分を説明します。

5. 自動化
前回の記事の「4. レビュー」まで、自動化については一切考えていませんでした。(BDDは自動化が目的ではないと第4回でお伝えした通りです。)
ここまできて初めて、自動化について考えます。
今回は、前回作成した以下のGherkin記法のシナリオをインプットにして自動化を行います。
Feature: 自動販売機
Scenario: 飲み物を買うと、飲み物代を引いた金額のお釣りが出る
Given 自動販売機がある
When 550 円を入れる
And 120 円の "コーラ" を選択する
Then "コーラ" が出てくる
And 430 円が出てくる
自動化の手順0. BDDのフレームワークを導入する
BDDで行うためのフレームワークを導入します。本記事では、
- プログラミング言語…Java
- フレームワーク…Cucumber
- ビルドツール…Maven
で臨みます。
また、IDEはIntelliJを使用しており、「Cucumber for Java」のプラグインがインストール済みです。記事中に載っている画像は全てIntelliJのスクリーンショットであることをご了承ください。
Cucumberの構造を理解する
Cucumberは以下の構造を作成して動かします。

Gherkin記法のシナリオとテストコードが分かれているのが、CucumberをはじめとしたBDDフレームワークの特徴です。
これにより、ビジネス関係者はGherkin記法のシナリオを見るだけで、どのような振る舞いを定義しているのか理解することができます。その際に、プログラミング特有のスキルは必要ありません。
CucumberのプロジェクトをCloneする
今回は、cucumber-java-skeletonのプロジェクトをCloneします。
Cloneの仕方とCucumberの実行の仕方についてはプロジェクトのReadmeをご覧ください。
テストが実行できることを確認する
GradleもしくはMavenを用いて、プロジェクトのReadmeに書いてある通りにテストを実行します。
例えばMavenの場合、以下のようにテストが実行できればOKです。初期状態ではテストが失敗するようになっています。

IDE上でフィーチャーファイルのテスト実行できることを確認する
GradleもしくはMavenでテスト実行すると、IDEのフィーチャーファイル上でCucumberの実行ができるようになっています。
今回はCloneしたプロジェクトにデフォルトで入っているmaven/src/test/resources/io/cucumber/skeleton/belly.featureのファイルを開いてみましょう。すると、以下の画像のようになっているはずです。

この中で、行番号の1行目もしくは3行目の右側についている三角形2つのアイコンをクリックします。すると、以下のようなウィンドウが出てくるはずです。この中の一番上にある「Run ‘〜〜’」をクリックすると、IDE上でCucumberのテストを実行できます。

実行後、以下の画像のような結果になればOKです。

不要なファイルおよび記述を削除する
実際のプロジェクトを記述する上で以下のファイルは不要なので、削除してください。
- maven/src/test/resources/io/cucumber/skeleton/belly.feature
- maven/src/main/java/io/cucumber/skeleton/Belly.java
- maven/src/test/java/io/cucumber/skeleton/StepDefinitions.java
以上で、Cucumberを用いてBDDの自動化を行う準備ができました。
自動化の手順1. フィーチャーファイルに記載する
新たにフィーチャーファイルを作成し、前回作成した以下のGherkin記法のシナリオを記載します。今回はmaven/src/test/resources/io.cucumber.vendormachine/vendormachine.featureというファイルを作成しました。
Feature: 自動販売機
Scenario: 飲み物を買うと、飲み物代を引いた金額のお釣りが出る
Given 自動販売機がある
When 550 円を入れる
And 120 円の "コーラ" を選択する
Then "コーラ" が出てくる
And 430 円が出てくる
自動化の手順2. フィーチャーファイルを実行し、失敗を確認する
「自動化の手順1」で作成したフィーチャーファイル上で、Cucumberの実行をします。
すると、以下のようにテスト失敗となるはずです。

この時点では失敗している状態が正解となります。なぜならばシナリオを記述しただけで、それぞれのステップに対する実装をしていないためです。
なお、上のテスト失敗時の画像では、以下のようなテスト実行ステータスになっています。
Feature: 自動販売機
Scenario: 飲み物を買うと、飲み物代を引いた金額のお釣りが出る
Given 自動販売機がある //←テスト失敗
When 550 円を入れる //←実行スキップ
And 120 円の "コーラ" を選択する //←実行スキップ
Then "コーラ" が出てくる //←実行スキップ
And 430 円が出てくる //←実行スキップFeature: 自動販売機
Scenario: 飲み物を買うと、飲み物代を引いた金額のお釣りが出る
Given 自動販売機がある //←テスト失敗
When 550 円を入れる //←実行スキップ
And 120 円の "コーラ" を選択する //←実行スキップ
Then "コーラ" が出てくる //←実行スキップ
And 430 円が出てくる //←実行スキップ
自動化の手順3. ステップ定義ファイルを作成し、Givenステップの実装を行う
「自動化の手順1」で作成したフィーチャーファイルを開くと、以下のようになっています。

このうち、4行目から8行目の背景色がついている部分は、コンパイルエラーの状態を示しています。今回の場合、それぞれの行に対応するステップ定義がないためコンパイルエラーとなっています。
そこで、まずは4行目の「Given 自動販売機がある」に対するステップ定義を作成します。
「自動販売機がある」の文章上にカーソルを持っていくと、ヒントとなる豆電球のアイコンが出てきます。
豆電球のアイコンをクリックし、「Create step definition」をクリックします。

すると、ステップ定義ファイルの作成ウィンドウが出てきますので、適当なファイルを作成します。
今回は、ファイル名を「VendorMachineDefinitions」、ファイルパスを「maven/src/test/java/io/cucumber/skeleton」としました。

ウィンドウの「OK」ボタンを押すと、以下の画像のようなmaven/src/test/java/io/cucumber/skeleton/VendorMachineDefinitions.javaファイルが自動作成されるはずです。

ここまで行ったらもう一度、「自動化の手順1」で作成したフィーチャーファイル上で、Cucumberの実行をします。
すると、前回とテスト結果が少し異なっているのが分かるでしょうか。

ステップ定義ファイル作成前のテスト結果

ステップ定義ファイル作成後のテスト結果
ステップ定義ファイル作成前では「自動販売機がある」の部分でテスト失敗になっており「550円を入れる」は実行スキップとなっていました。
一方ステップ定義ファイル作成後では「自動販売機がある」の部分は表示されず、「550円を入れる」の部分でテスト失敗になっています。
これは、「自動販売機がある」の部分のテストが成功しており、次のステップである「550円を入れる」のステップ定義が見つからないためテスト失敗となっていることを示しています。
自動化の手順4. Givenの中身を実装する
ステップ定義ファイルおよびメソッドを作成しただけでは、具体的に実装ができていません。そこで、次に中身の実装を行います。
今回の場合、以下の画像のように記述します。現時点ではVendorMachineクラスが無いにもかかわらず、まるで存在しているかのように書くのはTDDを書く時と似ていますね。

この時点ではコンパイルエラーが発生している状態になっていればOKです。
自動化の手順5. コンパイルエラーの解消を行う
「自動化の手順4」で発生していたコンパイルエラーの解消を行っていきます。
今回の場合、maven/src/main/java/io/cucumber/vendormachine/VendorMachine.javaを作成することでコンパイルエラーの解消を行いました。
自動化の手順6. Whenステップの実装を行う
先ほどまでと同様に、今度は「When 550 円を入れる」のステップの実装を行います。
豆電球のアイコンをクリックし、「Create step definition」をクリックします。
今回は先ほどの「Given 自動販売機がある」と同じファイル上にステップ定義の実装を行うため、「VendorMachineDefinitions(io.cucumber.skeleton)」を選択します。

すると、VendorMachineDefinitionsファイルは以下のようになります。(変数名はarg0からinsertedAmountに変更しました)

Tips
シナリオ記載時に「When 550 円を入れる」と、数値の前後に半角スペースを記載すると、Cucumberが自動的に数値の変数だと判断してくれます。
同様に「Then “コーラ” が出てくる」のように、用語を””で括ると、Cucumberが自動的に文字列の変数だと判断してくれます。
Whenの中身を実装する
Givenの時と同様に、TDDのような感覚で実装していきます。今回の場合、以下のようになります。

なお、Givenの時に生成したVendorMachineクラスを活用したいため、Given内のローカル変数だったvendorMachineをフィールド変数に変更しています。
そして、VendorMachineクラス内は以下のように変更します。

以下同様に、ステップ定義と実装を作成していきます。
おわりに
今回は「自動化(Automation)」として、BDDのフレームワークであるCucumberを用いた実装方法を紹介しました。
今回は説明しませんでしたが、BDDとしてのステップ定義を完成させた後は、より細かいテストを書いたり、実装部分のリファクタリングを行っていったりします。
その過程で色々と実装内容を変更することになるとは思いますが、今回のステップ定義を完成させておくことにより、外側の振る舞いは動くことを確認できるという安心感を持って変更することができます。これが、BDDやATDDの良さでもあります。
本連載「TDDとBDD/ATDD」も今回で最終回となります。今回は「自動化(Automation)」というプログラミング部分について説明していきましたが、BDDにおいて何よりも重要なのは「発見(Discovery)」で行うビジネス関係者との協調作業です。自動化のみを行って、Seb Roseに「開発アプローチは少しも BDD にはなっていません。」と言われないようにしましょう。
また、本連載をきっかけにBDDに興味を持った方は、ぜひThe BDD Booksシリーズをお読みいただければと思います。
The BDD Booksシリーズの書籍紹介ページは以下の通りです。
- 『The BDD Books – Discovery(邦訳:The BDD Books – Discovery Japanese Edition)』
- 『The BDD Books – Formulation(邦訳:The BDD Books – Formulation Japanese Editionはもうすぐ出版予定)』
- 『The BDD Books – Automation』はもうすぐ出版予定
それでは、BDDを通じてビジネス関係者と協調しながら、日々の業務を行ってみてください。
連載一覧
TDDとBDD/ATDD(1) TDDはテスト手法ではない
TDDとBDD/ATDD(2) 2種類のBDD
TDDとBDD/ATDD(3) BDDとATDDとSbE
TDDとBDD/ATDD(4) ツールとしてのBDDとプロセスに組み込まれたBDD
TDDとBDD/ATDD(5) BDDのプロセスその1「発見(Discovery)」と実例マッピング
TDDとBDD/ATDD(6) BDDのプロセスその2「定式化(Formulation)」とBRIEFの原則
TDDとBDD/ATDD(7) BDDのプロセスその3「自動化(Automation)」
【Sqripts編集部より】
風間裕也さんの連載記事『TDDの派生形!BDDやATDDとは何か? 概念からプロセスまで徹底解説!』はいかがでしたでしょうか。
読者のみなさまからの感想や今後の連載のリクエストをぜひお寄せください!
Sqriptsお問い合わせ、または公式XアカウントのDMでも受け付けています。

