Use Timecop to time travel in testing
Timecop is a gem providing “time travel” and “time freezing” capabilities, making it dead simple to test time-dependent code.
In this post, we are going to use the [Timecop](https://github.com/travisjeffery/timecop) ruby gem to test our trial_remaining_time
method which returns the number of days remaining in the user's trial plan.
timecop is a gem providing
time travel
andtime freezing
capabilities, making it dead simple to test time-dependent code. It provides a unified method to mockTime.now
,Date.today
, andDateTime.now
in a single call.
class User < ApplicationRecord
# Method to return number of remaining trial days
def trial_remaining_days
days = (created_at.to_date - 15.days.ago.to_date).to_i
return days if days.positive?
0
end
end
And we want to make sure our method is working fine, so how do we test it? Using timecop makes it dead simple to travel time and freeze it so that we can check expected results on different future dates for our use case.
NOTE: I am using the default
unit_test
from the rails project, you can also userspec
without any issue.
require 'test_helper'
class UserTest < ActiveSupport::TestCase
test 'should return remaining days for user' do
user = User.new(created_at: Time.current)
(15..0).to_a.each_with_index do |day, index|
Timecop.freeze(day.days.from_now) do
assert_equal index, user.trial_remaining_days
end
end
end
test 'should return 0 trial remaining days for user created more than 15 days ago' do
user = User.new(created_at: Time.current)
Timecop.freeze(16.days.from_now) do
assert_equal 0, user.trial_remaining_days
end
Timecop.freeze(20.days.from_now) do
assert_equal 0, user.trial_remaining_days
end
end
end
Running 2 tests in a single process (parallelization threshold is 50)
Run options: --seed 62828
# Running:
..
Finished in 0.038093s, 52.5033 runs/s, 52.5033 assertions/s.
2 runs, 2 assertions, 0 failures, 0 errors, 0 skips
To understand it let's print values of Timecop.freeze
method
# Today is 2022-01-11
Time.now
=> 2022-01-11 19:45:44.501290989 +0545
# lets freeze time in 0.days and see what will happens
irb(main):008:0> Timecop.freeze(0.days.from_now) { puts Time.current }
2022-01-11 14:01:00 UTC
# if we freeze time in 10.days from now
irb(main):010:0> Timecop.freeze(10.days.from_now) { puts Time.now }
2022-01-21 19:47:05 +0545
happy hacking!