5

次の単体テスト ケースのソリューション/パターンを探しています。

ケース:

それぞれ 1 つのメソッドを持つ 3 つのクラス A、B、C があるとします。A のメソッドは、C のメソッドを呼び出す B のメソッドを呼び出します。つまり、A->B->C です。各メソッドは 1 つの入力 (メソッド A の入力 A、入力 B、入力 C) を取ります。メソッド A の呼び出しの結果の出力は、次のようなツリー構造になります。

ルート (方法 A から作成) -- ノード B (方法 B から作成) -- ノード C1 -- ノード C2 (いずれも方法 C から作成)

私にとって単体テストとは、メソッドの入力からの出力を分離してテストすることです。したがって、上記の各メソッドの単体テストを作成します。テストは分離して記述されるため、メソッド A の単体テストを記述するときはメソッド B をモックし、メソッド B の単体テスト ケースを記述するときはメソッド C をモックします。

これまでのところ、すべて問題ありません。各メソッドの出力に期待値を書き込んで、結果のツリー構造が尊重されるようにすることができます。

問題:

メソッド B を呼び出す別のクラスを追加して、D->B->C という呼び出しチェーンも持つようにします。結果のルート ツリーは次のようになります。

  • ルート D
    • ノード B
      • ノード C1
      • ノード C2

開発中に、メソッド A の要件が誤解されており、ツリーの結果が次のようになるはずだったことに誰かが気づきました。

  • 根A
    • ノード B
      • ノード C

幸いなことに、開発者はメソッド C を変更して、出力が 2 つではなく 1 つのノードのみを返すようにします。彼は、それらの変更を反映するように単体テストを変更します。ただし、メソッド D の要件は変更されていないはずであり、そのメソッドの出力にはまだノード C1 とノード C2 が含まれているはずです。

質問:

2 番目の開発者がメソッド D に導入した破壊的変更について警告を受けるようにするには、単体テストをどのように記述しますか? ここで最も適していると思われる統合テストは避けたいと思います。

ありがとう。

4

3 に答える 3

2

「純粋な¹」単体テスト、不純な単体テスト、統合 (外部リソース ヒッティング) テスト、フル スタック テスト (UI ダウン) を組み合わせる必要があります。「純粋な」単体テストはテストの終わりではありません。

そのため、開発する機能ごとに、次のような種類のテストが行​​われることになります。

  • 単体テスト - 単独で A をヒット - 下位レベルが複雑であるか、外部リソースにヒットする場合。
  • 単体テスト (ただし、統合テストまたはコンポーネント テストとも呼ばれます) - 外部リソース (データベースなど) の前の (ほぼ) レベルまで A を押します - 下位レベルが複雑であるがテストされている場合、または下位レベルが複雑でない場合.
  • 統合テスト - A とデータベースをヒットします。
  • フル スタック テスト - ある時点でたまたま A を呼び出す UI をヒットします。このレベル (Cukes など) またはそれより下のレベルのいずれかで、少なくとも数個を目指します。

高レベルのテストがいくつかある限り、A 分離にヒットしたテストが失敗しなくても、それらは失敗するはずです。

¹「純粋な単体テスト」というフレーズを使用するだけで、単体テストの定義は分離された方法であると頭を悩ませている人もいます

于 2013-04-25T10:42:06.180 に答える
1

理想的には、単体テストはクラス C まで浸透する必要があります。単体テストは、必ずしも1 つのクラスで 1 つのメソッドを意味するわけではありません。ライブラリやデータベースなどの他の依存関係を必要とせずに実行できることを意味します。その後、統合テストが必要になります。

単体テストは C まで浸透する必要があります。A の要件が変更されると、単体テストが中断され、D の開発者は何かがおかしいことに気付きます。

于 2013-04-25T10:04:21.140 に答える
0

分離された単体テストに固執したい場合 (適切な深さで適切な量の統合テストを作成し、それらを高速に保つことはほぼ不可能であるため、中心的なオブジェクトのほとんどに対してこれを行います)、興味深いアプローチは Joe Rainsberger のContractです。およびコラボレーション テスト。彼は、その依存関係の具体的な実装が現実の世界でそのように動作することを保証する対応する契約テストがない限り、テストで何らかの動作をするために依存関係をモックアウトするべきではないという点を提起します。

あなたの例では、「メソッド C は 2 つではなく 1 つのノードのみを返すようになりました」ということは、C のコントラクトとそのコントラクト テストを適宜変更することを意味します。これにより、モックされた C が新しいコントラクトと同期しなくなる可能性が生じるため、C がモックされているすべてのテストを調べ、必要に応じてモックを調整する必要があります。

既存のテストを注意深く調べた後、メソッド C のコントラクトを実際に変更するのではなく、A のニーズに合った新しいメソッド C2 を導入する必要があることに気付くでしょう。

Rainsberger は、ここでテストでその互恵性を得ていることを確認するために使用するプロセスについて説明しています。このビデオで実際のテクニックを見ることもできます。

于 2013-04-25T17:53:49.217 に答える