13

状況と問題点

いくつかのテスト クラスがあり、それぞれにいくつかのテスト メソッドがあります。すべてのテストは、バックグラウンドで同じテスト データベースを使用します。各テスト クラスはデータベースの内容を初期化し、いくつかのテスト メソッドで内容をテストします。

各テストを個別に実行すると、すべて合格します。しかし、(Maven または IDE、IntelliJ を使用して) 同時に複数のテストを実行すると、異なるテスト クラスのメソッドがインターリーブされて実行されます。2 番目のクラスのデータベースの初期化は、最初のクラスが開始された後、最初のクラスのすべてのテスト メソッドが実行される前に実行されるため、これらのメソッドは失敗します (データベースには既に 2 番目のクラスのデータが含まれているため)。

私が試したいくつかのこと、およびいくつかの詳細

最も簡単な解決策は、TestNG ランナーにクラスを連続して実行させることです (つまり、別のクラスのテスト メソッドを実行する前に、テスト クラスのすべてのテスト メソッドが終了するのを待ちます)。これはできますか?

スイートで各クラスを個別のテストとして指定することでおそらくこれを行うことができますが、不器用でエラーのあるテストクラスを追加するたびにスイートに何かを追加する必要があるため、これを行いたくありません-傾向があります。

TestNG に何も並列化しないように要求する (たとえば、スレッド カウントを 1 に設定する、または並列実行を無効にする) だけでは、メソッドが間違った順序で実行されるため (同時にではありません)、ここでは役に立ちません。

1 つのオプションは、テスト クラスごとに異なるデータベースを使用することですが、これを行う簡単な方法がわかりません (JPA と Guice を使用)。

現在、DBUnit、Unitils などは使用していません。これらのツールについてはよくわかりませんが、問題が解決しないという印象を受けました。

JPAを使用して、各テストクラスでデータベースを初期化しています(つまり、エンティティオブジェクトを作成して保存します)。

4

7 に答える 7

6

シーケンシャル モードでも、TestNG は同じスイートのテスト メソッドをインターリーブできます。@BeforeClass -> @Test -> @AfterClass のシーケンスを保証しますが、次のようなことができます。

before class1
    test class1.method1
before class2
    test class2.method1
    test class1.method2
after class1
    test class2.method2
after class2

解決策は、各クラスを異なるスイートに強制することです (これらは完全に順番に実行されます)。バージョン 2.16 の時点で、maven Surefire プラグインは各クラスを個別のスイートに配置するため、問題は修正されています。

一方、IDEA (最新の 13 EAP でさえ) は、同じスイート内のすべてのクラスを含む xml ファイルを生成します。願わくば、IDEA もこれに倣い、これも修正してくれることを願っています。インターリーブ テストは、データベースなどの共有リソースを操作する場合に問題になります。

于 2013-09-07T05:00:46.363 に答える
0

依存しているクラスのいずれかのテストメソッドが失敗すると、クラスがまったく実行されないため、クラスレベルでdependsOnGroupsを使用しません...これは、「dependsOn」グループを使用することの本当の欠点です(または方法)。最初に @Test(group = thisClassName) をクラス レベルで設定してから、testng.xml ファイルでテスト タグを使用してクラスを識別します。次に、これらのテストのリストとして xml で実行されるクラスの順序を制御します。xml の次の上位レベルのタグで PreserveOrder = "True" も設定する必要があると思います。依存関係のために本当に必要であるが、順序を制御するために必要でない場合を除いて、dependsOnの使用は避けます。お役に立てれば。-JR

于 2013-08-29T18:21:38.713 に答える
0

TestNG でテストをシーケンス化するいくつかの方法について説明した記事を書きました。

http://ancient-marinator.blogspot.com/2013/05/on-testing-scheduling-your-tests.html

当然のことながら、最良の情報源は自宅にあります: http://testng.org/doc/index.html

于 2013-06-24T12:52:47.627 に答える
0

これと同じ問題が発生しました。ほとんどの人は、dependsOn の使用が原因だと言っていますが、私たちの解決策は、いくつかのテストのテスト レベルで優先順位を設定することでした。テストが正しい順序で実行されるように、テストの優先順位を再設定するテスト リスナーをセットアップしました。これはhttps://github.com/cbeust/testng/issues/106の saberduck のソリューションに基づいてい ます。

このソリューションは、テストの優先度をクラスの優先度に連結することで保持します。

package testng_Listeners;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import org.testng.IAnnotationTransformer;
import org.testng.Reporter;
import org.testng.annotations.ITestAnnotation;

//Listener to fix TestNG Interleaving issue. I had to re-write this as the original example I had did not allow for priority to be manually set on a test level.
public class RePrioritizingListener implements IAnnotationTransformer {

HashMap<Object, Integer> priorityMap = new HashMap<Object, Integer>();
Integer class_priorityCounter = 10000;
// The length of the final priority assigned to each method.
Integer max_testpriorityLength = 4;

@Override
public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {


// class of the test method.
Class<?> declaringClass = testMethod.getDeclaringClass();
// Current priority of the test assigned at the test method.
Integer test_priority = annotation.getPriority();
// Current class priority.
Integer current_ClassPriority = priorityMap.get(declaringClass);

if (current_ClassPriority == null) {
    current_ClassPriority = class_priorityCounter++;
    priorityMap.put(declaringClass, current_ClassPriority);
}

String concatenatedPriority = test_priority.toString();

// Adds 0's to start of this number.
while (concatenatedPriority.length() < max_testpriorityLength) {
    concatenatedPriority = "0" + concatenatedPriority;
}

// Concatenates our class counter to the test level priority (example
// for test with a priority of 1: 1000100001; same test class with a
// priority of 2: 1000100002; next class with a priority of 1. 1000200001)
concatenatedPriority = current_ClassPriority.toString() + concatenatedPriority;

//Sets the new priority to the test method.
annotation.setPriority(Integer.parseInt(concatenatedPriority));

String printText = testMethod.getName() + " Priority = " + concatenatedPriority;
Reporter.log(printText);
System.out.println(printText);

}
}

また、リスナーを testng.xml に追加する必要があります

<suite name="Suite" configfailurepolicy="continue" >
<listeners>
<listener class-name="testng_Listeners.RePrioritizingListener"></listener>
</listeners>
于 2017-06-27T19:43:44.893 に答える