Tech Sketch Bucket of Technical Chips by TIS Inc.

RSpec Tips -- Timecopで時間を自由に指定してテストしよう --

Pocket

この記事はeXcale Developer's Blogから移転されたものです。


eXcale 開発チームの冨樫です。

Ruby のテストフレームワークで人気の RSpec について、ハマりそうな点や知っておくと便利な機能をご紹介致します。
今回は「Timecop を使った、時間を指定してテストをする方法」です。 Timecop を使ったテスト方法と注意点についてご紹介致します。


eXcaleでは期間限定でサインアップキャンペーン実施中です。
キャンペーン内容についてはこちらを参照してください。


今回ご紹介する内容の題目です

  • 概要
  • 準備
  • 時間を固定させる(freeze)
  • 指定時刻からテストを開始させる(travel)
  • 1秒間に指定秒進ませる(scale)
  • Timecopの設定を無効にする(return)

概要

Timecop を使用することによって、下記の3つの処理に対して
freeze,travel,scale 等の指定を行うことができます。

・Time.now
・Date.today
・DateTime.now

準備

Gemfile に下記の通り test グループを追加し bundle install を実施してください。

準備が完了しましたら、実際にテストを書いていきましょう。

時間を固定させる(freeze)

Timecop.freeze を使用することで時間を固定させることができます。
以下のテストコードを動かしてみましょう。

テスト対象メソッドでは現在時刻を出力し、3秒経ってから再度現在時刻を出力させる処理を実施していますが、時間を固定させているため、同一時刻が出力されます。

年末年始や、閏年でのテストを実施する際に便利です。
Time.stub(:now).and_return() 等の stub を自分で用意する必要はありません。


指定時刻からテストを開始させる(travel)

Timecop.travel を使用することで、指定時刻からテストを開始させることができます。
指定時刻からは通常通り時間は進みます。

ではテストコードを動かして、値を確認してみましょう。
※ テスト対象メソッドは変更ありません

今度は指定時刻(2010/10/10 00:00:00)と、それから3秒後の時刻が出力されます。

こちらも年末年始や、閏年でのテストを実施する際に便利ですが、時間は固定されません。指定した時刻でテストしたいが時間を固定させたく無い場合はこちらを利用してください。


1秒間に指定秒進ませる(scale)

Timecop.scale を使用することで、1秒間に進む時間を指定することができます。

テストコードを動かして、値を確認してみましょう
※ テスト対象メソッドは変更ありません

テストでは1時間(3600秒)を指定したため、現在から3時間後の時刻が出力されます。

テスト時に一定時間待つ必要がある場合にこの scale を使用すれば、テスト実施時の待ち時間を縮めることができます。


Timecopの設定を無効にする(return)

Timecop で freeze 等を設定した場合、Timecop.return を実施するまで、設定が有効なままになります。
他のテストケースにも影響がでてしまう場合があるため、Timecop を使用した場合は Timecop.return の実施を忘れずに行いましょう。

Timecop.return の実施は after(:each) で定義するか、
spec_helper 内の config.after(:each) 等に定義しておくと良いかと思います。

また、別の対応方法として、Timecop で freeze 等を使用する際に、ブロック付き呼び出しで行う方法もあります。ブロックが終了した時点で Timecop の設定が無効になるため Timecop.return を実施する必要がありません。

さらに、常にブロック付き呼び出しをさせるような、 safe_mode 設定を行うこともできます。
Timecop.safe_mode が true の場合に、ブロック付きでない呼び出しを行うと Timecop::SafeModeException の例外が発生します。

5〜7行目はブロック付き呼び出しであるため例外は発生しませんが、8行目はブロック付きでは無いため例外が発生します。このように safe_mode を使い常にブロック付き呼び出しで対応する方法もあります。


最後に

今回は Timecop で時間を自由に指定してテストを実施する方法について、注意点を含めてご紹介させていただきました。
テストコードは面倒ですが怠けてるとそのうち自分に返ってくるので、便利機能を駆使して負けじと書いて行きましょう。

テストがお済みのアプリがありましたら、是非 eXcale へデプロイしてください。
操作手順は簡単なのでお気軽にお試し頂けます(基本無料です)。

※ サインアップからデプロイまでの流れは こちらのブログ で手順を紹介しているので、ご参照ください。

エンジニア採用中!私たちと一緒に働いてみませんか?