trouble comparing datetimes in rspec

I'm getting a weird failure when trying to compare two datetimes. The failure message is:

'Prompt as a featured prompt should set featured_on for public prompts' FAILED expected: Thu May 22 16:31:38 -0400 2008,      got: Thu May 22 16:31:38 -0400 2008 (using ==)

My test:

  it "should set featured_on for public prompts" do     date = 2.days.ago #cache timestamp     @prompt = create_prompt(:scope => "public", :featured_on => nil)     @prompt.make_featured :date => date     @prompt.featured_on.should == (date)   end

My model method:

def make_featured(options = {})     unless scope == "private"       options = {:date => Time.now}.merge(options)       date = options[:date].to_s(:db)       self.featured_on = date       self.save     else       false     end   end

I recently upgraded to Rails 2.1_RC1, so I'm hoping that didn't foul anything up. Also, what's weird is that in my method I'm setting :featured_on to date.to_s(:db). So if I run a prompt.inspect in the console, it returns "featured_on: '2008-05-24 16:20:45'", but if I just type "prompt.featured_on" in the console, it returns Sat May 24 16:20:45 -0400 2008, so I don't know if rails is doing any auto-conversion there. But that seems almost totally unrelated to my test failing when comparing two identical date values.

Any help?

Hi Bryan.

Could it be you're comparing the value date in your spec, which is of class Time, to a string (the value of featured_on)?

mike

Could it be you're comparing date in your spec, which is of class Time, to a string (the value of featured_on)?

That doesn't seem to be the problem. If I convert both values in the comparison to String, it will pass the test, but not if I just convert the value I'm comparing against.

It also seems that regardless of whether I pass in a Time object or a String to the record, Rails returns a Time object (which I assume is because the column is set as datetime). Both of the objects I'm comparing in my test belong to the Time class.

Is rspec comparing on the objects themselves, which will never be equal, instead of the value?

I did a quick test in the console (although this may not help at all)

d1 = 2.days.ago

=> Thu May 22 17:03:10 -0400 2008

d2 = Time.parse(d1.to_s)

=> Thu May 22 17:03:10 -0400 2008

d1 == d2

=> false

but here they are of course equal because they reference the same object

d1 = d2 = 2.days.ago

=> Thu May 22 17:03:10 -0400 2008

d1 == d2

=> true

cheers. mike

Is rspec comparing on the objects themselves, which will never be equal, instead of the value?

I did a quick test in the console (although this may not help at all)

d1 = 2.days.ago

=> Thu May 22 17:03:10 -0400 2008

d2 = Time.parse(d1.to_s)

=> Thu May 22 17:03:10 -0400 2008

d1 == d2

=> false

>> d1 = 2.days.ago => Fri May 23 11:51:52 UTC 2008 >> d2 = Time.parse(d1.to_s) => Fri May 23 11:51:52 UTC 2008 >> d1.usec => 7070 >> d2.usec => 0

The roundtrip via to_s (or the database) discards the fractional part of the time.

Fred

oh yes, I see that now. Thank you.

Ah ha! Thank you both for helping me out. I'm just going to stick to comparing them both as strings.

Try something like this:

it “should blablabla” do time = Time.now Time.stub!(:now).and_return(now) @foo.something_that_calls_time_now @foo.time_variable.should == time end

Stubbing Time.now [or whatever Time/Date method you use] is gonna be the trick. HTH

RSL