web-dev-qa-db-ja.com

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

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

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」
  • 私が考えていなかった別の選択:-)
21
malarres

一連のテストを1つのテストケースで実行するか、多数のテストケースで実行するかについて、私が使用する単純な経験則は次のとおりです。

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

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

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

30
David Arno

トレードオフがあります。 1つのテストでパックする数が多いほど、タマネギの効果が合格する可能性が高くなります。言い換えれば、最初の失敗はそのテストを停止させます。最初の失敗を修正するまで、他のアサーションについてはわかりません。とは言っても、セットアップコードを除いてほとんど同じような単体テストがたくさんあるのは、書かれている作業とそうでない作業があることを見つけるためだけに多くの忙しい作業です。

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

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

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

最良の結果が何であるかを決定するためにオプションを比較検討してください。 「WorksAsExpectedWhenNull」は、要素の数が異なるコレクションを処理する場合とは根本的に異なると言います。

14
Berin Loritsch

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

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

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

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

5
amon

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

この投稿を参照してください: 1つの単体テストで複数のアサートを設定しても問題ありませんか? 。関連する詳細な議論もあります:

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

[...]

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

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

3
sonny

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

  • テストに設定する条件が1つしかないが、多くの副作用がある場合。マルチアサートは許容されます。
  • ただし、複数の条件がある場合、つまり複数のテストケースがある場合は、それぞれが1つの単体テストのみでカバーされる必要があります。
0
HungDL