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 Adkins

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 10/12/07, Brian Adkins <lojicdotcom@gmail.com> wrote:

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

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 11, 11:49 pm, George <george.og...@gmail.com> wrote:

On 10/12/07, Brian Adkins <lojicdot...@gmail.com> 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

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

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"

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

···

On Oct 12, 2:48 am, Brian Adkins <lojicdot...@gmail.com> wrote:

On Oct 11, 11:49 pm, George <george.og...@gmail.com> wrote:
> On 10/12/07, Brian Adkins <lojicdot...@gmail.com> wrote:

class ParentTest < Test::Unit::TestCase
  hide_class

  def setup
    puts 'setup called'
  end

  def teardown
    puts 'teardown called'
  end
end