現在日時をズラしたテストが実行できる「TimeHelpers(travel・travel_back・travel_to)」(Rails)

【結論】

ActiveSupportTimeHelpersでは、時間経過によって動作が変化する機能のテストを行う為のヘルパーメソッドが提供される

travelメソッドは、現在の日時を指定された日時の分だけ未来または過去の日時に変更する

travel_toメソッドは、直接指定した日時に現在の日時を変更する

【目次】

【本題】

TimeHelpersについて

RailsActiveSupportには、時間経過によって動作が変化する機能をテストする為のヘルパーがあります。

それがTimeHelpersです。

これにより、「有効期限の過ぎたクーポンが使えない」といったテストが実行できます。

RSpecへの導入方法

RSpecTimeHelpersを利用できる様にするには、まずrails_helper.rbにincludeする必要があります。

RSpec.configure do |config|
  #...
  config.include ActiveSupport::Testing::TimeHelpers
  #...
end

これによりTimeHelpersによって提供されるメソッドを利用する事が可能になります。

travelメソッド

travelメソッドは、Time.now・Date.today・DateTime.nowなどで呼び出される現在の時刻を、指定した任意の時間差に変更できます。

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

変更された日時は、テストが終了した時点で元に戻ります。

もし部分的に現在日時を変更したい場合は、ブロックで対象のテストを囲めば、ブロック内の処理が完了すれば日時は元に戻ります。

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

または、travel_backメソッドを利用することで、元に戻すこともできます。

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

travel_back
Time.current 
# => Sat, 09 Nov 2013 15:34:49 EST -05:00

travel_toメソッド

travelメソッドは、現在日時からの時間差で変更する日時を指定します。

対して、travel_toメソッドは、直接変更する日時を指定します。

Time.current     
# => Sat, 09 Nov 2013 15:34:49 EST -05:00

travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
Time.current     
# => Wed, 24 Nov 2004 01:04:44 EST -05:00

DateTime.current 
# => Wed, 24 Nov 2004 01:04:44 -0500

変更された日時は、テストが終了した時点で元に戻ります。

もし部分的に現在日時を変更したい場合は、travelメソッドと同様、ブロックで対象テストを囲うか、travel_backメソッドを利用します。

参考情報

ActiveSupport::Testing::TimeHelpers

Rails テスティングガイド - Railsガイド

RSpec で安全に Timecop する - Qiita