わかりました。おそらく@BeforeClassなどで簡単に指定できるプロパティが必要なことはわかっていますが、実装されるまで待つ必要があるかもしれません。少なくとも私もそれを見つけることができませんでした。
次は地獄のように醜いですが、私はそれが少なくとも小規模ではうまくいくと思います、それはより複雑なシナリオでどのように振る舞うかを確認するために残されています。おそらくもっと時間があれば、これはより良いものに改善することができます。
さて、私はあなたに似たテストクラスを作成しました:
public class RetryTest extends TestConfig {
public class RetryTest extends TestConfig {
Assertion assertion = new Assertion();
@Test( enabled = true,
groups = { "retryTest" },
retryAnalyzer = TestRetry.class,
ignoreMissingDependencies = false)
public void testStep_1() {
}
@Test( enabled = true,
groups = { "retryTest" },
retryAnalyzer = TestRetry.class,
dependsOnMethods = "testStep_1",
ignoreMissingDependencies = false)
public void testStep_2() {
if (fail) assertion.fail("This will fail the first time and not the second.");
}
@Test( enabled = true,
groups = { "retryTest" },
retryAnalyzer = TestRetry.class,
dependsOnMethods = "testStep_2",
ignoreMissingDependencies = false)
public void testStep_3() {
}
@Test( enabled = true)
public void testStep_4() {
assertion.fail("This should leave a failure in the end.");
}
}
Listener
これを他のクラスに拡張したい場合に備えて、スーパークラスにがありますが、テストクラスでリスナーを設定することもできます。
@Listeners(TestListener.class)
public class TestConfig {
protected static boolean retrySuccessful = false;
protected static boolean fail = true;
}
上記の4つのメソッドのうち3つにはがありRetryAnalyzer
ます。私が次にtestStep_4
それをやっていることが残りの実行を台無しにしないことを確認するためにそれなしで残しました。上記RetryAnalyzer
は実際には再試行しません(メソッドがを返すことに注意してくださいfalse
)が、次のことを行います。
public class TestRetry implements IRetryAnalyzer {
public static TestNG retryTestNG = null;
@Override
public boolean retry(ITestResult result) {
Class[] classes = {CreateBookingTest.class};
TestNG retryTestNG = new TestNG();
retryTestNG.setDefaultTestName("RETRY TEST");
retryTestNG.setTestClasses(classes);
retryTestNG.setGroups("retryTest");
retryTestNG.addListener(new RetryAnnotationTransformer());
retryTestNG.addListener(new TestListenerRetry());
retryTestNG.run();
return false;
}
}
これにより、実行の中に実行が作成されます。レポートが乱れることはなく、終了するとすぐにメインの実行が続行されます。しかし、そのグループ内のメソッドを「再試行」します。
はい、わかっています。これは、テストスイートを永遠のループで永遠に実行することを意味します。それが理由RetryAnnotationTransformer
です。その中で、これらのテストの2回目の実行からRetryAnalyzerを削除します。
public class RetryAnnotationTransformer extends TestConfig implements IAnnotationTransformer {
@SuppressWarnings("rawtypes")
@Override
public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
fail = false; // This is just for debugging. Will make testStep_2 pass in the second run.
annotation.setRetryAnalyzer(null);
}
}
今、私たちは最後の問題を抱えています。元のテストスイートは、そこでの「再試行」の実行について何も認識していません。これは本当に醜いところです。何が起こったのかをレポーターに伝える必要があります。そして、これは私があなたに改善するよう勧める部分です。もっと良いことをする時間が足りないのですが、できればいつか編集します。
まず、retryTestNGの実行が成功したかどうかを知る必要があります。これを改善する方法はおそらく100万通りありますが、現時点ではこれでうまくいきます。実行を再試行するためだけにリスナーを設定しました。TestRetry
上でそれを見ることができ、それは以下で構成されています:
public class TestListenerRetry extends TestConfig implements ITestListener {
(...)
@Override
public void onFinish(ITestContext context) {
if (context.getFailedTests().size()==0 && context.getSkippedTests().size()==0) {
successful = true;
}
}
}
メインスイートのリスナー(上記のスーパークラスでTestConfig
見たもの)は、実行が発生したかどうか、正常に実行されたかどうかを確認し、レポートを更新します。
public class TestListener extends TestConfig implements ITestListener , ISuiteListener {
(...)
@Override
public void onFinish(ISuite suite) {
if (TestRetry.retryTestNG != null) {
for (ITestNGMethod iTestNGMethod : suite.getMethodsByGroups().get("retryTest")) {
Collection<ISuiteResult> iSuiteResultList = suite.getResults().values();
for (ISuiteResult iSuiteResult : iSuiteResultList) {
ITestContext iTestContext = iSuiteResult.getTestContext();
List<ITestResult> unsuccessfulMethods = new ArrayList<ITestResult>();
for (ITestResult iTestResult : iTestContext.getFailedTests().getAllResults()) {
if (iTestResult.getMethod().equals(iTestNGMethod)) {
iTestContext.getFailedTests().removeResult(iTestResult);
unsuccessfulMethods.add(iTestResult);
}
}
for (ITestResult iTestResult : iTestContext.getSkippedTests().getAllResults()) {
if (iTestResult.getMethod().equals(iTestNGMethod)) {
iTestContext.getSkippedTests().removeResult(iTestResult);
unsuccessfulMethods.add(iTestResult);
}
}
for (ITestResult iTestResult : unsuccessfulMethods) {
iTestResult.setStatus(1);
iTestContext.getPassedTests().addResult(iTestResult, iTestResult.getMethod());
}
}
}
}
}
}
レポートには、(再試行された)合格した3つのテストと、他の3つのテストの一部ではなかったために失敗した1つのテストが表示されます。
私はそれがあなたが探しているものではないことを知っていますが、TestNGに機能を追加するまで役立つことを支援します。