Cucumber到DRY实现相关测试中的RSpec自定义匹配器是否可能



我正在阅读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 }

相关内容

最新更新