views:

122

answers:

3

I'm trying to include the unit tests for a module in the same source file as the module itself, following the Perl modulino model.

#! /usr/bin/env ruby

require 'test/unit'

module Modulino
    def modulino_function
        return 0
    end
end

class ModulinoTest < Test::Unit::TestCase
    include Modulino
    def test_modulino_function
        assert_equal(0, modulino_function)
    end
end

Now, I can run the unit-tests executing this source file.

But, they are also run when I require/load them from another script. How can this be avoided ?

Is there a more idiomatic way to achieve this with Ruby, unless this practice is discouraged ?

+8  A: 

Personally I've never heard of anyone trying to do this in Ruby. It's definitely not a standard practice. That said you may be able to leverage this trick:

if __FILE__ == $0
  # Do something.. run tests, call a method, etc. We're direct.
end

The code in the if block will only execute if the file is executed directly, not if it's required by another library or application.

More ruby tricks here: http://www.rubyinside.com/21-ruby-tricks-902.html

samg
I find it a handy way to work on (usually) small independent modules when they're still "young" - especially when I'm working in an editor within which I can execute immediately (like SciTE). It's obviously less of an issue where you have larger bodies of code and/or AutoTest. But I don't live in that world ;-)
Mike Woodhouse
Thansk, this would work with a standard (normal?) module, but it does NOT work with unit tests since they are executed automatically. +1 for the link
philippe
You could put the `require 'test/unit'` and the test case definitions inside the if statement and then they would only run when the current file is executed.
BaroqueBobcat
I had thought you could do what @BaroqueBobcat suggests. This would prevent `test/unit` from being a dependency when you're not running tests.
samg
Works great, thanks to both of you.
philippe
+3  A: 

It's actually not that uncommon in Ruby though it's certainly not the common practice in Rails.

One of the issues you may be running into is the same as this post which is that modules really should be included in classes in order to test them. It's certainly possible to test a module by including it in your test case but you're testing whether the module works when mixed into Test::Unit::TestCase, not that it'll work when you mix it into something more useful.

So unit tests should probably live on the class file or if you just want generally available methods use a class function instead of a module.

Chuck Vose
+1  A: 

Just found one way to prevent the unit test from being executed when the module is required from a script. There is a flag in unit.rb in .../lib/ruby/1.8/test/ to set to true.

Combined with samg trick (thanks again), we can write:

if (__FILE__ != $0)
    Test::Unit.run = true  ### do not run the unit tests
end
philippe