前回のおさらい
前回はCucumberの仕組みと概要について説明しました。
今回の記事では,実際にRailsアプリケーションに対してCucumberでテストを書いてみたいと思います。かなり基本的な説明になってしまいますが,手始めとしては十分だと思います。
準備
なにはともあれ,CucumberとRailsをインストールする必要があります。Cucumberはgemで公開されているのでgemコマンドを使ってインストールしましょう。cucumberは内部でWebratを使用しているのでこちらも合わせてインストールしましょう。
gem install cucumber webrat
次にRailsアプリケーションを作成し,cucumberでテストする準備を行います。script/generate cucumberを実行するといくつかファイルが作成されます。
rails cuke
cd cuke
ruby script/generate cucumber
作成されたファイルのうち,features/step_definitions/webrat_steps.rbというものがあるかと思います。これが前回説明したstepの定義が書かれているファイルです。基本的にstep_definitions以下にあるファイルはstep定義として読み込まれます。新しく自分でstepファイルを作成した場合もこのディレクトリ以下に保存します。
webrat_steps.rbは当然と言えば当然ですが日本語化されていません。せっかくのCucumberなのに,テストコードが英語では読む人も大変です。
ありがたいことに,諸橋氏が日本語のstepファイルを用意してくれるgem,misoを使用させて頂きましょう。
これで新たにfeatures/step_definitions以下にstepファイルが作成されたと思います。
実際に書く
あらかた準備が整ったところで,実際にテストコードをCucumberで書いてみたいと思います。ところで今までずっとテストコードと言ってきました。ですが,Cucumberではテストの単位にシナリオという言葉を使っています。そのため今後はテストコードではなく,テストシナリオと言っていきたいと思います。
当然ですが,Cucumberでテストシナリオを書くにあたって,どのようなアプリケーションを作るかを決めなくてはなりません。今回はあくまでCucumberのテストシナリオのサンプルとなればいいのでScaffoldで生成されるデータの入力部分をテストしてみましょう。入力するデータは「名前」「メールアドレス」「年齢」にしましょう。
では,まずはこれらの要件をテストシナリオに落しこみましょう。目指すべきゴールを最初にハッキリさせておくことはとても大事なことです。
ruby script/generate feature users
このコマンドでfeatures/manage_users.featureというファイルが作成されています。ここにテストシナリオを記述していきます。拡張子のfeatureはいくつかのテストシナリオを1つにまとめた単位のことです。例えば「ユーザを管理したい」がフィーチャとなり,その下に「ユーザの登録」や「ユーザの削除」といったテストシナリオがあるわけです。
ではさっそくmanage_users.featureにテストシナリオを記述していきましょう。ジェネレータで作成した場合,既にシナリオのサンプルが記述されていますが丸ごと消して新しく書き直してしまいましょう。サンプルは英語で記述されていましたが,全て日本語で問題ありません。
フィーチャ: ユーザを管理したい
シナリオ: ユーザの登録
前提 "ユーザ登録"ページを表示している
もし "email"に"example@example.com"と入力する
かつ "name"に"赤松 祐希"と入力する
かつ "age"に"22"と入力する
かつ "Create"ボタンをクリックする
ならば "User was successfully created."と表示されていること
かつ "example@example.com"と表示されていること
かつ "赤松 祐希"と表示されていること
かつ "22"と表示されていること
「前提」「もし」「ならば」はそれぞれ英語「Given」「When」「Then」と対応しています。「かつ」は「And」に対応しており,1つ前のstepと同じ扱いになります。この辺りの対応は以下の表のようになっています。
英語 | 日本語 |
Feature | フィーチャ |
Given | 前提 |
When | もし |
Then | ならば |
And | かつ |
But | しかし |
Examples | 例 |
では,先程のテストシナリオを実行してみましょう。
ruby script/cucumber -l ja
オプションは日本語を指定するためのものです。このオプションを指定しないと「前提」「もし」などが認識されず,テストシナリオが実行されません。
実行すると,まず1つ目のstepで「Can't find mapping from "ユーザ登録" to a path.」と言ったエラーが発生していると思います。これはCucumberが「ユーザ登録」が具体的にどこか判断できないために発生しているエラーです。まず,このエラーを発生させないために「ユーザ登録」がどこか設定する必要があります。
これらを設定するにはfeatures/support/paths.rbを編集する必要があります。ここではある文字列(ここでいうユーザ登録)がどのルーティングに対応するのかcase文で記述しています。
def path_to(page_name)
case page_name
when /ユーザ登録/
new_user_path
else
raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
"Now, go and add a mapping in #{__FILE__}"
end
end
現時点ではアプリケーションの作成を行なっていませんので,ここで指定したnew_user_pathというルーティングは存在しません。テストシナリオも書いたことなので,アプリケーションの作成にうつりましょう。とは言っても,今回はScaffoldを用いるため,簡単に終わらせてしまいます。
ruby script/generate scaffold user email:string name:string age:integer
rake db:migrate
rake db:test:prepare
今回作るアプリケーションはこれだけですので,この状態でテストシナリオを実行すれば全てグリーンになると思います。今回はScaffold前提になってしまったので,全てのstepがまとめてグリーンになりましたが,大抵は上から順に1つずつレッドからグリーンにしていく形になるはずです。
Ajaxのテスト
Cucumberは慣れてしまえば,フォームの入力や画面遷移程度であればテストシナリオを書くのは難しくありません。ですが,Ajaxで実装されているものは基本的にテストできないと思っていた方がよいでしょう。その場合は,適宜Seleniumを用いるか,JsonやXMLデータを出力するControllerのactionをRSpecでテストするなどの対応が求められます。
まとめ
今回,Cucumberのテストシナリオを書き,それらが正しく実行されるアプリケーション(Scaffoldですが)を作成しました。細かい部分は省いていますが,筆者が実際に仕事でアプリケーションを開発する流れとほぼ同じになっています。その一連の流れをなんとなくでも掴んで頂けたなら幸いです。