Time is a huge topic. I mean, since the start of the times. Our species has thinking about time since a millennia ago. We don’t know the precise date when that happened because we didn’t take account of time until we ponder a lot about it. So, we could sometimes overlook some nuances of time. And that happened to the team that wrote some tests in a Rails project. Once Upon a Time, There Was a Ruby Project Dealing With Time… I started collaborating on that project where I took a tech-lead role. I was performing more code reviews than coding. And one of the first things that popped up to my eye when reviewing pull requests was that the team was changing tests even when the change was a refactor. “Why are you rewriting tests for a refactor? In a refactor, tests should remain the same. That tells us that the refactored code is working in the same way as the older code! ” I added in my comments. The frustrated team members pointed out that each week, at least one test fails because it depends on the date. One app controller retrieves the results of people whose birthday occurs on that week. If they run the test suite in a different week, they need to update the expected result. I was shocked! I was planning to add a task for refactoring those tests until the product owner said, “No! On this point, we need to create stories that add value to the final user. Tests are important, but they don’t add value to the final user!” I didn’t want to argue, so I accepted the ridiculous reality with stoicism. I continued performing code reviews, and I learned to ignore changes on tests. But after a while, I found the time to tackle those disgraceful test cases. And I found the gem «timecop», a gem created by and maintained by John Trupiano Travis Jeffery. What Does Timecop Do? Timecop is a ruby gem created for those specific cases where we have tests dependent on time. It could be birthdays, but also it could be expiration days for JWT tokens or recurrent billings. In a single line, Timecop creates a mock of Time.now, Date.today, and DateTime.now. As Timecop creators highlight in their README file, the gem doesn’t have dependencies, so it works well with any Ruby test framework. With only two basic methods ( and ), you can easily control the time! Time.travel Time.freeze How to Install Timecop Timecop is a ruby gem available on rubygems.org. So, you can just add Timecop to your Gemfile and run after that. Unless you're using Timecop for something different to testing, add the gem in a test group. bundle install Gemfile ... group :test do ... # Other gems gem 'timecop' end Alternatively, run or install it on your computer with . bundle add timecop gem install timecop To Timecop.travel or To Timecop.freeze? As I commented above, you only need to know two methods for using Timecop: Timecop.travel and Timecop.freeze. But what is the difference between these two methods? Timecop.travel Method With , you set up time to a specific date, and then time will move forward after that. Timecop.travel For example, if you to February 2, 1993, 6:00:00 AM, after ten seconds, returns February 2, 1993, 6:00:10 AM Timecop.travel Time.now groundhog_day = Time.local(1993, 2, 2, 6, 0, 0) Timecop.travel(groundhog_day) sleep(10) groundhog_day == Time.now # ==> false Timecop.freeze Method On the other way, with time stops completely. So, using a similar example, will return exactly on February 2, 1993, 6:00:00 AM: Timecop.freeze Time.now groundhog_day = Time.local(1993, 2, 2, 6, 0, 0) Timecop.travel(groundhog_day) sleep(10) groundhog_day == Time.now # ==> true Other Useful Methods Other Timecop methods allow you to move time faster or return to the system date. Timecop.scale Move times faster. It’s a good option for integration tests where you want to check that some jobs are performed. Code example: # seconds will now seem like hours Timecop.scale(3600) Time.now # => 2012-09-20 21:23:25 -0500 # seconds later, hours have passed and it's gone from 9pm at night to 6am in the morning Time.now # => 2012-09-21 06:22:59 -0500 Timecop.return Move time to system date again. GROUNDHOG_DAY = Time.local(1993, 2, 2, 23, 59, 51) def groundhog_day? = Time.now == GROUNDHOG_DAY Timecop.freeze(GROUNDHOG_DAY) sleep(10) groundhog_day? # => True Timecop.return groundhog_day? #=> False Set the Time of Your Tests’ Cases Timecop readme is really clear for its usage. For using Timecop in a time-sensitive test: joe = User.find(1) joe.purchase_home() assert !joe.mortgage_due? # move ahead a month and assert that the mortgage is due Timecop.freeze(Date.today + 30) do assert joe.mortgage_due? end For use in a group of tests, you write: describe "some set of tests to mock" do before do Timecop.freeze(Time.local(1990)) end after do Timecop.return end it "should do blah blah blah" do end end Set the Start Time of Your Test Environment for Your Rails Project If you want to set up your test environment to always start on the same date, add this configuration: config/environment/ test.rb ... # your configuration config.after_initialize do # Set Time.now to February 2, 1993 06:00:00 AM (at this instant), but allow it to move forward # year, month, day, hour, min, sec t = Time.local(1993, 2, 2, 6, 0, 0) Timecop.travel(t) end ... end After that, each time that you run your test, the date will start on February 2 at 6:00 AM. That’s all! I hope you found Timecop as useful as this post.