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.
- 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 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 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
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