我正在阅读Michael Hartl的新版"Rails教程",由于我非常喜欢Cucumber的BDD,我发现自己很担心作者在这里指出的内容:http://ruby.railstutorial.org/chapters/sign-in-sign-out?version=3.2#sec:rspec_custom_matchers
简而言之,Cucumber的主要问题是不可能像以下这样干燥依赖于实现的测试:
Then /^he should see an error message$/ do
page.should have_selector('div.alert.alert-error', text: 'Invalid')
end
像这样编写RSpec自定义匹配器:
RSpec::Matchers.define :have_error_message do |message|
match do |page|
page.should have_selector('div.alert.alert-error', text: message)
end
end
因为这样的自定义匹配器必须放在spec/support/utilities.rb中,并且可以从RSpec集成测试中调用,但不能从Cucumber步骤定义中调用。
你对此持肯定态度吗?
谢谢。
您当然可以创建RSpec匹配器,并在Cucumber步骤中使用它们——我经常这样做。我只需将它们放在features/support/matchers
中,它们就可以立即用于我的步骤定义中。
如果你也想与你的RSpec测试共享它们,你可能想将它们提取到一个单独的shared_test
类型位置,然后你可以在Cucumber env.rb文件和RSpec spec_helper.rb文件中require
这个文件夹,那么它们在两个测试框架中都可用。
您可以将依赖于实现或可重用的方法、定位器放在Cucumber World中。
您的场景示例:
# step_definitions/general_steps.rb
Then /^he should see an error message "(.+)"$/ do |text|
within(error_message) do
page.should have_content(text)
end
end
# support/general_helpers.rb
module GeneralHelpers
def error_message
page.first('div.alert.alert-error')
end
end
World(GeneralHelpers)
以下是一些关于这种方法的文章:
- 是时候收拾残局了:重构Cucumber步骤定义
- 使用黄瓜世界
Jon M的答案示例,说明如何在Cucumber中使用RSpec自定义匹配器:
# spec/support/matchers/http.rb
RSpec::Matchers.define :return_http_success do
match do |actual|
actual >= 200 && actual <= 299
end
end
# features/support/matchers.rb
Dir[Rails.root.join('spec/support/matchers/*.rb')].each { |file| require file }