- 更新日: 2014年3月19日
- RSpec
RSpec の –profile オプションで時間のかかる遅いテストを調べる
RSpec で書いている Rails のテストのサンプル数が300個を超えて、全部のテストを終えるのに5分以上とかかかるようになってきました。ネットワーク超えの外部ウェブサービスのAPIを利用したり、重いDB処理を行う箇所などが含まれるのでしょうがない側面もありますけれど。
— 環境 —
rails-4.0.1
rspec-rails-2.14.0
capybara-2.2.0
RSpec メンテナの方に –profile オプションを教えてもらった
それで、RSpec のテストが時間かかって遅い〜とつぶやいたところ、RSpec のメンテナの方からアドバイスを頂けました。Myron Marston さんありがとうございます!ブログでツイートと情報のシェアも承諾頂きました。
@takafumir The `–profile` option can be used to print out the slowest examples.
— Myron Marston (@myronmarston) March 18, 2014
訳:– profile オプションを使うと遅いサンプルをリストアップできるよ。
ヘルプを見てみますと…
1 2 3 4 |
$ bundle exec rspec --help -p, --[no-]profile [COUNT] Enable profiling of examples and list the slowest examples (default: 10). |
なるほど… ヘルプ見なきゃですね(戒め)。
時間のかかる処理を含むテストを20個抽出
遅いサンプルを20個抜き出してみます。数字のオプションなしだとデフォルトで10個。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
$ bundle exec rspec --profile 20 spec/ ... Top 20 slowest examples (188.59 seconds, 53.1% of total time): test example1... 18.93 seconds ./spec/requests/some_webapi_pages_spec.rb:230 test example2... 15.71 seconds ./spec/requests/some_webapi_pages_spec.rb:232 test example3... 12.2 seconds ./spec/requests/some_webapi_pages_spec.rb:109 test example4... 10.08 seconds ./spec/requests/some_webapi_pages_spec.rb:90 test example5... 9.36 seconds ./spec/lib/some_webapi_spec.rb:32 test example6... 8.75 seconds ./spec/requests/some_webapi_pages_spec.rb:203 test example7... 8.75 seconds ./spec/requests/some_webapi_pages_spec.rb:205 ... Finished in 5 minutes 55 seconds 319 examples, 11 failures |
なんと遅い20個のテストだけで全体の53%強を占めるという結果。しかも、ほとんど同じテストファイル(/spec/requests/some_webapi_pages_spec.rb)に含まれてます。それで profiling に以下が含まれていて分かったのですが、外部APIを叩く自作ライブラリの処理が遅い原因の1つだろう。
1 2 3 |
9.36 seconds ./spec/lib/some_webapi_spec.rb:32 |
lib/some_webapi.rb で外部ウェブサービスのAPIを利用する処理を作ったのですが、この自作ライブラリのテストだけで10秒近くかかっているのが分かりました。jsonレスポンスが返ってくるのに時間がかかるのですよね…。some_webapi_pages_spec.rb の該当箇所は、このライブラリの処理を含んでいるので結果的に処理が当然遅くなる。
RSpec の –profile オプションで遅い処理を含むテストを抽出できたので、該当する部分のコードを重点的にリファクタリングして処理速度の改善を行おうと思います。また、外部API叩く箇所など毎回テストに含めると時間がかかって辛いので、普段は該当のテストをコメントアウト、もしくは以下の skip: true の設定を利用しよう。
RSpecで普段は実行したくないテストをスキップする方法 – Qiita
改めて Myron Marston さん、ありがとうございました。
- RSpec の関連記事
- FactoryGirlをSpringと共に使う時の注意
- 複数モデルのpost :createをテストするRSpecコード(Controller Spec)
- RSpec3でTime.nowをスタブ化(stub)
- RSpecでJSONによるPOSTリクエストをテスト
- RSpec & Capybara の雑感
- RSpec+Capybaraで同名の複数要素の並び順をテストする
- RSpec3ではrails_helper.rbがrequireされる
- Capybara + Launchy で RSpec テストをブラウザで確認
- CapybaraのwithinをRSpecで使う
- Serverspec(RSpec)のテスト出力に色を付けて見やすくフォーマット
Leave Your Message!