【问题标题】:How to force an RSpec test to fail?如何强制 RSpec 测试失败?
【发布时间】:2012-03-07 20:33:48
【问题描述】:

强制 RSpec 测试失败的正确方法是什么?

我正在考虑1.should == 2,但可能有更好的选择。

【问题讨论】:

  • 你到底想完成什么?

标签: ruby-on-rails testing rspec


【解决方案1】:

fail/raise 可以解决问题(它们是彼此的别名)。

示例

specify "this test fails" do
  raise "this is my failure message"
end

失败:

1) failing this test fails
   Failure/Error: raise "this is my failure message"

   RuntimeError:
     this is my failure message

替代方案

如果您正在考虑在规范中使用raise/fail,您应该考虑可能有更明确的方式来编写您的期望。

此外,raise/fail 不能很好地与aggregate_failures 配合使用,因为该异常会使块短路并且不会运行任何后续匹配器。

将测试标记为待处理

如果您需要将测试标记为待处理以确保您可以返回它,您可以使用fail/raise,但您也可以使用pending

# ? Instead of this:
it "should do something" do
   # ...
   raise "this needs to be implemented"
end

# ✅ Try this:
it "should do something" do
  pending "this needs to be implemented"
end

断言一个块没有被调用

如果您需要确保某个块没有被执行,请考虑使用yield matchers。例如:

describe "Enumerable#any?" do
  # ? Instead of this:
  it "doesn't yield to the block if the collection is empty" do
    [].any? { raise "it should not call this block" }
  end

  # ✅ Try this:
  it "doesn't yield to the block if the collection is empty" do
    expect { |b| [].any?(&b) }.not_to yield_control
  end
end

【讨论】:

  • fail 示例:it("is awesome") { fail "needs flamethrower" }
  • 我认为在最新版本的 rails / ruby​​ 中你实际上会使用 raise 而不是失败:it("is does a") { raise "it should do b" }
  • @frbl raisefail 是别名。所以,要么工作。使用一个或另一个是一种风格决定。
  • 这不适用于aggregateFailures — 异常突破了块。
  • 谢谢@DavidMoles!我更新了答案以包含该警告。
【解决方案2】:

我知道很多年前有人问过并回答过,但RSpec::ExampleGroups 有一个flunk 方法。我更喜欢这种flunk 方法,而不是在测试环境中使用fail。使用 fail 会导致代码失败(您可以在此处查看更多信息:https://stackoverflow.com/a/43424847/550454)。

所以,你可以使用:

it 'is expected to fail the test' do
  flunk 'explicitly flunking the test'
end

【讨论】:

  • 我相信这实际上是在Minitest::Assertions,它被rspec-rails包裹,而不是核心rspec
【解决方案3】:

如果你想模拟一个 RSpec 期望失败而不是一个异常,你要找的方法是RSpec::Expectations.fail_with

describe 'something' do
  it "doesn't work" do
    RSpec::Expectations.fail_with('oops')
  end
end

# => oops
#
# 0) something doesn't work
#    Failure/Error: RSpec::Expectations.fail_with('oops')
#      oops

请注意,尽管有文档,fail_with 实际上并没有直接引发ExpectationNotMetError,而是将它传递给私有方法RSpec::Support.notify_failure。这在使用aggregate_failures 时很方便,它(在后台)通过custom failure notifier 工作。

describe 'some things' do
  it "sometimes work" do
    aggregate_failures('things') do
      (0..3).each do |i|
        RSpec::Expectations.fail_with("#{i} is odd") if i.odd?
      end
    end
  end
end

# => some things
# 
# Got 2 failures from failure aggregation block "things":
# 
#   1) 1 is odd
# 
#   2) 3 is odd
# 
#   0) some things sometimes work
#      Got 2 failures from failure aggregation block "things".
# 
#      0.1) Failure/Error: RSpec::Expectations.fail_with("#{i} is odd") if i.odd?
#             1 is odd
# 
#      0.2) Failure/Error: RSpec::Expectations.fail_with("#{i} is odd") if i.odd?
#             3 is odd
#     sometimes work (FAILED - 1)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 2019-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多