How to inherit abstract unit tests in Ruby?

I have two unit tests that should share a lot of regular tests with slightly different settings. If I write something like

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 

then Concrete1 doesn't seem to inherit the tests from Abstract. Or at least I can't get them to work in an eclipse. If I select Run All Test Tables for a file containing Concrete1, then Abstract is executed, although I do not want it to be. If I specify Concrete1, then it will not perform any tests at all! If I specify test_1 in Concrete1, then he complains that he cannot find it ("uncaught throw: invalid_test (ArgumentError)").

I am new to Ruby. What am I missing here?

+2
source share
2 answers

The problem is that, as far as I can tell, Test::Unit keeps track of which classes inherit from Test::Unit::TestCase , and, as a result, will only run tests from classes that directly inherit from it.

The way around this is to create a module with the tests you need, and then include this module in classes that come from 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 

Output:

  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
+7
source

The problem is that Test::Unit::TestCase does not explicitly run the tests defined in superclasses by default. In particular, note that TestSuiteCreator does not run tests if Test::Unit::TestCase#valid? does not return 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 

And what determines if a test case is valid? The default test is valid by default if this class explicitly defined this method or if the method was defined in 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 

Basically, if you subclass another unit test class, and you want to run the tests of the superclass module, you can:

  • Override those testing methods in your subclass and ask them to call your superclass testing method.
  • Move all your methods to the module (as explained in another answer in this thread)
  • Override the valid? method valid? in your subclass to return true:

def valid? return true end

+1
source

Source: https://habr.com/ru/post/1391362/


All Articles