Today I was testing a small helper method I had written that would convert a String to a date or if it was already a DateTime object it would just return it. A pretty simple function but one that needs testing all the same.

Initially my test looked something like this;


require 'spec_helper'
require 'date'
require 'time'

describe MyHelper do
  describe 'convert_to_datetime functionality' do

    let(:input) { '2012-03-04' }
    let(:date_version) { DateTime.parse(input) }

    it 'should successfully convert a well formatted date string' do
      output = convert_to_datetime input
      output.should == date_version
    end

    it 'should return the original date if a DateTime object was passed in' do
      output = convert_to_datetime date_version
      output.should == date_version
    end
  end
end

On the face of it this would seem to work, and indeed all the tests pass, but what if I changed output.should == date_version to output.should == input? Instant fail? Nope!

The reason why this also passes is because I am including ActiveSupport earlier on in the code and with that included so long as the String when converted to a DateTime is the same DateTime then .should == will pass.

This was unexpected, but fortunately I very quickly found be_an_instance_of, what this allows us to do is check that a variable is an instance of a particular class, in our example a DateTime class.

Now my code reads;


require 'spec_helper'
require 'date'
require 'time'

describe MyHelper do
  describe 'convert_to_datetime functionality' do

    let(:input) { '2012-03-04' }
    let(:date_version) { DateTime.parse(input) }

    it 'should successfully convert a well formatted date string' do
      output = convert_to_datetime input
      output.should be_an_instance_of(DateTime)
      output.should == date_version
    end

    it 'should return the original date if a DateTime object was passed in' do
      output = convert_to_datetime date_version
      output.should be_an_instance_of(DateTime)
      output.should == date_version
    end
  end
end

Which is a more solid check.

*Update*

Some nice folk on Reddit pointed out that I could have done one of the following;

  1. Swapped output.should for date_version.should which would force rspec not to change my DateTime into a String.
  2. Used eql instead of == which does not do type conversion.
  3. Using be_instance_of can make your code a little harder to read and might end up coupling your test to a particular data type and if that changes you could end up with stuff to fix.

Why not read some more of our Ruby posts?