Wednesday, August 13, 2008

Ruby Unit Tests

# mytest.rb
require 'test/unit'
require 'test/unit/ui/console/testrunner'

class MyTest < Test::Unit::TestCase
  # def setup
  # end

  # def teardown
  # end

  def test_fail
    assert(false, 'Assertion was false.')
  end
end

Test::Unit::UI::Console::TestRunner.run(MyTest)
# ordering.rb
class Ordering 
  attr_reader :x
  def initialize x
    @x = x
  end

  def <=> other
    self.x <=> other.x
  end

  def to_s 
    @x.to_s
  end
end

# o1 = Ordering.new 1
# o2 = Ordering.new 2

# puts o1 <=> o2
# puts o2 <=> o1
# ordering_test.rb
require 'test/unit'
require 'ordering.rb'

class MyTest < Test::Unit::TestCase
  # def setup
  # end

  # def teardown
  # end

  def test_compare
    o1 = Ordering.new 1
    o2 = Ordering.new 2
    assert((o1 <=> o2) == -1, 'not less than')
    assert((o2 <=> o1) == 1, 'not greater than')
    assert((o2 <=> Ordering.new(2)) == 0, 'not equal')
  end

  def test_sorting
    o1 = Ordering.new 1
    o2 = Ordering.new 2
    o3 = Ordering.new 3
    o4 = Ordering.new 4
    sorted = [o1, o2, o3, o4].sort
    (0..sorted.size - 2).each { |x|
      assert(sorted[x] <=> sorted[x + 1])
    }
  end
end
# test_runner.rb
require 'test/unit/ui/console/testrunner'
require 'ordering_test.rb'
Test::Unit::UI::Console::TestRunner.run(MyTest)
# person.rb
class Person
  def rocks_out! 
    true
  end
end
# employee.rb
require 'person'

class Employee < Person
  def initialize empl_nbr 
    @empl_nbr = empl_nbr 
  end
end 
# employee_test.rb
# see shoulda tutorial http://thoughtbot.com/projects/shoulda/tutorial/context
require 'rubygems'
require 'test/unit'
require 'shoulda'
require 'Employee'

class EmployeeTest < Test::Unit::TestCase 

  context "An Employee" do
    setup do
      @employee = Employee.new 1 
    end

    should "rock out" do
      assert @employee.rocks_out!
    end
  end

end
I see two benefits from using shoulda.   First, shoulda tests require less code since you no longer have to type both a meaningful method name and a test failure message.   Secondly, shoulda allows contexts to be nested and this closely mirrors the structure of business logic.   For instance, many change requests don't so much require a change to the business logic but rather a change to the context in which the logic is executed.   Shoulda tests mirror the nested contexts in which business logic resides. For Rails testing, see http://evang.eli.st/blog/rails