Timecop Ruby Gem

repository·master·Indexed 23 days ago

https://github.com/travisjeffery/timecop

A Ruby gem providing 'time travel', 'time freezing', and 'time scaling' capabilities. It allows developers to mock Time.now, Date.today, DateTime.now, and Process.clock_gettime for testing time-dependent code. Key features include Timecop.freeze for static mocking, Timecop.travel for offset simulation, Timecop.scale for accelerating time passage, and a safe_mode to prevent accidental global mocked states.

Tokens
1.4K
Snippets
7
Records
13
Agent score
36%

What's inside Timecop

  1. Use Timecop in Rails test environments

    master

    To set a consistent time for your entire Rails test environment, you can use an after_initialize block in config/environments/test.rb. This allows you to build test data at a specific point in time.

    # in config/environments/test.rb
    config.after_initialize do
      # Set Time.now to September 1, 2008 10:05:00 AM
      t = Time.local(2008, 9, 1, 10, 5, 0)
      Timecop.travel(t)
    end
  2. Enable Safe Mode

    master

    When Timecop.safe_mode is set to true, you are forced to use the block syntax for freeze and travel. This ensures that Timecop always automatically restores the original time once the block finishes. If you attempt to call these methods without a block, a Timecop::SafeModeException will be raised.

    # turn on safe mode
    Timecop.safe_mode = true
    
    # check if you are in safe mode
    Timecop.safe_mode?
    # => true
    
    # using method without block
    Timecop.freeze
    # => Timecop::SafeModeException: Safe mode is enabled, only calls passing a block are allowed.
  3. Scale time with Timecop.scale

    master

    Use Timecop.scale to accelerate the passage of time by a given scaling factor. This is useful for testing long-running cycles (like 30-day billing) in a short amount of real-world time.

    # seconds will now seem like hours
    Timecop.scale(3600)
    Time.now
    # => 2012-09-20 21:23:25 -0500
    
    # seconds later, hours have passed
    Time.now
    # => 2012-09-21 06:22:59 -0500
  4. Freeze time with Timecop.freeze

    master

    Use Timecop.freeze to statically mock the concept of 'now'. When time is frozen, Time.now will not change as your program executes unless you make subsequent calls to the Timecop API. You can pass a Time, DateTime, or Date instance, individual time arguments (year, month, day, etc.), or a single integer representing an offset in seconds from Time.now.

    new_time = Time.local(2008, 9, 1, 12, 0, 0)
    Timecop.freeze(new_time)
    sleep(10)
    new_time == Time.now # ==> true
  5. Travel through time with Timecop.travel

    master

    Use Timecop.travel to simulate the passage of time. Unlike freeze, travel computes an offset between the current mocked time and the time passed in, allowing time to continue moving forward from that point. You can pass a Time, DateTime, or Date instance, individual time arguments, or a single integer representing an offset in seconds from Time.now.

    new_time = Time.local(2008, 9, 1, 12, 0, 0)
    Timecop.return # "turn off" Timecop
    Timecop.travel(new_time)
    sleep(10)
    new_time == Time.now # ==> false
  6. Enable Safe Mode to prevent accidental unblocked calls

    master

    When safe_mode is enabled, Timecop.travel will raise a Timecop::SafeModeException if it is called without a block. This prevents developers from accidentally leaving the system in a mocked state globally.

    safe_mode? returns whether safe mode is currently active.

  7. Configure Timecop thread safety

    master

    By default, Timecop's state (the stack of mocked times) is global. If you are running tests in a multi-threaded environment and want each thread to have its own independent time state, enable thread_safe mode.

    Note: When thread_safe is enabled, the baseline and stack are stored in Thread.current.

  8. Check current Timecop state

    master

    Use these methods to inspect whether Timecop is currently manipulating time and which mode is active:

    • Timecop.frozen?: Returns true if time is currently frozen.
    • Timecop.travelled?: Returns true if time is currently being traveled (offset).
    • Timecop.scaled?: Returns true if time is currently being scaled.
  9. Simulate a running clock with Timecop.travel

    master

    Use Timecop.travel to simulate a running clock. Unlike freeze, time continues to move forward, but it is offset from the actual system time. This is a safer option for Rails environment files as it doesn't completely halt the clock.

    Supported arguments are identical to Timecop.freeze:

    • A Time, DateTime, or Date instance
    • An offset in seconds
    • Individual components: year, month, day, hour, minute, second
    • No arguments (defaults to Time.now)

    When passed a block, Timecop reverts to the previous time after the block finishes.