Since I’ve been encouraging myself to write more and better unit tests, I have encountered a troubling obstacle when writing tests to cover timestamp creation and updating. Let’s say I have a Record class which has a modification and creation timestamp. The ctime instance variable is created when a Record is instatiated and mtime is updated whenever the Record is updated. So, my test looks like this:
def test_ctime
record = Record.new
assert_equal(Time.now, record.ctime)
end
This failed because, believe it or not, the timers have too high
a resolution! In fact, even evaluating (with the help of irb)
Time.now == Time.now is false. This is evident by evaluating
5.times { puts Time.now.to_f } and seeing how the output differs
by a tiny amount with each iteration. I response to this, I decided
to generalize and adapt my assertion to accept a diminished
resolution with a tolerance of one second.
assert_equal(Time.now.sec, record.ctime.to_i). This is still
imprecise but it gets my point across. I had resigned myself to
accept this troublesome compromise until I went to write the test
for mtime. My test for mtime updating looked like this:
def test_mtime_update
record = Record.new
record.update
assert_operator(Time.now, :>, record.mtime)
end
I feel like I am compromising because I can’t make accurate
comparisons and can’t figure out how to do this properly. It seems
impossible and I don’t feel as if I have adequate coverage because
I can’t verify timestampt at all. Perhaps I am doing something
obviously wrong or testing for the wrong things. To make myself
feel better I added an assert_instance_of(Time, record.ctime) and
the same thing for mtime. Still, this has given me much frustration
and I can’t imagine no one else has encountered this before. I’m
writing this as part of a multithreaded application where timestamp
resolution could be quite crucial and I see my tests failing to
give me proper coverage. Help?