Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

フレークテストスイートのケース

私は最近、信頼性が低いために使用するのが本当にイライラするテストスイートに取り組みました。

テストスイートが対象としていたアプリケーションは、RailsAPIのみのアプリケーションでした。テストは、「JSONRESTエンドポイントでエンドツーエンドのテストを実行するように設計されたAPIテストフレームワーク」であるChakramと呼ばれるフレームワークを使用してJavaScriptで記述されました。

テストスイートの問題は、それが決定論的ではなかったことでした。関数またはプログラムは、同じ入力が与えられた場合、常に同じ出力を提供する場合、決定論的です。

この特定のテストスイートは、アプリケーションコードまたはテストコードに変更を加えることなく、最初の実行に合格し、2回目の実行に合格し、3回目の実行で失敗します。

rake db:resetを実行することで、テストスイートを合格に戻すことができることを発見しました。 。テスト環境ではなく、Railsアプリケーションの開発環境で動作するテストは、テストスイートの実行が開始されたときにRailsアプリケーションのデータベースが特定の状態にあることに依存していました。

場合によっては、新しくシードされたデータベースから始めて、テストスイートを実行してから、テストスイートをもう一度正常に実行することができます。テストスイートを3回以上実行できるかもしれません。しかし、かなり頻繁に、テストスイートはどういうわけかデータを台無しにし、私は別のrake db:resetを実行する必要があります テストスイートが正常に使用できる状態にデータを戻すため。

もちろん、これはどうあるべきかではありません。テストスイートが失敗するのは、テストしているコードが正しく機能しなくなるという1つの理由だけです。

代わりに何をすべきか

したがって、このテストスイートが問題のある方法で設定された場合、それを行う正しい方法でしたか?

問題の根本は、テストスイートが人間によって手動で行われるデータベースのリセットに依存していたことでした。代わりに、テストスイート内の個々のテストは、実行する前にデータベースを自動的にクリーンで準備ができた状態にする必要があります。 (テストが実行後にデータベースをワイプして、データが他のテストに「リーク」しないようにすることも一般的です。これは、すべてのテストが実行前にデータベースをクリアする場合は厳密には必要ありませんが、優れた保護手段です。 )

テストスイートは、開発環境ではなく、Railsアプリケーションのテスト環境も対象にしている必要があります。開発環境での開発者のアクションは、テストスイートの作業と干渉してはなりません。その逆も同様です。

他のタイプの問題のある依存関係

私の話では、問題のある依存関係は、データベースが適切にクリーンアップされていなかったことでした。

問題のある依存関係のもう1つのタイプは、ネットワーク要求です。 TwilioAPIにヒットするテストスイートがあるとします。火曜日にテストスイートを実行すると、合格します。次に、水曜日に同じテストスイートを実行すると、失敗します。知らないうちに、Twilioが停止しているため、テストスイートが失敗しました。数分後、停止が解決され、テストスイートが再び合格します。

これは、テストが1つの理由でのみ失敗する必要があるという考えに戻ります。それは、アプリケーションコードが機能しなくなった場合です。

ネットワークと相互作用するコードのテストを作成する必要がある場合(Ruby / Railsを使用している場合)、それを行うためのより良い方法は、ネットワーク要求を記録し、実際に後で再生することなく、VCRなどのツールを使用することです。インターネットを使用します。

外部の依存関係に問題がない場合

アプリケーションがTwilioAPIに依存していて、Twilio APIがダウンした場合、アプリケーションは実際に壊れたため、テストは実際に失敗するはずであると主張することができます。このアイデアを、テストが外部条件に依存してはならないというアイデアとどのように調和させるのでしょうか?

これら2つのことを調整する方法は、統合テストを区別することです。 、複数のレイヤーまたはシステムを一緒にテストし、単体テスト 、単一の機能を個別にテストします。

チームが、特定のテストセットがネットワーク全体の外部サービスに影響を与え、複数のシステムを一緒にテストできるようにするという意識的な決定を下した場合、それについて「間違った」ことは何もありません。 (別の方法は、これらのシステムを一緒にテストしないことを決定することです。)このシナリオでは、チームは、ネットワークに依存する統合テストスイートが決定論的であることが保証されておらず、場合によってはフレークアウトする可能性があることに注意する必要があります。 。このようなテストスイートは、開発者がリグレッションをチェックするために毎日自分のマシンで実行する一連のテストとは別に存在する必要があります。

テストが外部条件に依存してはならないという規則には例外がありますが、ほとんどの場合、規則を遵守する必要があり、テストスイートに決定論的で信頼できるという利点があります。


  1. VCRGemを使用してテストスイートを改善する方法

    Rubyアプリケーションが何らかの外部APIを使用している場合は、おそらくテストとAPIレートの制限が遅いという問題に直面している可能性があります。 。 解決策は何ですか? クライアントライブラリからHTTPメソッドを手動でスタブし、事前に決定された応答を返すことができます。 しかし、それは多くの作業と醜いコードです! より良い解決策は、 Webmock+VCRのような宝石の強力な組み合わせを使用することです。 。 WebMockは、次のような一般的なHTTPライブラリからのHTTPリクエストをインターセプトします。 net / http ファラデー RestClient

  2. Rubyのケースステートメントの多くの用途

    if / elsifを使用する必要があるときはいつでも 代わりにRubyのcaseステートメントを使用することを検討できるステートメント。この投稿では、いくつかの異なるユースケースと、それが実際に内部でどのように機能するかを学びます。 注:他のプログラミング言語では、これはスイッチとして知られています。 ステートメント。 Rubyのcaseステートメントのコンポーネント: キーワード 説明 ケース ケースステートメントの定義を開始します。使用する変数を取得します。 いつ 一致する可能性のあるすべての条件は1つのwhenステートメントです。 その他 一致