5

単体テストのベスト プラクティスの 1 つは、各テストを他のすべてのテストから独立させることです。BoundedPriorityBlockingQueue カスタム クラスの add() メソッドをテストしたいとしましょう。

public void testAdd() {
    BoundedPriorityBlockingQueue q = BoundedPriorityBlockingQueue();
    q.add(1);
    assertEquals(1, q.size());
}

ご覧のとおり、現在testAddはsize()メソッドを使用しているため、それに依存していますが、size()が壊れているときにtestAdd()が失敗することは望ましくありません。この状況でのベストプラクティスは何ですか?

4

4 に答える 4

12

この状況でのベストプラクティスは何ですか?

テストはあなたに役立つものであり、その逆ではないことを心に留めておいてください。

何かがひどくうまくいかない場合、テストは壊れますか? はい。

問題がどこにあるかは明確になりますか?おそらく、使用sizeするものはすべて失敗することを考えると。

このテストは、テストしにくい設計へとあなたを駆り立てていますか? いいえ。

addこれは、実装の詳細の変更に直面しても堅牢なテストへの最も簡単なアプローチですか? おそらく。(もう一度値を取得できることをテストしたいと思います。念のため。)

はい、これは同じクラスの 2 つの部分をテストするようなものですが、それは問題ではないと思います。テストに関しては多くのドグマが見られます (「パブリック API のみをテストし、常に AAA を使用する」など)。私の経験では、そのドグマティズムを適切な量のプラグマティズムで和らげる必要があります。

于 2013-09-26T12:44:27.240 に答える
6

目標は、すべてのテスト メソッドを他のテストメソッドから独立させることであり、このメソッドは独立しています。他のテスト メソッドで何を行うかに関係なく、テスト対象のクラスのメソッドの操作に基づいて合格または不合格になります。

テスト中のクラスの別のメソッドが壊れている場合、このテストが失敗しても問題ありません。size()が壊れている場合は、複数のテストの失敗 (これと明示的にテストsize()するもの) が発生するため、問題がどこにあるかは明らかです。が壊れている場合add()、このテストのみが失敗します ( に依存する他のメソッドと同様add())。

于 2013-09-26T12:44:04.530 に答える
2

As others have already said, if your size method is broken the test will fail anyway so you have a reason there to investigate and understand why is that happening.

Anyway, if you are still interested on having such independence between your tests you could go for a white-box testing strategy: I guess that your BoundedPropertyBlockingQueue uses internally either any of the java.util collections, an array or an collection implementation from other provider (Guava, Apache Collections, etc) that you rely on so you don't need to verify that those structures work as they are expected to do.

So, define that internal structure as protected, place your test class in a package with the same name and, instead of relying on the implementation of the size method, go into the guts of the BoundedPropertyBlockingQueue:

BoundedPriorityBlockingQueue q = BoundedPriorityBlockingQueue();
q.add(1);
assertEquals(1, q.contents.size());  // assuming that `contents` attribute is a collection.

The main drawback is that now if your internal implementation of the queue changes, you'll need to change the test whilst with your previous test method you won't need to.

IMO I would chose your current implementation, is less coupled and, at the end, meets its goal.

于 2013-09-26T12:50:26.313 に答える
1

このようなクロステストを行うことに何の問題もありません- 一部のメソッドはペアで存在する傾向があり (追加/削除、エンキュー/デキューなど)、補完部分なしでテストすることはほとんど意味がありません。

addただし、メソッドがクライアント (クラス ユーザー) によってどのように使用されるかについて、もう少し考えてみたいと思います。ほとんどの場合、サイズが変更されたかどうかを判断するためだけに add を呼び出すのではなく、後で追加された項目を取得するために呼び出します。おそらく、テストは次のようになります。

BoundedPriorityBlockingQueue q = new BoundedPriorityBlockingQueue();
QueueItem toAdd = 1;
QueueItem added = q.dequeue();
assertEquals(toAdded, added);

それに加えて、上記のテストにガードアサートを追加することもできます(キューが既に追加されたいくつかのアイテムで開始しないことを保証するため) またはさらに良い -キューの初期状態を保証する別のテストを含めることもできます (サイズは 0、デキューは null/ を返します)。投げ)。

于 2013-09-26T13:31:42.227 に答える