我正在与Test :: Unit挣扎.当我想到单元测试时,我想到了每个文件的一个简单测试.但是在Ruby的框架中,我必须改为:
class MyTest < Test::Unit::TestCase def setup end def test_1 end def test_1 end end
但是每次调用test_*方法都会运行setup和teardown.这正是我不想要的.相反,我想要一个只为整个类运行一次的设置方法.但我似乎无法在不破坏TestCase初始化的情况下编写自己的initialize().
那可能吗?或者我是否使这无可救药地变得复杂?
正如Hal Fulton的书"The Ruby Way"中所提到的那样.他重写了Test :: Unit的self.suite方法,它允许类中的测试用例作为套件运行.
def self.suite mysuite = super def mysuite.run(*args) MyTest.startup() super MyTest.shutdown() end mysuite end
这是一个例子:
class MyTest < Test::Unit::TestCase class << self def startup puts 'runs only once at start' end def shutdown puts 'runs only once at end' end def suite mysuite = super def mysuite.run(*args) MyTest.startup() super MyTest.shutdown() end mysuite end end def setup puts 'runs before each test' end def teardown puts 'runs after each test' end def test_stuff assert(true) end end
这就是它应该如何工作!
每个测试应该与其余测试完全隔离,因此每个测试用例都会执行一次setup
和tear_down
方法.但是,有些情况下,您可能希望更多地控制执行流程.然后,您可以在套件中对测试用例进行分组.
在您的情况下,您可以编写如下内容:
require 'test/unit' require 'test/unit/ui/console/testrunner' class TestDecorator < Test::Unit::TestSuite def initialize(test_case_class) super self << test_case_class.suite end def run(result, &progress_block) setup_suite begin super(result, &progress_block) ensure tear_down_suite end end end class MyTestCase < Test::Unit::TestCase def test_1 puts "test_1" assert_equal(1, 1) end def test_2 puts "test_2" assert_equal(2, 2) end end class MySuite < TestDecorator def setup_suite puts "setup_suite" end def tear_down_suite puts "tear_down_suite" end end Test::Unit::UI::Console::TestRunner.run(MySuite.new(MyTestCase))
在TestDecorator
定义了一个特殊套件,它提供了一个setup
和tear_down
其前和一组包含的测试用例的运行后只运行一次的方法.
这样做的缺点是你需要告诉Test :: Unit如何在单元中运行测试.如果您的单元包含许多测试用例,并且您只需要其中一个的装饰器,则需要以下内容:
require 'test/unit' require 'test/unit/ui/console/testrunner' class TestDecorator < Test::Unit::TestSuite def initialize(test_case_class) super self << test_case_class.suite end def run(result, &progress_block) setup_suite begin super(result, &progress_block) ensure tear_down_suite end end end class MyTestCase < Test::Unit::TestCase def test_1 puts "test_1" assert_equal(1, 1) end def test_2 puts "test_2" assert_equal(2, 2) end end class MySuite < TestDecorator def setup_suite puts "setup_suite" end def tear_down_suite puts "tear_down_suite" end end class AnotherTestCase < Test::Unit::TestCase def test_a puts "test_a" assert_equal("a", "a") end end class Tests def self.suite suite = Test::Unit::TestSuite.new suite << MySuite.new(MyTestCase) suite << AnotherTestCase.suite suite end end Test::Unit::UI::Console::TestRunner.run(Tests.suite)
该测试::单位文档文件提供了有关如何套房工作一个很好的解释.
最后,测试单元实现了这一点!活泉! 如果您使用的是v 2.5.2或更高版本,则可以使用:
Test::Unit.at_start do # initialization stuff here end
当您开始测试时,这将运行一次.除了在每次测试(设置)之前运行的回调之外,还有在每个测试用例(启动)开始时运行的回调.
http://test-unit.rubyforge.org/test-unit/en/Test/Unit.html#at_start-class_method