web-dev-qa-db-ja.com

JUnitテストケースでの実行順序の指定

エンティティを追加、更新、削除するテストケースがあります。したがって、ここでは実行の順序が重要です。私はそれが欲しいです:

  1. 作成する
  2. 更新
  3. 削除する

奇妙なことに、1つのテストケース(15のうち)に対して、JUnitは次の順序で実行します。

  1. 削除する
  2. 更新
  3. 作成します。

特定の順序で実行するようにJUnitに指示するにはどうすればよいですか?それ以外の場合、JUnitは完全に正常に動作します(シリアルで実行)。そして、なぜこの1つのケースでJUnitが奇妙に振る舞うのですか?

以下の関連コードスニペット:

    private static Date date;
    private static int entity;
    static Parking p;
    public ParkingTests(String name) {
       super(name);
    }
    public void testAdd() throws Exception {
           //Add code here
    }
    public void testUpdate() throws Exception {
            //update code here
    }
    public void testDelete() throws Exception {
            //delete code here
    }
  }

奇妙になります。スイートの一部として多くのテストケースを実行しています。パーキングケースだけを実行する場合、順序は維持されます。他の人と一緒に実行すると、時々維持され、時には維持されません!

19
crazyaboutliv

あなたの種類の状況ぎこちないです。テストを分離するために作業を繰り返し続けるのは気分が悪いので(以下を参照)-しかし、複製はsetUptearDown@Before@After)メソッドを使用するため、余分なコードは必要ありません。テストの実行がそれほど遅くないために頻繁に実行を停止する場合は、クリーンテストの名前でCPUを少し浪費することをお勧めします。

public void testAdd() throws Exception {
      // wipe database
      // add something
      // assert that it was added
}
public void testUpdate() throws Exception {
      // wipe database
      // add something
      // update it
      // assert that it was updated
}
public void testDelete() throws Exception {
      // wipe database
      // add something
      // delete it
      // assert that it was deleted
}

別の方法は、複数のアサートを使用してすべてを1つのテストに固定することですが、これは理解と保守が難しく、テストが失敗した場合の情報が少し少なくなります。

public void testCRUD() throws Exception {
      // wipe database
      // add something
      // assert that it was added
      // update it
      // assert that it was updated
      // delete it 
      // assert that it was deleted
}

データベースやコレクション、またはあらゆる種類のストレージを使用したテストは、1つのテストがデータベース/コレクションにジャンクを残して他のテストに常に影響を与える可能性があるため、注意が必要です。テストが明示的に相互に依存していない場合でも、特にテストの1つが失敗した場合は、相互に干渉する可能性があります。

可能な場合、各テストに新しいインスタンスを使用するか、データを消去します。理想的には可能な限りシンプルな方法で-たとえばデータベースの場合、誤って間違ってしまう可能性のある非常に具体的な削除よりも、テーブル全体を消去する方が成功する可能性が高くなります。

更新:通常、テストの開始時にデータを消去する方が良いため、1回のテストの失敗は次の実行に影響しません。

18
DNA

一般に、junitテスト(テストメソッド)は互いに依存するべきではありません。以下は junit FAQ からのものです

各テストは独自のテストフィクスチャで実行され、他のテストによる変更からテストを分離します。つまり、テストはテストフィクスチャ内のオブジェクトの状態を共有しません。テストは分離されているため、任意の順序で実行できます......テストメソッドの呼び出しの順序は保証されていません。

したがって、いくつかの一般的な初期化を行いたい場合は、@Beforeアノテーションが付けられたメソッドでそれを行い、@Afterアノテーションが付けられたメソッドでクリーンアップを行うことができます。または、テストクラスのすべてのテストメソッドでその初期化が必要でない場合は、プライベートメソッドに入れて、テストから適切に呼び出すことができます。

余談ですが、まだテストの順序付けを行いたい場合は、TestNGをご覧ください。

19
Kuldeep Jain

テストの実行順序が必要であると判断した場合、JUnit 4.11は注釈によってこれをサポートするようになりました。詳細については this thread を参照してください-基本的には、

@FixMethodOrder

そのようにしていくつかのテスト順序を保証します。それはがっかりです。

12
eis

Java 7を使用している場合、JunitはJava.langから「Method [] getDeclaredMethods()」を使用してすべてのテストのリストを取得することを知っている必要があります。クラス。このメソッドのjavadocまたは次のjunitドキュメントから読み取ることができます。 "返される配列の要素はソートされておらず、特定の順序でもありません。」ですが、以前のjvm実装メソッドリストは、ソースコードにあったように順序付けられていました。

これは blog から取られたもので、彼は回避策を提供します。

7
Joshua Wilson

一般に、JUnitはテストケースの順序を保証しません。アルファベット順やファイル内の順序は保証されていません。テストの順序が重要である場合、前の出力に依存します。最初のものが失敗した場合はどうなりますか?後の(そして依存する)テストを気にする必要がありますか?おそらくない。

したがって、これがある場合:

@Test
public void first(){...}

@Test
public void second() {...}

@Test
public void third() {...}

それらがどの順番で実行されるかはわかりません。順番に進むことを望んでいるので、おそらく前のものが失敗しても2番目または3番目を実行する必要はないので、代わりにこれを実行できます。

@Test
public void firstThree(){
    first();
    second();
    third();
}

public void first(){...}
public void second() {...}
public void third() {...}

今回は@Testが1つだけであり、順序が保証されていることに注意してください。

5
mudd

「ソースコードに存在するのと同じように」順序でjunitテストを実行する場合は、この点に関する私のメモを参照してください。

ソースコードにあるとおりにjunitテストを実行する方法

しかし、それは本当に良い考えではありません。テストは独立している必要があります。

2
kornero

できること:

  • すべてのテストの前にデータベースをクリーンアップします
  • 最初に最初の論理演算をテストすることから始めます。あなたが十分な自信を持っているとき、それが正しいと仮定し、次へなどに移動します...
  • 最初にホワイトボックステストを記述しますが、ブラックボックステストから始めます。たとえば、データベースにトリガーなどがある場合は、それから始めます。
1
UmNyobe