views:

63

answers:

2

I encountered a problem when trying to test a module with Test::Unit. What I used to do is this:

my_module.rb:

class MyModule
  def my_func
    5 # return some value
  end
end

test_my_module.rb:

require 'test/unit'
require 'my_module'

class TestMyModule < Unit::Test::TestCase
  include MyModule

  def test_my_func
    assert_equal(5, my_func) # test the output value given the input params
  end
end

Now the problem is, if my_module declares an initialize method, it gets included in the test class and this causes a bunch of problems since Test::Unit seems to override/generate an initialize method. So I'm wondering what is the best way to test a module?

I'm also wondering wether my module should become a class at this point since the initialize method is made for initializing the state of something. Opinions?

Thanks in advance !

+3  A: 

Yeah, your initialize should definitely suggest that you're going towards a class. A module in ruby often feels like an interface in other languages, as long as you implement some basic things when you include the module you'll get a lot for free.

Enumerable is a great example, as long as you define [] and each when you include Enumerable you suddenly get pop, push, etc.

So my gut feeling about testing modules is that you should probably be testing classes that include the module rather than testing the module itself unless the module is designed to not be included in anything, it's simply a code storage mechanism.

Chuck Vose
+3  A: 

Including an initialize method in a module feels very wrong to me, so I'd rethink that at the very least.

To answer your question about testing this as a module more directly, though, I would create a new, empty class, include your module in it, create an instance of that class, and then test against that instance:

class TestClass
  include MyModule
end

class TestMyModule < Unit::Test::TestCase
  def setup
    @instance = TestClass.new
  end

  def test_my_func
    assert_equal(5, @instance.my_func) # test the output value given the input params
  end
end
Steve Madsen
Similarly, but more compactly, we use @instance = Class.new{ include MyModule }.new
Kyle