リストのテスト…同じテストですべてですか、それとも各条件に対して1つのテストですか?


21

リストで期待されていることを関数が実行することをテストしています。だから私はテストしたい

f(null) -> null
f(empty) -> empty
f(list with one element) -> list with one element
f(list with 2+ elements) -> list with the same number of elements, doing what expected

そうするために、最善のアプローチは何ですか?

  • 「WorksAsExpected」という名前で、同じ(メソッド)テストですべてのケースをテストする
  • 各ケースに1つのテストを配置し、こうして
    • 「WorksAsExpectedWhenNull」
    • 「WorksAsExpectedWhenEmpty」
    • 「WorksAsExpectedWhenSingleElement」
    • 「WorksAsExpectedWhenMoreElements」
  • 私が考えていなかった別の選択肢:-)


2
それらを別々のテストケースとして作成します。テストシステムでサポートされている場合は、パラメーター化されたテストを使用できます。
jonrsharpe

5
あなたのテストが与えられたとき... ...次にスタイルで書く場合、それは...自明彼らが実際に個別にテストする必要があることになり
ロビーディー

1
追加したいのは、IMO、エッジケース(nullやemptyなど)を別々のテストに分離するのは良いことです。これらは異なる実装の可能性がある特殊なケースのロジックを伴うことが多いためです。テスト中のコードがどのように失敗するか(深く掘り下げたり、テストケースをデバッグして何が起こっているかを把握する必要はありません)。
フィリップミロヴァーノヴィッチ

1
重複した要素のリスト?
atayenel

回答:


30

1つのテストケースで一連のテストを実行するか、多くのテストを実行するかについて、私が使用する簡単な経験則は、セットアップが1つだけかどうかです。

そのため、複数の要素について、それらすべてを処理し、正しい結果を導き出すことをテストしていた場合、2つ以上のアサートがある可能性がありますが、リストを一度セットアップするだけで済みます。したがって、1つのテストケースで問題ありません。

ただし、あなたの場合、nullリスト、空のリストなどを設定する必要があります。それは複数の設定です。したがって、この場合は必ず複数のテストを作成します。

他の人が述べたように、それらの「複数のテスト」は、単一のパラメーター化されたテストケースとして存在できる可能性があります。つまり、さまざまなセットアップデータに対して同じテストケースが実行されます。これが実行可能な解決策であるかどうかを知る鍵は、テストの他の部分、「アクション」と「アサート」にあります。各データセットで同じアクションを実行してアサートできる場合は、このアプローチを使用します。ifたとえば、データのさまざまな部分に対してさまざまなコードを実行するためにを追加する場合、これは解決策ではありません。後者の場合は、個別のテストケースを使用します。


14

トレードオフがあります。1回のテストでより多くのパックを作成すればするほど、オニオンエフェクトを通過させようとします。つまり、最初の失敗でそのテストが停止します。最初の失敗を修正するまで、他のアサーションについては知りません。そうは言っても、セットアップコードを除いてほとんど同じような単体テストの束を持つことは、書かれたものとそうでないものを見つけるためだけに多くの忙しい仕事です。

フレームワークに基づいて可能なツール:

  • 理論。理論により、一連のデータに関する一連の事実をテストできます。次に、フレームワークは、フィールドまたはデータを生成する静的メソッドによって、複数のテストデータシナリオをテストに提供します。あなたの事実のいくつかがある前提条件に基づいて適用され、他の条件が適用されないなら、これらのフレームワークは仮定の概念を導入します。あなたはAssume.that()それが前提条件に失敗した場合、単純にデータのためのテストをスキップします。これにより、「期待どおりの動作」を定義し、単純に多くのデータをフィードできます。結果を表示すると、親テストのエントリがあり、次に各データのサブエントリがあります。
  • パラメータ化されたテスト。パラメーター化されたテストは理論の前兆であったため、理論で行うことのできる前提条件のチェックがない場合があります。最終結果は同じです。結果を表示し、テスト自体の親エントリがあり、次に各データポイントの特定のエントリがあります。
  • 複数のアサートを持つ1つのテスト。セットアップにかかる時間は短くなりますが、少しずつ問題を発見することになります。テストが長すぎて、テストされるシナリオが多すぎる場合、2つの大きなリスクがあります。実行に時間がかかり、チームがそれにうんざりして、テストをオフにします。
  • 同様の実装による複数のテスト。アサーションが異なる場合、テストはオーバーラップしないことに注意することが重要です。ただし、これはTDDに重点を置いたチームの従来の知恵です。

assertテストには1つのステートメントしか存在できないという厳密な考え方ではありませんが、すべてのアサートが単一のアクションの事後条件をテストするという制限を設けています。テスト間の唯一の違いがデータである場合、私はパラメーター化されたテストや理論のようなより高度なデータ駆動テスト機能を使用することを考えています。

オプションを比較検討して、最良の結果を判断してください。「WorksAsExpectedWhenNull」は、要素の数が異なるコレクションを扱う場合とは根本的に異なると言います。


5

これらは異なるテストケースですが、テストのコードは同じです。したがって、パラメータ化されたテストを使用することが最善のソリューションです。テストフレームワークがパラメーター化をサポートしていない場合は、共有コードをヘルパー関数に抽出し、個々のテストケースから呼び出します。

1つのテストケース内のループを介したパラメーター化を避けるようにしてください。これにより、エラーの原因となったデータセットを特定することが困難になります。

TDDの赤、緑、リファクタリングサイクルでは、一度に1つのサンプルデータセットを追加する必要があります。複数のテストケースをパラメーター化されたテストに結合することは、リファクタリング手順の一部になります。

かなり異なるアプローチは、プロパティのテストです。具体的な入力データを指定せずに、関数のさまざまなプロパティをアサートするさまざまな(パラメーター化された)テストを作成します。たとえば、プロパティは次のようになります。すべてのリストxsについて、リストのys = f(xs)長さはと同じxsです。テストフレームワークは、興味深いリストとランダムリストを生成し、プロパティがそれらすべてを保持していると断言します。手動で例を選択すると、興味深いエッジケースを見逃す可能性があるため、これは手動での例を指定することから離れます。


最後の文の「ミス」は「見つける」べきではありませんか?
ロビーディー

@RobbieDee英語はあいまいで、修正されています。
アモン

3

各テストで単一の概念をテストすることは、多くの場合推奨される優れたガイドラインであるため、各ケースに1つのテストを用意することが適切です。

この投稿を参照してください:単一の単体テストで複数のアサートを使用しても大丈夫ですか?。関連する詳細な議論もあります:

私のガイドラインは、通常、テストごとに1つの論理CONCEPTをテストすることです。同じオブジェクトに複数のアサートを持つことができます。通常、それらはテストされる同じ概念になります。 ソース-Roy Osherove

[...]

テストは1つの理由でのみ失敗するはずですが、それは常に1つのAssertステートメントが存在することを意味するわけではありません。私見では、「アレンジ、アクト、アサート」パターンを保持することがより重要です。

重要なのは、アクションが1つしかないこと、そしてアサートを使用してそのアクションの結果を検査することです。ただし、「アレンジ、アクト、アサート、テスト終了」です。別のアクションを実行してテストを続行し、その後さらにアサートする場合は、代わりに別のテストを作成します。ソース


0

私の考えでは、テスト条件に依存します。

  • テストにテストをセットアップする条件が1つしかないが、多くの副作用がある場合。マルチアサートは許容されます。
  • ただし、複数の条件がある場合は、複数のテストケースがあることを意味し、それぞれが1つのユニットテストのみでカバーされる必要があります。

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