web-dev-qa-db-ja.com

あるテストを別のテストの結果に依存させる方法は?

他の多くのクラスによってコード内で使用されるいくつかの一般的な静的メソッドeverywhereを提供するユーティリティクラスがあるとしましょう。

ユーティリティテストのいずれか1つが合格しなかった場合にテストが失敗するように、ユーティリティのコンシューマ用のユニットテストをどのように設計しますか?あなたはそれを行うことができますか、またはユーティリティクラスのテストがすべてグリーンであるかどうかを自分で確認する必要がありますか?

たとえば、メッセージパーサーによって使用されるメッセージスプリッターユーティリティ(またはその出力)があります。メッセージパーサーがテストされる前に、メッセージスプリッターが正しく動作することを確認したいのですが。

両方のテストを作成しましたが、それらをリンクして、1つのテストを他のテストの結果に依存させる方法はありますか?

これに適したタグが見つかりませんでしたが、Visual Studioの単体テストエンジンを使用しています。

13
t3chb0t

システムのすべての欠陥がトリップすることを確認しても意味がありません正確に 1つのテスト。

テストスイートには1つの仕事があります。既知の欠陥がないことを確認することです。欠陥がある場合、1つのテストが失敗しても10でも問題ありません。テストスイートの失敗に慣れている場合、プログラムの「悪い」程度を評価しようとすると失敗したテストのカウント、正しい方法で回帰テストを使用していない。テストスイートは、コードを公開する前にallテストに合格する必要があります。

テストをスキップする唯一の有効な理由は、それらが不完全な機能をテストするおよびが、それらを実装する際に、より適切に使用できるように非常に時間がかかる場合です。テストすることになっています。 (これは、厳密なテスト駆動型開発を実践しない場合にのみ問題になりますが、結局それは有効な選択です。)

それ以外の場合は、テストスイートをインジケーターにして、何が悪いのかを正確に伝えるようにしないでください。正確ではありませんし、そうであるとは限りません。それはあなたが二度同じ過ちを犯すことからあなたを守ることになっています、それはすべてです。

11
Kilian Foth

それはあなたのツールに依存しますが、おそらくできない(そしてすべきではない)

一部のユニットテストフレームワーク(たとえば PHPUnit を使用)では、1つのレベルで失敗したテストが他のテストを実行しないようにテストを「チェーン」できます。ただし、これでこの状況の問題が解決されるとは思いません。

保証されたテスト順序の実行を許可しないことは、テストを互いに分離することを強制し、一般に良いことと考えられています。テストがそれ自体で実行されるだけでなく、他のテストが機能するためのデータも提供するとしたらどうなるか想像してみてください...

これらのユーティリティメソッドを別のソリューションまたはテストカテゴリに配置できます。テストランナーで視覚的に「目立つ」ことを確認します。または、このカテゴリのテストが失敗した場合に、このカテゴリが最初に実行され、他のテストを実行しないようにします*。これらのテストの1つが失敗すると、失敗はおそらくすべてのテストにまたがって発生します。まず、これらの失敗したテストを修正することにより、テストを実行する人が誰でも開始できることを確認できるようにしてください。単体テストと統合テストについても同様です。ユニットテストが失敗すると、カスケードされ、統合テストであらゆる種類の騒乱を引き起こします。ユニットと統合のテストが失敗したとき、ユニットテストをチェックすることから始めることを誰もが知っています...

*自動化されたビルドまたはテストスクリプトを使用すると、最初にこのカテゴリを実行し、結果を確認して、この最初のテストバッチに合格した場合にのみ他のテストを実行できます。

8
JDT

単体テストをアトミックにしてみてください。自動テストコードもコードベースの一部ですが、それ自体はテスト中ではないため、できるだけシンプルでわかりやすいものにしてください。

より直接質問に答えるために、テストの実行順序は保証されていないため、他のテストが実行される前にユーティリティテストが成功することを保証する方法もありません。したがって、すべてのテストに単一のテストスイートを使用しながら、希望どおりの結果を得る保証された方法はありません。

ユーティリティを独自のソリューションに移動して、現在のプロジェクトで結果のDLLへの参照を追加できます。

5
Thorsal

