2

tdd 方式で実装する場合、クラスの内部についてアサートしますか、それともパブリック API についてのみアサートしますか?

バイナリヒープを実装しているとしましょう。オブジェクトを追加した後、ヒープのプロパティが保持されていることを主張したいと思います。リフレクションによって内部配列を取得し、その内容についてアサートするのは理にかなっていますか? すなわち

    @Test
    public void shouldPreserveHeapProperty() {
        // when
        heap.push(3);
        heap.push(2);
        heap.push(1);

        // then
        assertThat(Reflection.get(heap,"elements"))).contains(3,2,1);//made up Reflection class
    }

それともその公開APIによるものですか?ただし、テストごとに複数のアサーションが必要になります。

    @Test
    public void shouldPreserveHeapProperty() {
        // when
        heap.push(3);
        heap.push(2);
        heap.push(1);

        // then
        assertThat(heap.pop()).isEqualTo(3);
        assertThat(heap.pop()).isEqualTo(2);
        assertThat(heap.pop()).isEqualTo(1);
    }

さらに、並行コードのテストをどのように実装しますか? 内部ロックにアクセスせずにデッドロックや待機をシミュレートするのが非常に難しい場合があります。

4

1 に答える 1

1

APIのみを使用する必要があると思います。そうは言っても、パッケージ プライベート アクセスを使用して、テスト コードとフレンドリ クラスに、パブリックにする必要のある一部の項目への制限付きアクセスを与えることができます。

これを行うには、mutator メソッドをテストするために、オブジェクトの重要なプロパティにアクセスするためのいくつかの getter メソッドも必要になることがわかります。スタックの場合、プッシュ ミューテーターとポップ ミューテーターのみが必要な場合がありますが、テストの場合は、サイズ ゲッターがあると便利です。

このように自分自身を制限することは、自然に契約アプローチによるプログラミングにつながることがわかりました。これは良いことです。

クラスをリファクタリングする場合、プライベート データにアクセスするテストは面倒です。個人情報は必要に応じて簡単に変更できるはずですが、代わりにテスト コードも変更する必要があります。

サンプル テストでは、クラスがヒープ プロパティを保持していることを確認しようとします。これは、1 回のテストで確認できるものではありません。ヒープ プロパティは、プッシュとポップのすべてのシーケンスに対する制約です。1 回のプッシュの後に 1 回のポップ、および 2 回のプッシュの後に 2 回のポップで別のテスト ケースを作成してみてください。一緒に、それらは、クラスがすべてのシーケンスに対して正しいという帰納法による貧しい人の証明として機能します。

各テストにアサーションを 1 つだけ含める必要があるという考えは非常に一般的ですが、不必要で面倒です。コードをリファクタリングしていて、バグが発生する危険性がある場合、それらのバグを検出する可能性を最大限に高めたいと考えます。したがって、テストしている mutatir のすべての事後条件と、クラスのすべての不変条件をチェックする必要があります。これは非常に多くのアサーションになる可能性があるため、テスト ケースごとに複数のアサーションを使用することが唯一の実用的な方法です。

于 2013-09-11T07:40:05.380 に答える