Cucumber是一個用來做BDD( Behavior Driven Design)的工具。你可以用自己的語言來寫場景(scenarios)和定義(definitions).
Capybara可以用來模擬用戶對瀏覽器(browser)的訪問。
下載和配置
下載cucumber到本地:
$gem install cucumber
創建好你的rails項目以後, 編輯 Gemfile 加上Cucumber:
group :development, :test do
gem "rspec-rails", ">= 2.0.1"
gem 'cucumber-rails'
gem 'database_cleaner'
end
創建你的測試
在你的Rails項目裏, Cucumber測試在 features文件夾下面的 .feature後綴文件裏。 可參考Cucumber目錄結構和執行過程
你可以創建一個 contact.feature 文件寫上一些場景(scenario):
Feature: Contact me
In order to get in touch
A visitor
Should send me a message by contact form
Scenario: Sends a contact message
Given I am on the contact page
And I fill in "contact visitor name" with "John"
And I fill in "contact visitor email" with "[email protected]"
And I fill in "contact subject" with "Hello"
And I fill in "contact message" with "Great post!"
When I press "Send message"
Then page should have notice message "Your message was successfully delivered."
* 注意縮進 ( 注: 是否應該是縮進2格? 上面代碼是縮進4格的)
場景(scenario)是由很多步驟(steps)組成的。
一個步驟(step)是一個驗證(validation)或者一個更簡單的測試(simple test).
開始運行cucumber命令:
$ bundle exec cucumber
將得到警告說步驟沒有定義:
cucumber_test$ bundle exec cucumber
Using the default profile...
Feature: Contact me
(....)
You can implement step definitions for undefined steps with these snippets:
Given /^I am on the contact page$/ do
pending # express the regexp above with the code you wish you had
end
Given /^I fill in "(.*?)" with "(.*?)"$/ do |arg1, arg2|
pending # express the regexp above with the code you wish you had
end
When /^I press "(.*?)"$/ do |arg1|
pending # express the regexp above with the code you wish you had
end
Then /^page should have notice message "(.*?)"$/ do |arg1|
pending # express the regexp above with the code you wish you had
end
這裏要用capybara模擬瀏覽器的訪問。
在 features/step_definitions/ 文件夾創建 navigation_steps.rb
require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "paths"))
Given /^I am on (.+)$/ do |page_name|
visit path_to(page_name)
end
When /^I go to (.+)$/ do |page_name|
visit path_to(page_name)
end
When /^I press "([^\"]*)"$/ do |button|
click_button(button)
end
When /^I click "([^\"]*)"$/ do |link|
click_link(link)
end
When /^I fill in "([^\"]*)" with "([^\"]*)"$/ do |field, value|
fill_in(field.gsub(' ', '_'), :with => value)
end
When /^I fill in "([^\"]*)" for "([^\"]*)"$/ do |value, field|
fill_in(field.gsub(' ', '_'), :with => value)
end
When /^I fill in the following:$/ do |fields|
fields.rows_hash.each do |name, value|
When %{I fill in "#{name}" with "#{value}"}
end
end
When /^I select "([^\"]*)" from "([^\"]*)"$/ do |value, field|
select(value, :from => field)
end
When /^I check "([^\"]*)"$/ do |field|
check(field)
end
When /^I uncheck "([^\"]*)"$/ do |field|
uncheck(field)
end
When /^I choose "([^\"]*)"$/ do |field|
choose(field)
end
Then /^I should see "([^\"]*)"$/ do |text|
page.should have_content(text)
end
Then /^I should see \/([^\/]*)\/$/ do |regexp|
regexp = Regexp.new(regexp)
page.should have_content(regexp)
end
Then /^I should not see "([^\"]*)"$/ do |text|
page.should_not have_content(text)
end
Then /^I should not see \/([^\/]*)\/$/ do |regexp|
regexp = Regexp.new(regexp)
page.should_not have_content(regexp)
end
Then /^the "([^\"]*)" field should contain "([^\"]*)"$/ do |field, value|
find_field(field).value.should =~ /#{value}/
end
Then /^the "([^\"]*)" field should not contain "([^\"]*)"$/ do |field, value|
find_field(field).value.should_not =~ /#{value}/
end
Then /^the "([^\"]*)" checkbox should be checked$/ do |label|
find_field(label).should be_checked
end
Then /^the "([^\"]*)" checkbox should not be checked$/ do |label|
find_field(label).should_not be_checked
end
Then /^I should be on (.+)$/ do |page_name|
current_path.should == path_to(page_name)
end
Then /^page should have (.+) message "([^\"]*)"$/ do |type, text|
page.has_css?("p.#{type}", :text => text, :visible => true)
end
在 features/support/ 文件夾 增加一個 support文件 paths.rb
module NavigationHelpers
def path_to(page_name)
case page_name
when /the home\s?page/
'/'
else
begin
page_name =~ /the (.*) page/
path_components = $1.split(/\s+/)
self.send(path_components.push('path').join('_').to_sym)
rescue Object => e
raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
"Now, go and add a mapping in #{__FILE__}"
end
end
end
end
World(NavigationHelpers)
再次跑一邊測試:
$ bundle exec cucumber
現在,你可以做代碼方面的事了。 寫 models, controllers, views, routes.
這兒是我的例子, 步驟定義的是簡單的瀏覽(navigation), 但你可以寫更復雜的測試, 要讓場景簡單,比如 When I fill contact form可以定義成這樣:
When /^I fill contact form$/ do
visit contact_form_path
fill_in('contact_visitor_name', :with => "John")
fill_in('contact_visitor_email', :with => "[email protected]")
fill_in('contact_subject', :with => "Hello")
fill_in('contact_message', :with => "Great post! Bye.")
click_button("Send message")
end
原文: http://loudcoding.com/posts/quick-tutorial-starting-with-cucumber-and-capybara-bdd-on-rails-project/