断言在Cucumber中抛出了一个特殊的exception
脚本
我正在写一个库(没有Ruby on Rails),我想要非常详细的Cucumberfunction。 这尤其包括描述在各种情况下应该抛出的错误/exception。
例
编写Cucumber步骤最直观的方法可能就是这样
When I do something unwanted Then an "ArgumentError" should be thrown
问题
我必须解决两个问题:
- 抛出exception时,第一步不应该失败。
- 第一步抛出的exception应该可以被第二步访问,以便做一些断言魔术。
不雅和繁琐的解决方案
我能够提出的最好方法是在第一步中缓存exception并将其放入第二步可以访问的实例变量中,如下所示:
When /^I do something unwanted$/ do begin throw_an_exception! rescue => @error end end Then /^an "(.*)" should be thrown$/ do |error| @error.class.to_s.should == error end
但是,在我不希望它失败的情况下,这使得第一步或多或少无用,并且它需要一个实例变量,这绝不是一件好事。
那么,任何人都可以帮助我解决至少不那么麻烦的解决方案吗? 或者我应该以不同的方式编写我的function? 任何帮助将非常感激。
我再一次想到了,也许答案是:
没有优雅的解决方案,因为在您的情况下违反了Given-When-Then -Scheme。 你期望“然后应该抛出exception”是“当我做一些不需要的东西”时的结果。
但是当你想到它时,这不是真的! exception不是此操作的结果,实际上exception只是显示“When”-Statement失败。
我的解决方案是在更高级别进行测试:
When I do something unwanted Then an error should be logged
要么
When I do something unwanted Then the user should get an error message
要么
When I do something unwanted Then the program should be locked in state "error"
或这些的组合。
然后你会在程序中“缓存exception” – 这很有道理,因为你最有可能需要这样做。
你所陈述的两个问题也将得到解决。
如果你真的必须测试exception
好吧,我猜黄瓜不是正确的测试套件,嗯? 😉
因为无论如何违反了Given-When-Then-Scheme,我只会写
When I do something unwanted it should fail with "ArgumentError"
并且在步骤定义中有类似的东西(未经测试,如果您尝试,请纠正我)
When /^I do something unwanted it should fail with "(.*)"$/ do |errorstring| expect { throw_an_exception! }.to raise_error(errorstring) end
如上所述,由于计划被打破,这是非常错误的,但它会达到目的,不是吗? 😉
您可以在rspec期望的测试错误中找到更多文档。
一种选择是使用@allow-rescue
标记场景并检查页面的输出和状态代码。 例如
在my_steps.rb
Then(/^the page (?:should have|has) content (.+)$/) do |content| expect(page).to have_content(content) end Then(/^the page should have status code (\d+)$/) do |status_code| expect(page.status_code.to_s).to eq(status_code) end Then /^I should see an error$/ do expect(400..599).to include(page.status_code) end
在my_feature.feature
@allow-rescue Scenario: Make sure user can't do XYZ Given some prerequisite When I do something unwanted Then the page should have content Routing Error And the page should have status code 404
或者:
@allow-rescue Scenario: Make sure user can't do XYZ Given some prerequisite When I do something unwanted Then I should see an error
这可能不是您所希望的,但对于遇到此页面的人来说,这可能是一种可接受的解决方法。 我认为它将取决于exception的类型,因为如果exception没有在任何级别获救,那么该方案仍将失败。 到目前为止,我主要使用这种方法来处理路由错误,这种方法运行良好。
可以在When
块中引发exception,然后在下面的Then
块中对它进行断言。
使用你的例子:
When /^I do something unwanted$/ do @result = -> { throw_an_exception! } end Then /^an "(.*)" should be thrown$/ do |error| expect{ @result.call }.to raise_error(error) end
该示例使用RSpec的匹配器,但重要的部分是->
(Lambda); 它允许引用throw_an_exception!
要传递的方法。
我希望有所帮助!
我是从在行为驱动的开发情况下使用Cucumberfunction的人的角度回答的,所以接受或离开它……
应编写方案来测试应用程序的“function”或function,而不是用于测试代码本身。 一个例子是:
When the service is invoked Then a success code should be returned
这听起来像你的测试用例(即如果我这样做,那么应该抛出这个exception)是unit testing或集成测试的候选者 – 在我的例子中,我们将使用一些模拟或unit testing框架。
我的建议是重新评估您的function方案,看看它们是否真的在测试您打算测试的内容。 根据个人经验,我发现如果我的测试类变得exception复杂,那么我的function是“错误的”。