Tuesday, November 13, 2007
Ruby: Time::is
Mocha is fantastic for unit testing, but I usually try to avoid requiring it while functional testing. In general this works, but Time.now is something that I occasionally like to fix even while functional testing. To solve the problem, within a functional test helper I load a time_extensions.rb file that defines a Time::is method. The Time::is method is useful for freezing time at a certain point and executing a block of code. When the block of code finishes the Time.now method is returned to it's original implementation.
The example below is how I usually solve the described problem.
The example below is how I usually solve the described problem.
end
end
metaclass.class_eval do
define_method :now do
new_time
end
end
yield
end
end
end
Time.is(Time.now) do
Time.now # => Tue Nov 13 19:31:46 -0500 2007
sleep 2
Time.now # => Tue Nov 13 19:31:46 -0500 2007
end
Time.is("10/05/2006") do
Time.now # => Thu Oct 05 00:00:00 -0400 2006
sleep 2
Time.now # => Thu Oct 05 00:00:00 -0400 2006
end
Labels: functional testing, Time.now
Comments:
<< Home
You should have an "ensure" after the "yield" so that if the test fails Time.now will go back to the correct method.
Why not juse use mocha? I would argue it will be easier to read and follow for future devs, especially since it would be a 1 liner versus opening up the metaclass and hacking it manually.
Jay, could you bless us with a little insight on why you jump through the metaclass hoop instead of redefining now() right after creating the old_now alias?
I believe you are talking about this:
class << self
alias old_now now
end
metaclass.class_eval do
define_method :now do
new_time
end
end
which could also be
metaclass.class_eval do
alias old_now now
define_method :now do
new_time
end
end
There is no reason not to use the 2nd version. The first version was simply how the code evolved as I was writing tests. The 2nd version is what I would refactor to after all the tests were passing, I just missed it in the initial write up.
Cheers, Jay
class << self
alias old_now now
end
metaclass.class_eval do
define_method :now do
new_time
end
end
which could also be
metaclass.class_eval do
alias old_now now
define_method :now do
new_time
end
end
There is no reason not to use the 2nd version. The first version was simply how the code evolved as I was writing tests. The 2nd version is what I would refactor to after all the tests were passing, I just missed it in the initial write up.
Cheers, Jay
Why would you not just get rid of the metaclass call and just define now again in the first class << self ?
I'm curious about what the purpose of metaclass is.
I'm curious about what the purpose of metaclass is.
If you redefined now like so:
class << self
alias old_now now
define_method :now do
new_time
end
end
then "new_time" wouldn't be defined. The class << self limits the scope.
Cheers, Jay
Post a Comment
class << self
alias old_now now
define_method :now do
new_time
end
end
then "new_time" wouldn't be defined. The class << self limits the scope.
Cheers, Jay
<< Home




