2

広く使用されているいくつかのインターフェースのコントラクトテストを作成しようとしています。

の線に沿って:

public abstract class MyInterfaceContractTest extends TestCase {

  private MyInterface _toTest;

  public void setUp(){
    _toTest = getTestableImplementation();
  }

  protected abstract MyInterface getTestableImplementation();

  public void testContract(){

  }
}

...と...

public class MyInterfaceImplementationTest extends MyInterfaceContractTest {

  protected MyInterface getTestableImplementation(){
    return new MyInterfaceImplementation(...);
  }
}

ただし、の複数のインスタンスをテストできるようにしたいと思いますMyInterfaceImplementation。私のユースケースでは、これはデータのコレクションを含む不変のオブジェクトであり(インターフェイスごとにアクセサが指定されていますMyInterface)、空であるか、少量のデータ、または大量のデータが含まれている可能性があります。

したがって、問題は、実装の複数のインスタンスをどのようにテストできるかということです。

現時点では、実装を初期化して、抽象コントラクトテストに合格させる必要があります。1つのアプローチは、実装ごとに複数のテストクラスを用意することです。ここで、各テストクラスは、その実装の特定のインスタンスをテストしますが、それは少し膨大で、追跡するのが難しいようです。

FWIW、私はJUnit3を使用しています。

4

2 に答える 2

3

一般に、アプローチは、抽象クラスの「テスト可能な」サブクラスを使用して、1回のテストで抽象クラスのすべての機能をテストすることです。次に、具象クラスで定義/実装されたメソッドのみをテストする具象実装ごとに個別のテストを記述します(具象クラスの機能を再テストしないでください)。

于 2012-06-22T16:01:17.173 に答える
2

私があなたの必要性を正しく理解しているなら、あなたは同じテストメソッドまたは同じインターフェースの複数の実装を持つメソッドを実行したいと思うでしょう。

JUnit3でこれをうまく行う方法がわかりません。

JUnit 4にアップグレードする場合は、パラメーター化されたテストを使用してアップグレードできます。

インターフェイスの2つの実装で単一のテストメソッドを実行する簡単な例の場合、テストコードは次のようになります。

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.util.Arrays;
import java.util.Collection;

import static junit.framework.Assert.assertEquals;

// Tell JUnit4 to run it as a parametrized test.
@RunWith(Parameterized.class)
public class MyInterfaceContractTest {

    private MyInterface _toTest;

    // Load the test data into your test instance via constructor
    public MyInterfaceContractTest(MyInterface impl) {
        this._toTest = impl;
    }

    // Supply the test data, in this example just the two implementations you want to test.
    @Parameterized.Parameters
    public static Collection<Object[]> generateData() {
        return Arrays.asList(new Object[]{new MyInterfaceImpl1()}, new Object[]{new MyInterfaceImpl2()});
    }

    @Test
    public void testContract(){
        // assert whatever, using your _toTest field
    }
}

このテストを実行すると、JUnitはテストを2回実行し、パラメーターリストの連続するエントリを使用してコンストラクターを呼び出します。

さまざまな実装に対するさまざまな期待など、より複雑なものがある場合、データ生成は複数の要素を含むオブジェクト配列のリストを返す可能性があり、コンストラクターは対応する複数の引数を取ります。

テストメソッド間でテスト対象のオブジェクトを再初期化する必要がある場合は、この関連する質問で説明したトリックを使用することもできます。

TestNGでも同様のことが可能であると思います。これは、アップグレードパスのもう1つの選択肢になる可能性があります。

于 2012-06-22T22:54:33.293 に答える