最近話したこと Rails アプリケーションのデバッグ編 - Re: 醤油の一升瓶じゃあ戦えない の続き。ここではRSpecのテスト対象はRailsアプリケーションを指すことにする。また、ソフトウェアテスト技法そのものに関してはここではほとんど触れない。
まず読むもの
- Publisher: RSpec - Relish
- RSpecのドキュメント。
- RSpec Core 3.10 - RSpec Core - RSpec - Relish
- 設定とか基本構文とか
- RSpec Expectations 3.10 - RSpec Expectations - RSpec - Relish
- 期待値を表現するための述語とか
- 期待値が冗長な書き方になりそう、みたいなことがあったらBuilt in matchers を眺めるとより便利なマッチャーが用意されていることに気がついたりする
- RSpec Mocks 3.10 - RSpec Mocks - RSpec - Relish
- モックとスタブ
- 自分はあまり使ってないので詳しくない
- RSpec Rails 5.0 - RSpec Rails - RSpec - Relish
- Railsのための拡張
- Job specs や Mailer specs はそのテストを書くことになった時にまず読むと良さそう
- Railsのための拡張
- RSpec Core 3.10 - RSpec Core - RSpec - Relish
- RSpecのドキュメント。
- Rails テスティングガイド - Railsガイド
- minitestだけど、Railsのテストについて一通り書かれている
テストの書き方
自分はRSpecしぐさの内容にだいたい従っている。
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の書籍をパラパラ読み返すいい機会になった。気が向いたら見返したり追記したりする。