概要
Railsアプリでretryable gemを使ったリトライの処理があって、その処理でリトライオーバーした時の挙動をRspecで確認するときの時間短縮テクニックになります。
問題点
リトライオーバーした時の挙動を確認するためのテストを書いたが、素直にテスト対象ロジックのリトライ処理を動かすとテストの実行時間が大幅に伸びてしまう。
例
リトライ回数3回、リトライ時のインターバルが3秒のリトライ処理のリトライオーバー時の挙動をテストしようとすると、リトライ回数×インターバル時間=9秒もテストの実行時間が伸びる。
テスト対象ロジック
begin
Retryable.retryable(tries: 4, sleep: 3) do
# リトライ対象の処理
end
rescue => e
# リトライオーバー時の処理
end
(triesで4を指定しているのは、初回実行1回+リトライ3回の合計が4のため)
解決策
rspecのstub_constメソッドで定数をスタブ化する
stub_constメソッドを使うことでテスト実行中のみ一時的にテスト対象ロジックの定数を上書きすることができる。
retryableのtriesとsleepに指定する値を定数で定義しておき、テスト中にこの機能を使ってsleepの定数を上書きすれば、テストの時だけリトライのスリープを無視できる。
ただし、リトライごとにスリープするようなリトライ処理は外部と通信を行う処理だったりすることが多いので、そこはスタブ化しておく必要がある。
テスト対象ロジック
TRY_COUNT = 4
TRY_INTERVAL_SEC = 3
(省略)
begin
Retryable.retryable(tries: TRY_COUNT, sleep: TRY_INTERVAL_SEC) do
# リトライ対象の処理
end
rescue => e
# リトライオーバー時の処理
end
テストロジック
stub_const("MyClass::TRY_INTERVAL_SEC", 0)
まとめ
色々調べたのですがこの観点の情報に辿り着けなかったので記事にしました。
他にいい方法があれば教えていただけると幸いです。