On 2009-09-16, at 08:08 , David Chelimsky wrote:
On Wed, Sep 16, 2009 at 3:34 AM, Ramon Tayag <ramon.ta...@gmail.com>
wrote:
I put an expectation test, but it complains two things are different
when it prints it out in the error in the exact same way:
http://pastie.org/618481
Printing is printing. Time is _not_ time. The problem is that the
times are off by milliseconds that aren't accounted for in time.to_s.
The usual solution is to either stub Time.now or introduce a time
generator, but you're not using Time.now, so that won't work. Options
include:
1. examine the submitted argument directly
@orders.should_receive(:updated_on) do |actual|
expected = 1.week.ago.to_i
actual.to_i.should be_between(expected - 1000, expected)
end
That will expect the time within 1 second of 1.week.ago.
2. introduce a custom argument matcher
class Roughly
def initialize(expected)
@expected = expected.to_i
end
def ==(actual)
actual.to_i.between?(@expected - 1000, @expected)
end
end
def roughly(expected)
Roughly.new(expected)
end
@orders.should_receive(:updated_on).with(roughly(1.week.ago))
And for extra credit, you can even make this one more flexible and
provide a lower and upper bound using a fluent interface:
@orders.should_receive(:updated_on).with(within(1.second).of
(1.week.ago))
I highly recommend a small refactoring to increase the clarity of your
code and reduce the coupling with the system clock. I posted my
suggestion at http://pastie.org/619142.
By doing this, you make it easy to stub/expect @orders in your
#process_aftersale test, and make it easy to test
#ready_for_aftersale_letter without wanting to use a stub or mock. To
test #ready_for_aftersale_letter, simply use 1.week.ago, 8.days.ago
and 6.days.ago as your test cases. Noticing this, you probably want to
try 7.days.ago + 1.millisecond and make sure that behaves the way
you'd expect, because you probably want to ensure that you use
1.week.ago.at_midnight, and not just 1.week.ago.
Question: if I buy from you on September 15, 2009 at 17:50, when is my
order ready for an aftersale letter? (a) September 22, 2009 at 17:50,
(b) September 22, 2009 at 00:00, (c) September 22, 2009 at 09:00, (d)
September 23, 2009 at 00:00, or some other time entirely? Write a test
for that.
Take care.
----
J. B. (Joe) Rainsberger :: http://www.jbrains.ca
Your guide to software craftsmanship
JUnit Recipes: Practical Methods for Programmer Testing
2005 Gordon Pask Award for contributions to Agile Software Practice
_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users