大規模なRailsアプリケーションでのRSpecテストの高速化


90

私のRSpecテストには、2,000を超える例を含むRailsアプリケーションがあります。言うまでもなく、これは大規模なアプリケーションであり、テストする必要があることがたくさんあります。この時点でこれらのテストを実行することは非常に非効率的であり、非常に時間がかかるため、新しいビルドをプッシュする前にテストを作成することはほとんどお勧めできません。spec.optsに--profileを追加して、実行時間が最も長いサンプルを見つけました。実行に平均10秒かかるサンプルが少なくとも10個あります。あなたのRSpecエキスパートの間でそれは正常ですか?一例として、10秒は完全に長すぎますか?2,000の例を使用すると、すべてを完全にテストするにはかなりの時間がかかることがわかりますが、現時点では4時間は少し馬鹿げています。

最長の実行例については、どのようなときに見ていますか?ボトルネックを特定してスピードアップを図るために、既存の仕様をトラブルシューティングするにはどうすればよいですか。この時点では、毎分本当に役に立ちます。


1
遅いテストは統合テストですか?彼らはdbを打っていますか?もしそうなら、どのくらいの頻度でdbがリロードされ、dbをモックできますか?
Kaleb Pederson、2010

1
SeattleRBの自動テストのように、取り組んでいる部分に関連する仕様の一部だけを実行できますか?すべてのテストを実行できる継続的インテグレーションサーバーはありますか?
Andrew Grimm

すべてのものは相対的であることを覚えておいてください。「grrr、私たちのテストスイートは永遠にかかる」と20分...と16-20時間の両方で聞いたことがあります。それはすべて見る人の目にあります。多くの場合、特定のテストの10秒は、以下に示すように統合テストになった単体テストを意味します。
Michael Durrant 2013

この種の問題に対する提案:perftools.rbテストフレームワークと一緒に使用して、ほとんどの時間を使い果たしているものを理解します。上位10件の電話に出て、それらを排除/スキムしてみてください。その後、幸せになるまで繰り返します。
aledalgrande

回答:


118

10秒は、単一のテストを実行するには非常に長い時間です。私の直感は、仕様ターゲットが単体テストと統合テストの両方を同時に実行していることです。これは、プロジェクトが陥る典型的なことであり、ある段階で、より多く、より速く生産したい場合は、この技術的負債を克服する必要があります。これを行うのに役立ついくつかの戦略があります...そして、私が過去に使用したいくつかをお勧めします。

1.ユニットを統合テストから分離する

私が最初に行うことは、ユニットを統合テストから分離することです。次のいずれかの方法でこれを行うことができます。

  1. それらを(specディレクトリーの下の別個のフォルダーに)移動し、rakeターゲットを変更する
  2. タグを付ける(rspecを使用すると、テストにタグを付けることができます)

哲学は、あなたはあなたの定期的なビルドを速くしたいということです-そうでなければ、人々はそれらを頻繁に実行するのにあまりにも幸せではないでしょう。だから、その領域に戻ります。通常のテストをすばやく実行し、継続的インテグレーションサーバーを使用して、より完全なビルドを実行します。

統合テストは、外部の依存関係(データベース、WebService、キュー、および一部はFileSystemを主張するものなど)を伴うテストです。単体テストは、チェックしたい特定のコード項目をテストするだけです。高速で実行する必要があります(45秒で9000が可能です)。つまり、ほとんどがメモリで実行されます。

2.統合テストを単体テストに変換する

単体テストの大部分が統合テストスイートよりも小さい場合は、問題があります。これは、矛盾がより簡単に現れ始めることを意味します。したがって、ここから、統合テストに代わるユニットテストの作成を開始します。このプロセスを支援するためにできることは次のとおりです。

  1. 実際のリソースの代わりにモックフレームワークを使用します。Rspecには組み込みのモックフレームワークがあります。
  2. 単体テストスイートでrcovを実行します。これを使用して、単体テストスイートの徹底度を測定します。

統合テストを置き換える適切な単体テストができたら、統合テストを削除します。重複したテストは、メンテナンスを悪化させるだけです。

3.備品を使用しないでください

備品は悪です。代わりにファクトリー(マニシストまたはfactorybot)を使用してください。これらのシステムでは、より適応性の高いデータのグラフを作成できます。さらに重要なのは、外部データソースからデータを読み込むのではなく、使用できるメモリ内オブジェクトを作成できることです。

4.統合テストになる単体テストを停止するためのチェックを追加する

これでより高速なテストを実施できたので、これを阻止するためのチェックを再度行う時間です。

データベース(UnitRecord)にアクセスしようとしたときにエラーをスローするアクティブパッチをサルパッチするライブラリがあります。

