2

テスト スイートで実行するいくつかの JUnit 4 テストに問題があります。

テストを個別に実行すると問題なく動作しますが、スイートで実行すると、ほとんどのテスト メソッド (テスト メソッドの 90%) がエラーで失敗します。私が気づいたのは、常に最初のテストは正常に機能しますが、残りは失敗するということです。もう 1 つの問題は、メソッドのいくつかのテストが正しい順序で実行されないことです (リフレクションが期待どおりに機能しないか、メソッドの取得が必ずしも作成された順序で行われるとは限らないため、機能します)。これは通常、同じ名前のメソッドを持つ複数のテストがある場合に発生します。いくつかのテストをデバッグしようとしましたが、ある行から次の行へといくつかの属性の値が になっているようですnull

何が問題なのか、または動作が「正常」であるかどうかを知っている人はいますか?

前もって感謝します。

PS: OK、テストは互いに依存していません。どれも依存しておらず、すべてが , , を@BeforeClass持っているため、テスト間ですべてがクリアされます。テストはデータベースで動作しますが、データベースは各テストの前にクリアされるため、これは問題になりません。@Before@After@AfterClass@BeforeClass

簡単な例:

テスト スイート:

import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
importy testclasses...;

@RunWith(Suite.class)
@Suite.SuiteClasses({ Test1.class, Test2.class })
public class TestSuiteX {
 @BeforeClass
 public static void setupSuite() { System.out.println("Tests started"); }   
 @AfterClass
 public static void setupSuite() { System.out.println("Tests started"); }   
}

テスト: このテストは、Glassfish で実行されているサーバー アプリケーションの機能をテストしています。

ここで、テストは、データベースとログインをクリアする @BeforeClass メソッドと、ログオフのみを行う @AfterClass を持つ基本クラスを拡張します。このクラスを導入する前に同じことが起こったので、これは問題の原因ではありません。

このクラスには、他のテストでは使用されない public static 属性がいくつかあり、2 つの制御メソッドを実装しています。

残りのクラスは、この例では基本クラスを拡張し、継承された制御メソッドをオーバーライドしません。

テストクラスの例:

    imports....

    public class Test1 extends AbstractTestClass {  
    protected static Log log = LogFactory.getLog( Test1.class.getName() );

    @Test
    public void test1_A() throws CustomException1, CustomException2 {

        System.out.println("text");

        creates some entities with the server api.
        deletes a couple of entities with the server api.

        //tests if the extities exists in the database
        Assert.assertNull( serverapi.isEntity(..) );

    }

}

そして2番目:

public class Test1 extends AbstractTestClass {

    protected static Log log = LogFactory.getLog( Test1.class.getName() );

    private static String keyEntity;
    private static EntityDO entity;

    @Test
    public void test1_B() throws CustomException1, CustomException2 {

        System.out.println("text");

        creates some entities with the server api, adds one entities key to the static attribute and one entity DO to the static attribute for the use in the next method.
        deletes a couple of entities with the server api.

        //tests if the extities exists in the database
        Assert.assertNull( serverapi.isEntity(..) );

    }

    @Test
    public void test2_B() throws CustomException1, CustomException2 {

        System.out.println("text");

        deletes the 2 entities, the one retrieved by the key and the one associated with the static DO attribute

        //tests if the deelted entities exists in the database
        Assert.assertNull( serverapi.isEntity(..) );

    }

これは基本的な例です。実際のテストはもっと複雑ですが、単純化されたテストで試してみましたが、それでもうまくいきません。ありがとうございました。

4

3 に答える 3

3

あなたが説明する状況は、副作用の問題のように聞こえます。テストは単独では正常に機能しますが、操作の順序に依存していると述べています。これは通常、重大な症状です。

テスト ケースのスイート全体を設定する際の課題の 1 つは、各テストをクリーンな状態から開始し、テストを実行してからクリーンアップし、すべてをクリーンな状態に戻すことを保証することです。

標準のクリーンアップ ルーチン (@Beforeおよび など@After) では不十分な場合があることに注意してください。しばらく前に発生した問題の 1 つは、一連のデータベース テストで発生しました。テストの一環としてデータベースにレコードを追加していて、追加したばかりのレコードを具体的に削除する必要がありました。

そのため、元の状態に戻すために特定のクリーンアップ コードを追加する必要がある場合があります。

于 2010-06-11T10:30:35.960 に答える
1

メソッドの実行順序が固定されていることを前提として、テスト スイートを作成したようです。これは誤りです。JUnit はテスト メソッドの実行順序を保証しないため、信頼するべきではありません。

これは設計によるものです。単体テストは互いに完全に独立している必要があります。これを保証するために、JUnit は各テスト メソッドを実行するためのテスト クラスの個別の新しいインスタンスを作成します。したがって、あるメソッドで設定した属性は、次のメソッドでは失われます。

共通のテスト セットアップ / ティアダウン コードがある場合は、@Before/で注釈を付けて別のメソッドに配置する必要があります@After。これらは、各テスト メソッドの前後に実行されます。

更新:あなたが書いた

@BeforeClass の各テストの前にデータベースがクリアされます

これがタイプミスでない場合、これが問題の原因である可能性があります。@BeforeDB はメソッドでクリアする必要があります@BeforeClass。クラスごとに 1 回だけ実行されます。

于 2010-06-11T10:29:57.463 に答える
0

@BeforeClass一度だけ設定する方法と、@Before個々のテストの前に設定する方法には注意してください。また、インスタンス変数には注意してください。

何がうまくいかないかの簡単な例を投稿していただければ、より具体的に支援できる場合があります。

于 2010-06-11T10:33:41.717 に答える