3

我有两个单元测试应该共享很多常见的测试,但设置方法略有不同。如果我写类似

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 继承测试。或者至少我不能让它们在 Eclipse 中运行。如果我为包含 Concrete1 的文件选择“运行所有测试用例”,那么即使我不希望它运行 Abstract 也会运行。如果我指定 Concrete1,那么它根本不会运行任何测试!如果我在 Concrete1 中指定 test_1,那么它会抱怨找不到它(“uncaught throw :invalid_test (ArgumentError)”)。

我是红宝石的新手。我在这里想念什么?

4

2 回答 2

6

问题是,据我所知,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

输出:

加载套件a
开始
。F..
在 0.027873 秒内完成。

  1) 失败:
test_something_bad(Concrete1) [a.rb:13]:
<假> 不正确。

4 次测试,4 次断言,1 次失败,0 次错误

外壳返回 1
于 2010-04-01T22:45:30.650 回答
2

问题是Test::Unit::TestCase默认情况下明确不运行超类中定义的测试。特别要注意,除非返回 true(https://github.com/test-unit/test-unit/blob/2.5.5/lib/test/unit/testsuitecreator.rb#L40TestSuiteCreator,否则不会运行测试:Test::Unit::TestCase#valid?

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

什么决定了一个测试用例是否有效?Module如果此类明确定义了该方法,或者该方法在( https://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

于 2014-10-22T01:01:39.903 回答