【问题标题】:How do I inherit abstract unit tests in Ruby?如何在 Ruby 中继承抽象单元测试?
【发布时间】:2010-04-01 22:19:06
【问题描述】:

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

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)”)。

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

【问题讨论】:

    标签: ruby unit-testing inheritance testunit


    【解决方案1】:

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

    【讨论】:

    • 谢谢 - 这太棒了!它帮助我最终解决了在 Rails 功能(控制器)测试的上下文中设置的stackoverflow.com/questions/8888614/…,因此有一点额外的挑战。
    • 另一个观察结果:不幸的是,这种方法似乎不允许覆盖包含的测试。我想需要另一个黑客来解决这个问题:-(
    • 这对我来说没有意义。如果测试类必须直接继承自Test::Unit::TestCase,那么ActiveSupport::TestCase和ActionController::TestCase如何不引起本题中描述的问题呢?它们不都只是 Test::Unit::TestCase 和具体类之间的额外继承级别吗?
    【解决方案2】:

    问题是Test::Unit::TestCase 默认情况下明确不运行超类中定义的测试。特别要注意TestSuiteCreator 不会运行测试,除非Test::Unit::TestCase#valid? 返回true (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
    

    什么决定了一个测试用例是否有效?如果该类显式定义了该方法,或者该方法在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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-11
      • 2011-04-07
      • 1970-01-01
      • 1970-01-01
      • 2020-05-31
      • 2018-10-19
      • 1970-01-01
      相关资源
      最近更新 更多