また、ペアリングとTDDを試すこともできます。これにより、チームはより高速なテストを強制的に作成できます。

  1. 誰かがチェックしている-だれも怠惰にならない
  2. 適切なTDDには迅速なフィードバックが必要です。テストが遅いと、全体が苦痛になります。

5.他のライブラリを使用して問題を解決する

誰かがspork(rails3の下のテストスイートのロード時間を短縮する)、hydra / parallel_tests-ユニットテストを並列に(複数のコア間で)実行することについて言及しました。

これはおそらく最後に使用する必要があります。あなたの本当の問題は、ステップ1、2、3にあります。それを解決すれば、追加のインフラストラクチャをロールアウトするためのより良い立場になります。


すばらしい答えです。悪いテストを迅速に実行するのに役立つ高度なツールがないことは非常に事実です。だから良いものだけ書いてみてください。
Yura Omelchuk

5
フィクスチャを使用すべきではないという3番目の点には同意しません。適切に使用すれば、オブジェクトを作成する必要がないため、ファクトリよりも高速です。データがあるので、テストケースごとにデータを作成する必要はありません。
wallerjake 2014

3
工場の高速化についてのこれは冗談ですよね?
Mike Szyndel 2014年

ファクトリー・ガールの回避により選択的にスピードアップテスト- robots.thoughtbot.com/...
geekdev

16

テストスイートのパフォーマンス向上に関する優れたクックブックについては、Grease Your Suiteプレゼンテーションをご覧ください

彼は、次のような手法を利用することにより、テストスイートの実行時間を45倍高速化することを文書化しています。


リンクは好きですが、プレゼンテーションは好きではありません。誰かのスピーチのインデックスカードは、スピーカーがプレゼンテーションの要点を記入するためのプロンプトです。
Brian Maltzan

このプレゼンテーションは終了しました。fast_contextは、複数のshouldaブロックを高速化します。quickerclip(リンクも無効)は明らかにPaperclipを高速化します。Hydraは、parallel_testsおよびGorgonでは非推奨です。bootsnapにはファイルシステムの微調整があり、Railsに含まれています。Rubyの最近のバージョンでは、割り当てとGCが改善されています。
担当者による

5

Sporkを使用できます。2.3.xをサポートしています。

https://github.com/sporkrb/spork

または./script/spec_server 2.xで動作する可能性があります

また、データベース構成を編集することもできます(データベースクエリなどを本質的に高速化します)。これにより、テストのパフォーマンスも向上します。


Sporkは素晴らしいです。Rails 3でも動作し、少しハッキングされています。ただし、Spork on Rails 3で注意すべき点の1つは、コントローラーの変更を反映していないように見えるため、頻繁に再起動する必要があることです。とにかく、スポークは本当に素晴らしいです、テストの速度の改善は非常に重要です。
AboutRuby

4
Sporkは起動を高速化するためだけのもので、テストのためのものではありません。したがって、多くの仕様では、利点は重要ではありません。
Reactormonk

上記のコメントに反して、railscast railscasts.com/episodes/285-sporkのように、起動と同様にテストを高速化するためにsporkを使用できます。非常に大きなアプリでのrspecテストスイートを大幅に改善しました。(192秒から10秒に短縮!)
jamesc

3

例あたり10秒は非常に長い時間のようです。1秒以上かかるスペックは見たことがなく、ほとんどがはるかに短いです。ネットワーク接続をテストしていますか?データベースは書き込みますか?ファイルシステムは書き込みますか?

モックとスタブは可能な限り使用してください- データベースにヒットするコードを書くよりもはるかに高速です。残念ながら、モックやスタブも書き込みに時間がかかります(正しく行うのが困難です)。テストの作成に費やした時間とテストの実行に費やした時間のバランスをとる必要があります。

テストスイートの並列化を可能にする可能性のあるCIシステムの調査に関するAndrew Grimmのコメントの2番目です。そのサイズの場合、それが唯一の実行可能な解決策かもしれません。


ええ、10秒だったら、プロファイルを作成してボトルネックがどこにあるかを確認します
rogerdpack

1
私は巨大なプロジェクトを抱えており、1回のrspecテストの実行には15〜20秒かかります。
ExiRe 2013

2

何人かの人々が上記のハイドラについて言及しました。過去に大成功を収めてきました。最近、ヒドラを起動して実行するプロセスを文書化しました:http : //logicalfriday.com/2011/05/18/faster-rails-tests-with-hydra/

この種の手法は、デフォルトで適切に構造化された高速なテストを作成する代わりに使用すべきではないという意見に同意します。





弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.