Rubyunit testing:在每次测试失败后运行一些代码

teardown执行之前,在Test::Unit中的rubyunit testing中断言失败后,是否有一些干净而优雅的方法来执行我的代码?

我正在进行一些自动GUI测试,并希望在出现故障后立即截取屏幕截图。

如果您使用的是1.9,请不要使用Test :: Unit :: TestCase作为基类。 对它进行子类化并覆盖#run_test进行救援,获取屏幕截图并重新加注:

 class MyAbstractTestCase < Test::Unit::TestCase def run_test( *args ) super(*args) rescue snapshot() raise end end 

或者,我认为这实际上是最简洁的方法,你可以使用before_teardown钩子:

 class MyTestCase < Test::Unit::TestCase add_teardown_hook do |tc| screenshot() unless tc.passed? end end 

这不适用于1.8的测试/单位,但最小的是1.9。

那么你可以扩展Test::Unit::Assertions来做你喜欢的事情,我认为没有内置的方法来做到这一点。 也许是这样的(快速和肮脏):

 require 'test/unit' module Test::Unit::Assertions def safe_assert(test, msg=nil) passed = msg.nil? ? assert(test) : assert(test,msg) ensure puts 'take screenshot' unless passed end end class MyTest < Test::Unit::TestCase def setup puts 'setup' end def teardown puts 'teardown' end def test_something safe_assert true puts 'before failing assert' safe_assert false, "message" puts 'after failing assert' end end 

输出:

 Loaded suite unittest Started setup before failing assert take screenshot teardown F Finished in 0.001094 seconds. 1) Failure: test_something(MyTest) [unittest.rb:5]: message 1 tests, 2 assertions, 1 failures, 0 errors, 0 skips Test run options: --seed 58428 

编辑:您实际上可以通过更简单的方式将args传递给assert

 module Test::Unit::Assertions def safe_assert(*args) passed = assert(*args) ensure puts 'take screenshot' unless passed end end 

另外,如果您不经常需要此function,则可以在begin - ensure - end块中包装标准assert

 class MyTest < Test::Unit::TestCase def test_something safe_assert true puts 'before failing assert' begin passed = assert false, "message" ensure puts 'take screenshot' unless passed end puts 'after failing assert' end end 

或者您构建一个方法来确保屏幕截图,如下例所示。 这实际上对我来说似乎是最干净的方式:

 def screenshot_on_fail passed = yield ensure puts 'take screenshot' unless passed end class MyTest < Test::Unit::TestCase def test_something_else screenshot_on_fail do assert true end screenshot_on_fail do assert false, 'message' end end end