Ruby单元测试:在每次测试失败后运行一些代码

时间:2012-03-23 12:12:29

标签: ruby unit-testing

Test::Unit执行teardown之前,{{1}}中的ruby单元测试失败的断言后,是否有一些干净而优雅的方法来执行我的代码?

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

2 个答案:

答案 0 :(得分:9)

如果您使用的是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。

答案 1 :(得分:3)

你可以扩展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

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

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

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

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