Why do my time-related unit tests break every day at 4pm?
For a long time I've been having this issue that at a certain time of the day, a TON of my tests break. I have a lot of tests that are doing 开发者_C百科simple date comparisons and everything runs fine from midnight to like 4:00 in the afternoon. Any idea why this is happening? I've set my timezone in my environment file too.
It seems like some of my calls like 5.days.from_now.to_date are adding an extra day.
Edit
For instance, this test fails:
# Widget that creates items for how many days the trip is gone.
def test_should_create_correct_amount_of_days_for_trip
w = DayWidget.create(:trip => trips(:hawaii))
assert_equal w.days.size, 5
end
# Code in trip model that calculates amount of days
def number_of_days
(self.return_date.to_date - self.depart_date.to_date).to_i + 1
end
# Test fixture yaml for Hawaii
hawaii:
depart_date: <%= Time.now.tomorrow.to_s(:db) %>
return_date: <%= 5.days.from_now.to_s(:db) %>
After 4:00 pm, the test above fails and says it created 6 days instead of 5. :(
You're probably in the Pacific time zone, 8 hours behind UTC (which is why at 4:00p they start breaking, since that's when it hits midnight UTC).
Without seeing your test/comparison code, all I could say is to make sure you're comparing dates/times with the same location (UTC to UTC or localtime to localtime).
Update: Ok, it looks like Time.now
returns a Time
object, whereas using XXX.days.from_now
returns an ActiveSupport::TimeWithZone
object, resulting in different handling of timezones:
ruby-1.9.2-p136 :009 > (Time.now+5.days).to_s(:db)
=> "2011-02-08 19:40:24"
ruby-1.9.2-p136 :010 > 5.days.from_now.to_s(:db)
=> "2011-02-09 03:40:29"
My recommendation would be to either call .utc
on your times in your fixtures like so:
ruby-1.9.2-p136 :017 > 5.days.from_now.utc.to_s(:db)
=> "2011-02-09 03:42:39"
ruby-1.9.2-p136 :018 > (Time.now+5.days).utc.to_s(:db)
=> "2011-02-09 03:42:39"
or to just switch to using 1.day.from_now
instead of Time.now.tomorrow
to keep the types consistent.
You can also use Time.current
instead of Time.now
.
Time.current
returns ActiveSupport::TimeWithZone
just like #ago
and #from_now
, so you can safely compare dates returned by them.
If you are truly dealing with just dates, be sure to set the hours, minutes and seconds to 0, otherwise you are at the mercy of the time of day you create the dates.
精彩评论