スタッフブログ
satoです。
テストと言えばユニットテストとかはだいぶ充実してきましたが、機械的なコードになりがちなので、プログラマ以外のテストケースの検証が難しいという問題があり、別途説明用にテストケースを書き直したりする必要がありました。
Ruby on Railsの話になりますが、Cucumberというツールがあるようです。
これは、YAMLで受け入れテストを書くことによって、Railsアプリのテストを行えるようにするものです。
ちなみにこれは正確にはBDD(Behavior Driven Development/ビヘイビア駆動開発)のためのツールらしいです。
Cucumberのページを開くと、以下のようなものが記述されています。
見た感じだとただの英文に見えます(YAMLっぽい部分が若干ありますが)が、Cucumberではこれをテストコードとして解釈して実行させることができます。
■インストール
CucumberはRails2.1以降で動作します。
でインストールできます。
また、別途
あたりをインストールしておくといいようです。
■テスト用プロジェクト作成
とりあえずブログアプリケーションのようなものを作る想定で作ります。
http://127.0.0.1:3000/entries/とかで、表示ができていることを確認してください。
■Cucumber初期化
で、いろいろ生成されます。
で、Entryに対するテストコードの雛形が生成されます。
features/manage_entries.feature
features/step_definitions/entry_steps.rb
このうち、manage_entries.featureが、実際のテストコードになります。このファイルを開くと以下のように書かれています。
Featureは、このテストシナリオ全体の内容を記載します。(Featureの直後に書いてあるのは概要のようなものです)
実際の動作は、各Scenarioに記述していきます。
とりあえずScenarioを書いてみます。
これで、
すると、以下のようにテストが実行されます。
passedとなっているので、正常終了しているようです。
試しに失敗させてみます。
app/controllers/entries_controller.rb
すると以下のようになると思います。
削除をコメントアウトしたので、削除の部分が失敗しているのがわかると思います。
このような感じでテストを書くことができるようになります。
英語だと若干わかりづらいのですが、有志の手によって一部を日本語で書けるようにしたものもあるようです(今回は省略します)。また、同時に生成されたstepファイル(今回だとentry_steps.rb)で、細かい実行内容の定義を書くことができます。これらを組み合わせることにより、自然な日本語でテストを書くことができるようにもなります。
従来のテストコードに比べて視認性が格段に良くなりますので、Railsで開発をしている方は是非試してみてください。
テストと言えばユニットテストとかはだいぶ充実してきましたが、機械的なコードになりがちなので、プログラマ以外のテストケースの検証が難しいという問題があり、別途説明用にテストケースを書き直したりする必要がありました。
Ruby on Railsの話になりますが、Cucumberというツールがあるようです。
これは、YAMLで受け入れテストを書くことによって、Railsアプリのテストを行えるようにするものです。
ちなみにこれは正確にはBDD(Behavior Driven Development/ビヘイビア駆動開発)のためのツールらしいです。
Cucumberのページを開くと、以下のようなものが記述されています。
Feature: Search courses
In order to ensure better utilization of courses
Potential students should be able to search for courses
Scenario: Search by topic
Given there are 240 courses which do not have the topic "biology"
And there are 3 courses A,B,C that each have "biology" as one of the topics
When I search for "biology"
Then I should see the following courses:
| title |
| A |
| B |
| C |
■インストール
CucumberはRails2.1以降で動作します。
gem install rspec rspec-rails cucumber webrat
また、別途
gem install term-ansicolor treetop diff-lcs nokogiri builder
■テスト用プロジェクト作成
とりあえずブログアプリケーションのようなものを作る想定で作ります。
rails blog
cd blog
script/generate scaffold entry name:string title:string body:text
rake db:migrate
■Cucumber初期化
script/generate cucumber
script/generate feature Entry
features/manage_entries.feature
features/step_definitions/entry_steps.rb
このうち、manage_entries.featureが、実際のテストコードになります。このファイルを開くと以下のように書かれています。
Feature: Manage entries
In order to [goal]
[stakeholder]
wants [behaviour]
Scenario: Register new entry
Given I am on the new entry page
And I press "Create"
Scenario: Delete entry
Given the following entries:
||
||
||
||
||
When I delete the 3rd entry
Then I should see the following entries:
||
||
||
||
実際の動作は、各Scenarioに記述していきます。
とりあえずScenarioを書いてみます。
Feature: Manage entries
In order to [goal]
[stakeholder]
wants [behaviour]
Scenario: Register new entry
Given I am on the new entry page
When I fill in "Name" with "user"
And I fill in "Title" with "blog title"
And I fill in "Body" with "blog content"
And I press "Create"
Then I should see "user"
And I should see "blog title"
And I should see "blog content"
Scenario: Delete entry
Given the following entries:
| name | title | body |
| name1 | title1 | body1 |
| name2 | title2 | body2 |
| name3 | title3 | body3 |
| name4 | title4 | body4 |
| name5 | title5 | body5 |
When I delete the 3rd entry
Then I should see the following entries:
| name | title | body |
| name1 | title1 | body1 |
| name2 | title2 | body2 |
| name4 | title4 | body4 |
| name5 | title5 | body5 |
rake features
すると、以下のようにテストが実行されます。
/usr/bin/ruby1.8 -I "/usr/lib/ruby/gems/1.8/gems/cucumber-0.3.11/lib:lib" "/usr/lib/ruby/gems/1.8/gems/cucumber-0.3.11/bin/cucumber" --format pretty features/manage_entries.feature
Feature: Manage entries
In order to [goal]
[stakeholder]
wants [behaviour]
Scenario: Register new entry # features/manage_entries.feature:6
Given I am on the new entry page # features/step_definitions/webrat_steps.rb:6
When I fill in "Name" with "user" # features/step_definitions/webrat_steps.rb:22
And I fill in "Title" with "blog title" # features/step_definitions/webrat_steps.rb:22
And I fill in "Body" with "blog content" # features/step_definitions/webrat_steps.rb:22
And I press "Create" # features/step_definitions/webrat_steps.rb:14
Then I should see "user" # features/step_definitions/webrat_steps.rb:93
And I should see "blog title" # features/step_definitions/webrat_steps.rb:93
And I should see "blog content" # features/step_definitions/webrat_steps.rb:93
Scenario: Delete entry # features/manage_entries.feature:16
Given the following entries: # features/step_definitions/entry_steps.rb:1
| name | title | body |
| name1 | title1 | body1 |
| name2 | title2 | body2 |
| name3 | title3 | body3 |
| name4 | title4 | body4 |
| name5 | title5 | body5 |
When I delete the 3rd entry # features/step_definitions/entry_steps.rb:5
Then I should see the following entries: # features/step_definitions/entry_steps.rb:12
| name | title | body |
| name1 | title1 | body1 |
| name2 | title2 | body2 |
| name4 | title4 | body4 |
| name5 | title5 | body5 |
2 scenarios (2 passed)
11 steps (11 passed)
0m1.040s
passedとなっているので、正常終了しているようです。
試しに失敗させてみます。
app/controllers/entries_controller.rb
def destroy
@entry = Entry.find(params[:id])
# @entry.destroy # ここをコメントアウト
respond_to do |format|
format.html { redirect_to(entries_url) }
format.xml { head :ok }
end
end
rake features
すると以下のようになると思います。
/usr/bin/ruby1.8 -I "/usr/lib/ruby/gems/1.8/gems/cucumber-0.3.11/lib:lib" "/usr/lib/ruby/gems/1.8/gems/cucumber-0.3.11/b
in/cucumber" --format pretty features/manage_entries.feature
Feature: Manage entries
In order to [goal]
[stakeholder]
wants [behaviour]
Scenario: Register new entry # features/manage_entries.feature:6
Given I am on the new entry page # features/step_definitions/webrat_steps.rb:6
When I fill in "Name" with "user" # features/step_definitions/webrat_steps.rb:22
And I fill in "Title" with "blog title" # features/step_definitions/webrat_steps.rb:22
And I fill in "Body" with "blog content" # features/step_definitions/webrat_steps.rb:22
And I press "Create" # features/step_definitions/webrat_steps.rb:14
Then I should see "user" # features/step_definitions/webrat_steps.rb:93
And I should see "blog title" # features/step_definitions/webrat_steps.rb:93
And I should see "blog content" # features/step_definitions/webrat_steps.rb:93
Scenario: Delete entry # features/manage_entries.feature:16
Given the following entries: # features/step_definitions/entry_steps.rb:1
| name | title | body |
| name1 | title1 | body1 |
| name2 | title2 | body2 |
| name3 | title3 | body3 |
| name4 | title4 | body4 |
| name5 | title5 | body5 |
When I delete the 3rd entry # features/step_definitions/entry_steps.rb:5
Then I should see the following entries: # features/step_definitions/entry_steps.rb:12
| name | title | body |
| name1 | title1 | body1 |
| name2 | title2 | body2 |
| name4 | title4 | body4 |
| name5 | title5 | body5 |
expected: "name4",
got: "name3" (using ==)
Diff:
@@ -1,2 +1,2 @@
-name4
+name3
(Spec::Expectations::ExpectationNotMetError)
./features/step_definitions/entry_steps.rb:16
./features/step_definitions/entry_steps.rb:15
(eval):3:in `each_with_index'
./features/step_definitions/entry_steps.rb:14:in `each'
./features/step_definitions/entry_steps.rb:14:in `each_with_index'
./features/step_definitions/entry_steps.rb:14
(eval):3:in `each_with_index'
./features/step_definitions/entry_steps.rb:13:in `each'
./features/step_definitions/entry_steps.rb:13:in `/^I should see the following entries:$/'
features/manage_entries.feature:25:in `Then I should see the following entries:'
2 scenarios (1 failed, 1 passed)
11 steps (1 failed, 10 passed)
0m0.884s
rake aborted!
Command failed with status (1): [/usr/bin/ruby1.8 -I "/usr/lib/ruby/gems/1....]
(See full trace by running task with --trace)
削除をコメントアウトしたので、削除の部分が失敗しているのがわかると思います。
このような感じでテストを書くことができるようになります。
英語だと若干わかりづらいのですが、有志の手によって一部を日本語で書けるようにしたものもあるようです(今回は省略します)。また、同時に生成されたstepファイル(今回だとentry_steps.rb)で、細かい実行内容の定義を書くことができます。これらを組み合わせることにより、自然な日本語でテストを書くことができるようにもなります。
従来のテストコードに比べて視認性が格段に良くなりますので、Railsで開発をしている方は是非試してみてください。