
【開発ブログ】RSpecで時間を操作してテストする
こんにちは。24年度新卒の ryoaio です。
私の所属するチームは2024年7月に立ち上がり、この半年で体制やメンバーを変えつつ、経験を積みながら形成してきました。
半年はあっという間ですね...! 今年も多くのことを経験し、個人としてもチームとしても強くなっていきます💪
さて、本日は、最近触ったRSpecの時間の操作に関してまとめたいと思います。
RSpecで時間操作をすることになったきっかけ
「start_time ~ end_timeまでの期間を指定して情報を取得するようなGETメソッドにて、end_timeが現在時間よりも未来を指していた場合、未来のデータが仮にあったとしても、現在時間までのデータを返すようにする」 という実装を行いました。
この際、RSpec上正しく返されているかを確認するために、時間の操作が必要でした。
RSpecで時間を止める方法は複数ある
Timecopを使う
Railsのgem
Time, Date, DateTimeオブジェクトのオーバーライドによる実装
.freezeで現在時間を完全に停止
.travelで指定した時間に固定したり、指定した時間からの経過を測れるようにする
TimeHelpersを使う
Railsの組み込み
4.1以降が対応
fleeze_timeで現在時間を完全に停止
travelや travel_to で指定時間に固定
travel_backで現在時刻に戻す
5.2以前ではtravel_backをするまでテスト中時間が止まり続ける
5.2以降ではテスト終了時に自動的に元に戻る
今回の課題の解決
以下理由でTimeHelpersを使いました。
どちらの方法でもできることに大きな違いがないため
今回やりたいことは日時の固定のみとシンプルで、gemを導入せずとも問題なくテストができそうだったため
時間操作時の注意点
ミリ秒の誤差が生じてテストが落ちることがある
TimeHelpersのドキュメントに次のような記載があります。
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).
実際、時間を指定して固定するだけでは、テストが落ちてしまうことがありました。
# 時間を固定し、operate時に time:にcurrent_timeが入ること
current_time = Time.zone.now
travel_to current_time
target.operate
expect(Target.find(target.id)).to have_attributes(
time: current_time,
)
一見問題なさそうに見えますが、以下のように期待していた値から差ができ、テスト失敗となってしまいます。
(expedcted) -:time => 2025-02-05 07:59:11.384651543 +0000,
(got) +:time => 2025-02-05 07:59:11.000000000 +0000,
Timeクラスで使えるusecの指定によって、期待値を調整しておきましょう。
# 時間を固定し、operate時に time:にcurrent_timeが入ること
current_time = Time.zone.now.change(usec: 0)
travel_to current_time
target.operate
expect(Target.find(target.id)).to have_attributes(
time: current_time,
)
これでOKです!
実際、上記例のようにtravel_toで現在時間を固定した上で、固定した日時より未来の日時でリクエストを送り、固定した日時までのデータが返されていることを確認できました!
最後に
ご覧いただきありがとうございました。
私のチームは、伸び代の宝庫です。まだまだスクラムが不安定であったりと、試行錯誤する毎日。 そういった学びの共有はまた、チームの成長を実感し、言語化できるようになった時にしたいと思います。
いいなと思ったら応援しよう!
