33

RubyTest::Unitassert_nothing_raised. Test::Unit已被MiniTest取代。为什么 MiniTest 的断言/期望没有与此类似的东西?例如,您可以期望must_raise但不能wont_raise

4

3 回答 3

50

MiniTest 确实assert_nothing_raised在它的 Test::Unit 兼容层中实现了,但在它自己的测试 (MiniTest::UnitMiniTest::Spec) 中它没有实现任何这样的测试。程序员争辩说,原因是,对任何东西的测试都不是对任何东西的测试。您永远不会期望在测试中引发任何事情,除非您正在测试异常。如果测试代码中发生意外(未捕获)异常,您将收到测试按良好顺序报告的异常,您将知道您遇到了问题。

例子:

require 'minitest/autorun'

describe "something" do
  it "does something" do
    Ooops
  end
end

输出:

Run options: --seed 41521

# Running tests:

E

Finished tests in 0.000729s, 1371.7421 tests/s, 0.0000 assertions/s.

  1) Error:
test_0001_does_something(something):
NameError: uninitialized constant Ooops
    untitled:5:in `block (2 levels) in <main>'

1 tests, 0 assertions, 0 failures, 1 errors, 0 skips

这正是您想知道的。如果您期望什么都不会被提高,那么您就没有得到它,而且您已经被告知了。

所以,这里的论点是:不要使用assert_nothing_raised!这只是一个没有意义的拐杖。参见,例如:

https://github.com/seattlerb/minitest/issues/70

https://github.com/seattlerb/minitest/issues/159

http://blog.zenspider.com/blog/2012/01/assert_nothing_tested.html

另一方面,显然assert_nothing_raised对应于用户之间的一些直觉,因为很多人都希望 awont_raisemust_raise等一起使用。特别是有人希望将断言集中在这一点上,而不仅仅是测试。幸运的是,MiniTest 非常简约和灵活,所以如果你想添加自己的例程,你可以。因此,您可以编写一个方法来测试无异常并在没有异常时返回已知结果,现在您可以断言该已知结果。

例如(我不是说这是完美的,只是展示这个想法):

class TestMyRequire < MiniTest::Spec
  def testForError # pass me a block and I'll tell you if it raised
    yield
    "ok"
  rescue
    $!
  end
  it "blends" do
    testForError do
      something_or_other
    end.must_equal "ok"
  end
end

关键不是这是一个好主意还是坏主意,而是 MiniTest 从来没有责任为您做这件事。

于 2012-09-19T16:48:34.290 回答
11

如果你需要它:

# test_helper.rb

module Minitest::Assertions
  def assert_nothing_raised(*)
    yield
  end
end

并使用它:

def test_unknown_setter
  assert_nothing_raised do
    result.some_silly_column_name = 'value'
  end
end
于 2015-05-11T08:40:21.243 回答
3

这让我很困扰,以至于我深入研究了 MiniTest 源代码并在我的spec_helper.rb文件中提供了一个实现:

module MiniTest
  module Assertions
    def refute_raises *exp
      msg = "#{exp.pop}.\n" if String === exp.last

      begin
        yield
      rescue MiniTest::Skip => e
        return e if exp.include? MiniTest::Skip
        raise e
      rescue Exception => e
        exp = exp.first if exp.size == 1
        flunk "unexpected exception raised: #{e}"
      end

    end
  end
  module Expectations
    infect_an_assertion :refute_raises, :wont_raise
  end
end 

希望这对同样需要的其他人有所帮助wont_raise。干杯! :)

于 2015-09-01T15:52:31.323 回答