要約すると、ツール/テクニックを使用して、本来の目的以外のことをしたくありません。

あなたがしようとしていることは、CI(継続的インテグレーション)プラクティスで簡単に解決できる懸念のように聞こえます。

このようにして、既に提案されているようにテストをアトミックに保ち、CIにテストの検証を任せることができます。

テストが失敗した場合は、コードが公開されないように設定できます。

4
AvetisG

私は常にアプリケーションレベルのコードとフレームワークレベルのコードを区別しようとする傾向があるため、頻繁に説明している問題に遭遇しました。通常、すべてのフレームワークレベルのコードをテストしてから、アプリケーションレベルのコードのテストを開始します。 。また、フレームワークレベルのコード内であっても、他のすべてのフレームワークモジュールで使用される基本的なフレームワークモジュールが存在する傾向があり、基本に何かが失敗した場合、他のものをテストしても意味がありません。

残念ながら、テストフレームワークの提供者は、自分の作品がどのように使用されるかについてある程度固いアイデアを持っている傾向があり、それらのアイデアを保護する傾向があります。一方、フレームワークを使用する人々は、質問せずに意図した使用法を受け入れる傾向があります。これは実験と革新を阻害するため、問題があります。私は他の誰についても知りませんが、私は奇妙な方法で何かをしようとする自由を持ち、結果が確立された方法よりも良いか悪いかを自分自身で確認したいのです。そもそも自分のやり方で物事を行う。

したがって、私の意見では、テストの依存関係はすばらしいものであり、その代わりに、テストが実行される順序を指定する機能が次善の策となるでしょう。

テストの順序付けの問題に対処するために私が見つけた唯一の方法は、テストフレームワークがテストをアルファベット順に実行する傾向を利用するために、慎重に名前を付けることです。

これがVisual Studioでどのように機能するかはわかりません。C#を使用した広範なテストに関係することはまだ何もしていないためですが、Java側では、次のように機能します。ソースフォルダーの下通常、プロジェクトには2つのサブフォルダーがあり、1つは「main」と呼ばれ、1つは本番コードを含み、もう1つは「test」と呼ばれ、テストコードを含みます。「main」の下には、私たちのパッケージ階層に正確に対応するフォルダー階層があります。ソースコードJavaパッケージはおおよそC#名前空間に対応しています。C#では、フォルダー階層を名前空間階層に一致させる必要はありませんが、そうすることをお勧めします。

ここで、Javaの世界で通常行うことは、「test」フォルダの下にあるということですmirror「main」フォルダの下にあるフォルダ階層。テストは、テストするクラスとまったく同じパッケージに存在します。この背後にある理由は、テストクラスがテスト中のクラスのパッケージプライベートメンバーにアクセスする必要があることが多いため、テストクラスはテスト中のクラスです。世界のC#側では、名前空間ローカルの可視性などは存在しないため、フォルダー階層をミラーリングする理由はありませんが、C#プログラマーは、構造化において同じ原則に従うと思います彼らのフォルダ。

いずれにせよ、私は実装ではなくインターフェイスをテストする傾向があるため、テストクラスがテスト対象のクラスのパッケージローカルメンバーにアクセスできるようにするというこの全体的な考えが間違っています。したがって、テストのフォルダー階層は、実稼働コードのフォルダー階層をミラーリングする必要はありません。

したがって、私が行うことは、テストのフォルダー(つまり、パッケージ)に次のように名前を付けることです。

t001_SomeSubsystem
t002_SomeOtherSubsystem
t003_AndYetAnotherSubsystem
...

これにより、「SomeSubsystem」のすべてのテストが「SomeOtherSubsystem」のすべてのテストの前に実行され、さらに「AndYetAnotherSubsystem」などのすべてのテストの前にすべて実行されることが保証されます。

フォルダ内では、個々のテストファイルには次の名前が付けられます。

T001_ThisTest.Java
T002_ThatTest.Java
T003_TheOtherTest.Java

もちろん、最新のIDEには強力なリファクタリング機能があり、パッケージ全体(およびすべてのサブパッケージとそれらを参照するすべてのコード)を数回のクリックとキーストロークで名前変更できるので非常に役立ちます。

4
Mike Nakis