1. ホーム
  2. ruby-on-rails

[解決済み] 大規模なRailsアプリケーションのRSpecテストを高速化する

2023-02-14 06:57:22

質問

私はRailsアプリケーションを持っており、RSpecのテストには2,000以上の例があります。言うまでもなく、大規模なアプリケーションであり、テストしなければならないことがたくさんあります。この時点でこれらのテストを実行するのは非常に非効率的で、時間がかかりすぎるため、新しいビルドをプッシュする前にテストを書くことを思いとどまるところまで来ています。spec.optsに-profileを追加して、最も長く実行される例を探したところ、少なくとも10個の例が平均10秒かかっています。RSpecの専門家の間では、これが普通なのでしょうか?1つのサンプルに10秒というのは長すぎるでしょうか?2,000 の例では、すべてを徹底的にテストするには自明ではない時間がかかると思いますが、この時点で 4 時間は少しばかばかしいです。

最も長く実行される例では、どのような時間がかかっているのでしょうか。ボトルネックを特定し、物事を高速化するために、既存の仕様をトラブルシューティングするために何ができるでしょうか。この時点では、1 分 1 秒でも早ければ本当に助かります。

どのように解決するのですか?

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

1. ユニットテストとインテグレーションテストを分離する

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

  1. それらを (spec ディレクトリの下の別々のフォルダに) 移動させる - そして rake ターゲットを修正する
  2. タグ付け (rspec ではテストにタグを付けることができます)

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

統合テストとは、外部の依存関係(データベース、Webサービス、キュー、およびファイルシステムなど)を含むテストです。単体テストは、チェックしたいコードの特定の項目をテストするだけです。テストは高速に実行されるべきで(45秒で9000は可能)、つまり、そのほとんどがメモリ内で実行されるべきです。

2. 統合テストをユニットテストに変換する

ユニットテストの大部分が統合テストスイートよりも小さい場合、問題があります。これは何を意味するかというと、矛盾がより簡単に現れ始めるということです。そこで、ここから、統合テストを置き換えるために、より多くのユニットテストを作成し始めます。このプロセスのためにできることは、以下の通りです。

  1. 実際のリソースの代わりにモッキングフレームワークを使用する。Rspecにはモッキングフレームワークが内蔵されています。
  2. ユニットテストスイートでrcovを実行します。あなたのユニットテストスイートがどの程度徹底しているかを評価するために使用します。

統合テストを置き換えるための適切なユニットテストができたら、統合テストを削除してください。重複したテストはメンテナンスを悪化させるだけです。

3. フィクスチャを使わない

什器は邪道です。代わりにファクトリー(machinistまたはfactorybot)を使ってください。これらのシステムは、データのより適応的なグラフを構築することができ、さらに重要なことに、外部のデータソースから物事をロードするのではなく、使用できるインメモリオブジェクトを構築することができるのです。

4. ユニットテストが統合テストにならないようにするためのチェックを追加する

さて、より高速なテストを実施することができたので、次はこのようなことが再び起こらないようにするためのチェックを入れる番です。

データベース(UnitRecord)にアクセスしようとしたときにエラーを投げるように、アクティブレコードをモンキーパッチするライブラリがあります。

また、ペアリングとTDDを試すこともできます。これは、チームがより速いテストを書くことを強制するのに役立ちますので。

  1. 誰かがチェックするので、誰も怠け者になりません。
  2. 適切なTDDには、速いフィードバックが必要です。遅いテストは全体を苦しめるだけです。

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

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

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