Rails 实战 - Cucumber

从上周的文章 Rails 实战 - RSpec 了解到如何做单元测试,本文将介绍如何利用 Cucumber 来做行为驱动测试。
Rails 和 Cucumber
Rails 项目中使用 Cucumber,在 Gemfile 加入如下配置:
group :test do
gem 'cucumber-rails', :require => false
# database_cleaner is not required, but highly recommended
gem 'database_cleaner'
gem 'rspec-rails', '~> 3.1.0'
gem 'factory_girl_rails'
# Capybara's selenium driver to test javascript
gem 'selenium-webdriver'
end
安装 Gems:
$ bundle install
初始化 features 目录,features 目录下会生成文件 support/env.rb,此文件明确一些配置项:
$ rails generate cucumber:install
Factory Girl
在文章 Rails 实战 - RSpec 中编写的 Factories,在这里还是可以使用。
编写 Features
创建锻炼,选择分类,填写名称,单位,还可以附加图片
接着我们来编写 features/create_exercise.feature 来保证上面这个需求:
Feature: Create exercise
In order to add exercise
As an admin
I want to create it
Scenario: Create an exercise
Given there is an exercise category called "Sport"
And there is a logined admin
When I click "Exercises"
And I click "New Exercise"
And I select "Sport" of "Category" of form
And I fill in "Name" with "Football" of form
And I attach file "Image" with "features/resources/bread.png" of form
And I fill in "Unit" with "minute" of form
And I fill in "Calorie" with "10" of form
And I press "Create Exercise" of form
Then I should be on the exercise page
And see a message "Exercise was successfully created."
And see an exercise "Football"
And see an unit "minute"
终端中运行测试,我们还没有编写步骤定义,肯定会报错:
$ bin/cucumber features/create_exercise.feature
编写 Step Definitions
通过 features/step_definitions 编写步骤定义,不同 Feature 中描述的类似场景可以使用相同的步骤定义:
features/step_definitions/authentication_steps.rb
Given(/^I am on the login page$/) do
visit "/login"
end
Then(/^I should be on the page with "(.*?)"$/) do |name|
expect(page).to have_content(name)
end
Given(/^there is a logined admin$/) do
admin = FactoryGirl.create(:admin)
visit "/login"
fill_in(:username, :with => admin.username)
fill_in(:password, :with => admin.password)
click_button("Login")
end
features/step_definitions/common_steps.rb
When(/^I click "(.*?)"$/) do |link_name|
click_link(link_name)
end
Then(/^see a message "(.*?)"$/) do |message|
expect(page).to have_content(message)
end
features/step_definitions/form_steps.rb
When(/^I fill in "(.*?)" with "(.*?)" of form$/) do |name, value|
fill_in(name, :with => value)
end
When(/^I check "(.*?)" of form$/) do |name|
check(name)
end
When(/^I uncheck "(.*?)" of form$/) do |name|
uncheck(name)
end
When(/^I select "(.*?)" of "(.*?)" of form$/) do |value, name|
select(value, :from => name)
end
When(/^I attach file "(.*?)" with "(.*?)" of form$/) do |name, path|
attach_file(name, File.expand_path(path))
end
When(/^I press "(.*?)" of form$/) do |name|
click_button(name)
end
features/step_definitions/exercise_steps.rb
Given(/^there is an exercise called "(.*?)" in this category$/) do |exercise_name|
category = Category.last
FactoryGirl.create(:exercise, :name => exercise_name, :category => category)
end
Then(/^I should be on the exercises list page$/) do
expect(current_path).to eq(admin_exercises_path)
end
Then(/^I should be on the exercise page$/) do
exercise = Exercise.first
expect(current_path).to eq(admin_exercise_path(exercise))
end
Then(/^see an exercise "(.*?)"$/) do |exercise_name|
expect(page).to have_content(exercise_name)
end
Then(/^not see an exercise "(.*?)"$/) do |exercise_name|
expect(page).not_to have_content(exercise_name)
end
在 Rails 项目中实现相应的业务逻辑,终端中再次运行测试,就会看到测试通过:
$ bin/cucumber features/create_exercise.feature
Capybara
在上面编写测试步骤的过程中,可以看到 visit, fill_in, click_button, click_link 和 attach_file 这些方法都是由 Capybara 提供的,用来执行浏览器中的操作,如访问链接,填写表单,提交表单等。
含有 JavaScript 操作的测试
在 Gemfile 中包含有 selenium-webdriver,在运行包含有 JavaScript 操作的测试时,就会启动浏览器进行相应的测试,你需要做的就是在 Feature 中添加一个标记,如下:
@javascript
Feature: Tag foods
...