views:

32

answers:

1

I have a number of ruby files (a.rb, b.rb, c.rb) which define very similar classes. (They should test the same)

I've written a unit test to test these subclasses and I've generated contexts for each of the classes programatically (see below) — should I instead programatically create entire Test Classes instead? If so why and how?

I'm using the shoulda unit test extensions so my files look something like this:

a.rb

class ItsA
  def number
    1123
  end
end

b.rb

class ItsB
  def number
    6784
  end
end

test_letters.rb

require 'rubygems'
require 'test/unit'
require 'shoulda'

class LettersTest < Test::Unit::TestCase
  Dir.glob('letters/*.rb') do |letter|
    context "The #{letter} letter file"
      setup do
        # Here I require the ruby file and allocate
        # @theclass to be an instance of the class in the file.
        # I'm actually testing JavaScript using Harmony, but 
        # putting those details in might complicate my question.
      end

      should "return a number" do
        assert @theclass.number.is_a? Number
      end
    end
  end

This does the job reasonably well, but should I do some other jiggerypokery and create LetterATest, LetterBTest etc. automatically instead? If so, how would you go about doing it and why?

A: 

This really depends on how similar your classes are, but assuming they're pretty much identical and require a few small tests, and you're using shoulda, you could do something like:

class LettersTest < Test::Unit::TestCase
  context "The letter classes"
    setup do
      @instances = # your code to get a list of the instances
    end

    should "return a number" do
      @instances.each do |instance|
        assert instance.number.is_a?(Number), "#{instance.class}.number should be a number"
      end
    end
  end
end

In our codebase we've found that a large number of auto-generated contexts and tests leads to pretty slow test execution, so we favor the approach above to minimize the number of contexts/tests. You may not have this issue.

avaynshtok
That answers both my questions, sounds like I need to reduce my number of contexts where possible! Thank you!
JP