модуль ActiveSupport::Testing::TimeHelpers
Содержит вспомогательные функции для тестирования хода времени.
Публичные методы экземпляров
# File activesupport/lib/active_support/testing/time_helpers.rb, line 69 def after_teardown travel_back super end
# File activesupport/lib/active_support/testing/time_helpers.rb, line 252 def freeze_time(with_usec: false, &block) travel_to Time.now, with_usec: with_usec, &block end
Вызывает travel_to с Time.now. Передает необязательный аргумент with_usec.
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
Этот метод также принимает блок, который вернёт текущее время в исходное состояние по завершении блока:
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
# File activesupport/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
Изменяет текущее время на время в будущем или прошлом на заданную разницу во времени, подменяя Time.now, Date.today, и DateTime.now. Подстановки автоматически удаляются по завершении теста.
Обратите внимание, что usec для полученного времени будет установлено в 0, чтобы предотвратить ошибки округления с внешними сервисами, такими как MySQL (который округляет вместо округления вниз, что приводит к ошибкам в одну секунду), если аргумент with_usec не установлен в 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
Этот метод также принимает блок, который вернёт текущее время в исходное состояние по завершении блока:
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
# File activesupport/lib/active_support/testing/time_helpers.rb, line 226 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, travel_to, и 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
Этот метод также принимает блок, который возвращает подстановки по завершении блока:
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
# File activesupport/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)
elsif with_usec
now = date_or_time.to_time
else
now = date_or_time.to_time.change(usec: 0)
end
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, **options|
if args.empty? && options.empty?
at(now)
else
stub = stubs.stubbing(Time, :new)
Time.send(stub.original_method, *args, **options)
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 Изменяет текущее время на заданное время, подменяя Time.now, Time.new, Date.today, и DateTime.now для возврата времени или даты, переданных в этот метод. Подстановки автоматически удаляются по завершении теста.
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
Даты рассматриваются как их метки времени в начале дня во временной зоне приложения. Time.current возвращает указанную метку времени, а Time.now её эквивалент во временной зоне системы. Аналогично, Date.current возвращает дату, равную аргументу, а Date.today дату в соответствии с Time.now, которая может отличаться. (Обратите внимание, что вам редко нужно иметь дело с Time.now, или Date.today, для соблюдения временной зоны приложения всегда используйте Time.current и Date.current.)
Обратите внимание, что usec для переданного времени будет установлен в 0, чтобы предотвратить ошибки округления с внешними сервисами, такими как MySQL (который округляет вместо округления вниз, что приводит к ошибкам в одну секунду), если аргумент with_usec установлен в true.
Этот метод также принимает блок, который вернёт текущее время в исходное состояние по завершении блока:
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
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.