TestNGの@Testだけでなく、完全なクラスを再実行する


9

私は数日間、stackoverflowを閲覧しており、@Testステップだけでなく、テストクラス全体を再実行する方法を見つけようとしました。TestNGとIRetryAnalyzerではこれはサポートされていないと多くの人が言いますが、実際には機能しない回避策を投稿している人もいます。誰かがなんとかやっていますか?そして、その理由を明確にするために、意図的にサポートされていないという回答を避けるために:TestNGは、開発者だけのツールではありません。e2eテストのためにswテスターからも使用されることを意味します。E2eテストには、前のテストとは異なるステップを含めることができます。つまり、単純な@Testではなく、テストクラス全体を再実行することが有効ですIRetryAnalyzer。これは、を介して簡単に実行できます。

私が達成したいことの例は次のようになります:

public class DemoTest extends TestBase {

@Test(alwaysRun = true, description = "Do this")
public void testStep_1() {
    driver.navigate().to("http://www.stackoverflow.com");
    Assert.assertEquals(driver.getCurrentUrl().contains("stackoverflow)"));

}

@Test(alwaysRun = true, dependsOnMethods = "testStep_1", description = "Do that")
public void testStep_2() {
    driver.press("button");
    Assert.assertEquals(true, driver.elementIsVisible("button"));

}

@Test(alwaysRun = true, dependsOnMethods = "testStep_2", description = "Do something else")
public void testStep_3() {
   driver.press("button2");
Assert.assertEquals(true, driver.elementIsVisible("button"));

}

}

それtestStep_2が失敗したとしましょう、私は再実行class DemoTestしたいだけでなくtestStep_2


うまくいかない回避策を教えてください。
AndiCover

質問を編集し、サンプルを含めて、ご期待をお聞かせください。それは他の人があなたの期待に応える答えを与えるのを助けるのに大いに役立ちます。
クリシュナンマハ

仕事をしません(あるいはTestNGのロジックを破壊する回避策です)の回避策に@AndiCoverリンク:stackoverflow.com/questions/25781098/... stackoverflow.com/questions/50241880/... stackoverflow.com/questions/53736621/...
gandalf_the_cool

回答:


1

わかりました。おそらく@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に機能を追加するまで役立つことを支援します。


エラー:メインリスナーに条件を追加して、再試行スイートが発生して成功した場合にのみ最終レポートを更新することを忘れていました。今追加されました。
Rodrigo Vaamonde
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.