为什么 MiniTest::Spec 没有wont_raise断言?


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

MiniTest确实在其Test::Unit兼容层中实现了assert_nothing_raised,但在其自己的测试(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对应于用户的一些直觉,因为很多人希望wont_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从来没有责任为您做这件事。

如果需要:

# 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

这让我很烦恼,以至于我不得不深入挖掘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的人有所帮助。干杯!:)

最新更新