Child < Parent < Test::Unit::TestCase

I just ran into a problem with Test::Unit exhibited by the two files
below and the output of ‘ruby tc_child.rb’:

— tc_child.rb —
require ‘tc_parent’

class ChildTest < ParentTest
def test_one
puts ‘test_one called’
assert true
end
end
— tc_child.rb —

— tc_parent.rb —
require “test/unit”

class ParentTest < Test::Unit::TestCase
def setup
puts ‘setup called’
end

def teardown
puts ‘teardown called’
end
end
— tc_parent.rb —

ruby tc_child.rb
Loaded suite tc_child
Started
setup called
test_one called
teardown called
.setup called
Fteardown called

Finished in 0.004709 seconds.

  1. Failure:
    default_test(ParentTest) [tc_child.rb:4]:
    No tests were specified.

2 tests, 2 assertions, 1 failures, 0 errors

So apparently it’s inadvisable to insert a class between
Test::Unit::TestCase and a ‘leaf node’ test class. In my case, I ended
up moving the base functionality into a module that I mixed into
tc_child.rb, and this actually worked better for what I’m trying to
accomplish. The flexibility of modules is a great feature of Ruby.

Is there a way to instruct Test::Unit to not attempt to run tests in
intermediate classes in the hierarchy?

Brian A.

On 10/12/07, Brian A. [email protected] wrote:

Is there a way to instruct Test::Unit to not attempt to run tests in
intermediate classes in the hierarchy?

Hi Brian,

I don’t know if it’s advisable or not, but one way is to undefine
`default_test’.

require ‘test/unit’

class AbstractTestCase < Test::Unit::TestCase
undef_method :default_test
end

class ConcreteTestCase < AbstractTestCase
def test_foo
assert true
end
end

Having said that, unless you really need class inheritance for
something, it’s probably cleaner just to #include mixins.

Regards,
George.

On Oct 11, 11:49 pm, George [email protected] wrote:

class AbstractTestCase < Test::Unit::TestCase
undef_method :default_test
end

Thanks! I just looked through testcase.rb, and your suggestion seems
to be exactly what I was asking for. I’m satisfied with the mixin
approach for my current scenario, but it’s nice to know I have an
option for inheritance if the need arises.

Another option is to just hide the class from ObjectSpace :slight_smile: I did
some experimenting for the heck of it and came up with the following.
It’s just a hack for fun, but can anyone come up with a better way of
passing in the class to be hidden to the redefined each_object method
besides the ugly $cloaked global variable? The fact that the
definition is being evaluated in the scope of the metaclass for
ObjectSpace kind of complicates things.

require “test/unit”

class Module
$cloaked = []
def hide_class
$cloaked << self
end
end

class << ObjectSpace
alias orig_each_object each_object
def each_object(klass)
ObjectSpace.orig_each_object(klass) do |obj|
yield obj if !$cloaked.include?(obj)
end
end
end

class ParentTest < Test::Unit::TestCase
hide_class

def setup
puts ‘setup called’
end

def teardown
puts ‘teardown called’
end
end

On Oct 12, 2:48 am, Brian A. [email protected] wrote:

Another option is to just hide the class from ObjectSpace :slight_smile: I did
some experimenting for the heck of it and came up with the following.
It’s just a hack for fun, but can anyone come up with a better way of
passing in the class to be hidden to the redefined each_object method
besides the ugly $cloaked global variable? The fact that the
definition is being evaluated in the scope of the metaclass for
ObjectSpace kind of complicates things.

require “test/unit”

Using a Module class variable helps a bit, but it still doesn’t feel
right. Of course, that’s likely because it’s way too late and my brain
shut off a couple hours ago :frowning:

class Module
def hide_class
Module.cloaked << self
end

def Module.cloaked
@@cloaked ||= []
end
end

class << ObjectSpace
alias orig_each_object each_object
def each_object(klass)
ObjectSpace.orig_each_object(klass) do |obj|
yield obj if !Module.cloaked.include?(obj)
end
end
end