RSpecについて最近話したことと自分のスタンス

最近話したこと Rails アプリケーションのデバッグ編 - Re: 醤油の一升瓶じゃあ戦えない の続き。ここではRSpecのテスト対象はRailsアプリケーションを指すことにする。また、ソフトウェアテスト技法そのものに関してはここではほとんど触れない。

まず読むもの

テストの書き方

自分はRSpecしぐさの内容にだいたい従っている。

www.slideshare.net

it / specify の使い分けについては基本郷に従うけど、自分で書くなら specify を使う。個人的にテストの結果は期待されることの主語を明確にするために受動態で書きたい気持ちがあるのだけれども、it だと主語がダブりそうなので。受動態で書きたいのは古の記憶がそう呼んでくるから。

この使い分けについては伊藤さんが最近書いた記事も合わせて読むと良さそう。 RSpecでit / example / specifyはどのように使い分けるのか?〜日本語で書くならexampleって本当?〜 - Qiita

実践

Active Jobのテスト

仮にFooJob をテスト対象とする。

FooJobジョブそのものをdescribeする場合は perform_now で呼び出せばよい。

何らかのクラスの処理の中で FooJob.perform_later のように非同期でジョブがエンキューされることを確認したいときは、have_enqueued_job matcher を使うとよい。perform_later に渡された引数は have_enqueued_job(FooJob).with("bar", "baz") のように with が使える。そんなことがドキュメントに書かれている。

何らかのクラスの処理の中で FooJob.perform_later が非同期で起こす副作用を確認したいこともあるかもしれない。そのまま実行しても非同期で実行されたジョブはRSpecがその処理を待ってくれず、期待した結果が返ってこない。その時は perform_enqueued_jobs を使うと良い。RSpecではなく、ActiveJob::TestHelper のメソッドである。

perform_enqueued_jobs do
  # FooJob.perform_later を含む処理
end

このように挟んでおくと perform_later も同期的に実行してくれる。パーフェクトRuby on Rails 2版だと「5-1-7 ジョブのテスト」に記載がある。

Action Mailerのテスト

Railsガイドを読むとだいたい解決しそう。 - 12 メイラーをテストする - Rails テスティングガイド - Railsガイド - ActionMailer::Base.deliveries がテストごとにリセットされなくて、テストの結果がランダムで落ちる現象については大昔に書いてた。大事なことは大体Rails ガイドが教えてくれる - Re: 醤油の一升瓶じゃあ戦えない

おまけ

  • 動くコード書くよりもテスト書いてる時間のほうが多分長くなりますよ
  • キリ悪いときはわざと落ちるテスト書いておくと、あとから再開する時に続きがわかって便利すよ

みたいな話をしたきもする。


眠気覚ましにガッと書いた。合わせて昔買ったソフトウェア技法やRailsの書籍をパラパラ読み返すいい機会になった。気が向いたら見返したり追記したりする。