Module: ActiveSupport::Testing::TimeHelpers
- Included in:
- ActiveSupport::TestCase
- Defined in:
- lib/active_support/testing/time_helpers.rb
Overview
Contains helpers that help you test passage of time.
Instance Method Summary collapse
- #after_teardown ⇒ Object
-
#freeze_time(with_usec: false, &block) ⇒ Object
Calls
travel_to
withTime.now
. -
#travel(duration, with_usec: false, &block) ⇒ Object
Changes current time to the time in the future or in the past by a given time difference by stubbing
Time.now
,Date.today
, andDateTime.now
. -
#travel_back ⇒ Object
(also: #unfreeze_time)
Returns the current time back to its original state, by removing the stubs added by
travel
,travel_to
, andfreeze_time
. -
#travel_to(date_or_time, with_usec: false) ⇒ Object
Changes current time to the given time by stubbing
Time.now
,Time.new
,Date.today
, andDateTime.now
to return the time or date passed into this method.
Instance Method Details
#after_teardown ⇒ Object
69 70 71 72 |
# File 'lib/active_support/testing/time_helpers.rb', line 69 def after_teardown travel_back super end |
#freeze_time(with_usec: false, &block) ⇒ Object
Calls travel_to
with Time.now
. Forwards optional with_usec
argument.
Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
freeze_time
sleep(1)
Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
This method also accepts a block, which will return the current time back to its original state at the end of the block:
Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
freeze_time do
sleep(1)
User.create.created_at # => Sun, 09 Jul 2017 15:34:49 EST -05:00
end
Time.current # => Sun, 09 Jul 2017 15:34:50 EST -05:00
256 257 258 |
# File 'lib/active_support/testing/time_helpers.rb', line 256 def freeze_time(with_usec: false, &block) travel_to Time.now, with_usec: with_usec, &block end |
#travel(duration, with_usec: false, &block) ⇒ Object
Changes current time to the time in the future or in the past by a given time difference by stubbing Time.now
, Date.today
, and DateTime.now
. The stubs are automatically removed at the end of the test.
Note that the usec for the resulting time will be set to 0 to prevent rounding errors with external services, like MySQL (which will round instead of floor, leading to off-by-one-second errors), unless the with_usec
argument is set to true
.
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
travel 1.day
Time.current # => Sun, 10 Nov 2013 15:34:49 EST -05:00
Date.current # => Sun, 10 Nov 2013
DateTime.current # => Sun, 10 Nov 2013 15:34:49 -0500
This method also accepts a block, which will return the current time back to its original state at the end of the block:
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
travel 1.day do
User.create.created_at # => Sun, 10 Nov 2013 15:34:49 EST -05:00
end
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
97 98 99 |
# File 'lib/active_support/testing/time_helpers.rb', line 97 def travel(duration, with_usec: false, &block) travel_to Time.now + duration, with_usec: with_usec, &block end |
#travel_back ⇒ Object Also known as: unfreeze_time
Returns the current time back to its original state, by removing the stubs added by travel
, travel_to
, and freeze_time
.
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
travel_to Time.zone.local(2004, 11, 24, 1, 4, 44)
Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
travel_back
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
This method also accepts a block, which brings the stubs back at the end of the block:
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
travel_to Time.zone.local(2004, 11, 24, 1, 4, 44)
Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
travel_back do
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
end
Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
230 231 232 233 234 235 236 237 |
# File 'lib/active_support/testing/time_helpers.rb', line 230 def travel_back stubbed_time = Time.current if block_given? && simple_stubs.stubbed? simple_stubs.unstub_all! yield if block_given? ensure travel_to stubbed_time if stubbed_time end |
#travel_to(date_or_time, with_usec: false) ⇒ Object
Changes current time to the given time by stubbing Time.now
, Time.new
, Date.today
, and DateTime.now
to return the time or date passed into this method. The stubs are automatically removed at the end of the test.
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
travel_to Time.zone.local(2004, 11, 24, 1, 4, 44)
Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
Date.current # => Wed, 24 Nov 2004
DateTime.current # => Wed, 24 Nov 2004 01:04:44 -0500
Dates are taken as their timestamp at the beginning of the day in the application time zone. Time.current
returns said timestamp, and Time.now
its equivalent in the system time zone. Similarly, Date.current
returns a date equal to the argument, and Date.today
the date according to Time.now
, which may be different. (Note that you rarely want to deal with Time.now
, or Date.today
, in order to honor the application time zone please always use Time.current
and Date.current
.)
Note that the usec for the time passed will be set to 0 to prevent rounding errors with external services, like MySQL (which will round instead of floor, leading to off-by-one-second errors), unless the with_usec
argument is set to true
.
This method also accepts a block, which will return the current time back to its original state at the end of the block:
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
travel_to Time.zone.local(2004, 11, 24, 1, 4, 44) do
Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
end
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/active_support/testing/time_helpers.rb', line 133 def travel_to(date_or_time, with_usec: false) if block_given? && in_block travel_to_nested_block_call = <<~MSG Calling `travel_to` with a block, when we have previously already made a call to `travel_to`, can lead to confusing time stubbing. Instead of: travel_to 2.days.from_now do # 2 days from today travel_to 3.days.from_now do # 5 days from today end end preferred way to achieve above is: travel 2.days do # 2 days from today end travel 5.days do # 5 days from today end MSG raise travel_to_nested_block_call end if date_or_time.is_a?(Date) && !date_or_time.is_a?(DateTime) now = date_or_time.midnight.to_time elsif date_or_time.is_a?(String) now = Time.zone.parse(date_or_time) else now = date_or_time now = now.to_time unless now.is_a?(Time) now = now.change(usec: 0) unless with_usec end # +now+ must be in local system timezone, because +Time.at(now)+ # and +now.to_date+ (see stubs below) will use +now+'s timezone too! now = now.getlocal stubs = simple_stubs stubbed_time = Time.now if stubs.stubbing(Time, :now) stubs.stub_object(Time, :now) { at(now) } stubs.stub_object(Time, :new) do |*args, **| if args.empty? && .empty? at(now) else stub = stubs.stubbing(Time, :new) Time.send(stub.original_method, *args, **) end end stubs.stub_object(Date, :today) { jd(now.to_date.jd) } stubs.stub_object(DateTime, :now) { jd(now.to_date.jd, now.hour, now.min, now.sec, Rational(now.utc_offset, 86400)) } if block_given? begin self.in_block = true yield ensure if stubbed_time travel_to stubbed_time else travel_back end self.in_block = false end end end |