I believe every ruby developer has faced time comparison issue at least once and tests are one of the possible areas where it may happen. RSpec message like this may confuse:
confirmed_at should have been changed to Mon, 24 Mar 2014 09:47:22 UTC,
but is now Mon, 24 Mar 2014 09:47:22 UTC
What’s wrong?
Investigation
Let’s create two
Time
objects:
> t1, t2 = Time.now, Time.now
=> [2014-03-27 23:19:18 UTC, 2014-03-27 23:19:18 UTC]
At the first glance, they are equal. But it’s not true:
> t1 == t2
=> false
The issue occurs because ruby
Time
makes comparison with fractions of seconds. We may use
to_f
method to see the difference between
t1
and
t2
:
> t1.to_f
=> 1395955158.547284
> t2.to_f
=> 1395955158.547298
or
to_r
method to get rational numbers:
> t1.to_r
=> (348988789636821/250000)
> t2.to_r
=> (697977579273649/500000)
Summary
If you don’t care about milliseconds, you may compare timestamps using
to_i
method:
> t1.to_i == t2.to_i
=> true
or make a new
Time
object from timestamps to have better RSpec failure messages:
> Time.at(t1.to_i) == Time.at(t2.to_i)
=> true
But even better to use fixed times in our tests.