2010-04-01 46 views
2

我有两个单元测试,应该用稍微不同的设置方法共享大量的常见测试。如果我写类似如何继承Ruby中的抽象单元测试?

class Abstract < Test::Unit::TestCase 
    def setup 
    @field = create 
    end 

    def test_1 
    ... 
    end 
end 

class Concrete1 < Abstract 
    def create 
    SomeClass1.new 
    end 
end 

class Concrete2 < Abstract 
    def create 
    SomeClass2.new 
    end 
end 

那么Concrete1似乎不会继承Abstract中的测试。或者至少我不能让他们在日食中运行。如果我为包含Concrete1的文件选择“运行所有TestCases”,则即使我不希望它运行,也会运行Abstract。如果我指定Concrete1,那么它根本不运行任何测试!如果我在Concrete1中指定test_1,那么它会抱怨它找不到它(“未捕获的throw:invalid_test(ArgumentError)”)。

我是Ruby的新手。我在这里错过了什么?

回答

7

的问题是,据我所知,Test::Unit跟踪哪些类从Test::Unit::TestCase继承,作为结果,将只有运行从类测试,从它直接继承

解决此问题的方法是创建一个模块,其中包含您想要的测试,然后包括该模块位于从Test::Unit::TestCase派生的类中。

require 'test/unit' 

module TestsToInclude 
    def test_name 
    assert(self.class.name.start_with?("Concrete")) 
    end 
end 

class Concrete1 < Test::Unit::TestCase 
    include TestsToInclude 

    def test_something_bad 
    assert(false) 
    end 
end 

class Concrete2 < Test::Unit::TestCase 
    include TestsToInclude 

    def test_something_good 
    assert(true) 
    end 
end 

输出:

 
Loaded suite a 
Started 
.F.. 
Finished in 0.027873 seconds. 

    1) Failure: 
test_something_bad(Concrete1) [a.rb:13]: 
<false> is not true. 

4 tests, 4 assertions, 1 failures, 0 errors 

shell returned 1 
+0

感谢 - 这是伟大的!它帮助我最终解决了在Rails功能(控制器)上下文中设置的http://stackoverflow.com/questions/8888614/how-to-write-and-inherit-from-an-abstract-subclass-of-actioncontrollertestcase,测试,因此有一点额外的挑战。 – 2012-01-26 00:24:48

+0

另一个观察:不幸的是,似乎这种方法不允许覆盖所包含的测试。如果测试类必须直接从Test :: Unit :: TestCase继承,那么ActiveSupport :: TestCase和ActionController :: TestCase如何直接从Test :: Unit :: TestCase继承,那么我们就需要另外一个破解来解决这个问题了:-( – 2012-01-26 00:37:27

+0

这对我没有意义。不会导致这个问题中描述的问题?它们不仅仅是Test :: Unit :: TestCase和具体类之间的继承关系吗? – 2012-10-10 19:52:00

1

问题是Test::Unit::TestCase明确不运行在默认情况下在超类定义的测试。尤其注意的是TestSuiteCreator不运行测试,除非Test::Unit::TestCase#valid?真(https://github.com/test-unit/test-unit/blob/2.5.5/lib/test/unit/testsuitecreator.rb#L40):

def append_test(suite, test_name) 
    test = @test_case.new(test_name) 
    yield(test) if block_given? 
    suite << test if test.valid? 
end 

什么确定测试用例是有效的?测试用例是默认有效的,如果在这个类明确定义的方法,或者如果该方法是在一个Modulehttps://github.com/test-unit/test-unit/blob/2.5.5/lib/test/unit/testcase.rb#L405-L418)定义:

def valid? # :nodoc: 
    return false unless respond_to?(@method_name) 
    test_method = method(@method_name) 
    if @internal_data.have_test_data? 
    return false unless test_method.arity == 1 
    else 
    return false unless test_method.arity <= 0 
    end 
    owner = Util::MethodOwnerFinder.find(self, @method_name) 
    if owner.class != Module and self.class != owner 
    return false 
    end 
    true 
end 

所以基本上,如果你继承另一个单元测试类,并且要运行超类的单元测试,您可以:

  • 重新定义你的子类的测试方法,让他们打电话给你的父类的测试方法
  • 把你所有的方法,以一个模块(如在对方的回答解释这个帖子)
  • 重新定义valid?方法在子类返回true:

def valid? return true end