RSpec is great:

it "should be its own root" do
  @node.root.should == @node
end

it "should add a child" do
  @node.children.size.should == 0

  child = @klass.new

  @node.add_child(child)
  @node.children.size.should == 1

  child.parent.should == @node
  child.root.should == @node
end

Looks beautiful. However, look at line #2. What would the output be if that test fails? The message would be something like this: "expected #{@target.inspect} to the same as #{@expected.inspect}".

Inspecting an object like a tree node could result in multiple pages worth of data and the output basically becomes unreadable if there’s an array of objects.

This problem could easily be fixed with a custom expectation matcher.

module BeTheSameAsMatcher
  class BeTheSameAs
    def initialize(expected)
      @expected = expected
    end

    def matches?(target)
      @target = target
      @target.eql?(@expected)
    end

    def failure_message
      "expected <#{to_string(@target)}> to " +
      "the same as <#{to_string(@expected)}>"
    end

    def negative_failure_message
      "expected <#{to_string(@target)}> not to " +
      "be the same as <#{to_string(@expected)}>"
    end

    # Returns string representation of an object.
    def to_string(value)
      # indicate a nil
      if value.nil?
        'nil'
      end

      # join arrays
      if value.class == Array
        return value.join(", ")
      end

      # otherwise return to_s() instead of inspect()
      return value.to_s
    end
  end

  # Actual matcher that is exposed.
  def be_the_same_as(expected)
    BeTheSameAs.new(expected)
  end
end

As you can see, methods failure_message and negative_failure_message define our error messages. Instead of default inspect call, I’m using a custom to_string method which will either return a join for an Array or to_s for any other object.

To make this available in all of your specs, the module needs to be added in your `spec_helper.rb` like so:

require 'spec/be_the_same_as'

Spec::Runner.configure do |config|
  config.include(BeTheSameAsMatcher)
end

After this, we can change our line #2 from the original script to this:

it "should be its own root" do
  @node.root.should be_the_same_as(@node)
end

Rails allows you to create data fixtures which can contain test data which is used during unit tests and gets loaded into a _test database.

It’s possible to load that data into your _development database so that you can use the same data while looking at your site in the browser. This can be achieved using a rake command. Read the rest of this entry »