重新运行完整的类,而不仅仅是在TestNG中运行@Test


9

我浏览了几天的stackoverflow,试图找到如何重新运行整个测试类,而不仅仅是@Test一步。许多人说TestNG和并不支持此功能IRetryAnalyzer,而有些人已经发布了变通方法,但实际上并不起作用。有没有人设法做到这一点?只是为了阐明原因,以避免出现故意不支持的答案:TestNG不仅是针对开发人员的工具。这也被sw测试人员用于e2e测试。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

请编辑您的问题,包括样本并向我们展示您的期望。这将有助于帮助他人给您一个符合您期望的答案。
克里希南(Krishnan Mahadevan),

@AndiCover链接不工作(或者是破坏TestNG的逻辑的解决方法)的变通办法:stackoverflow.com/questions/25781098/... stackoverflow.com/questions/50241880/... stackoverflow.com/questions/53736621/...
gandalf_the_cool

Answers:


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没有使用它,以确保接下来要做的事情不会影响其余的执行。Said 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。在其中,我们将从那些测试的第二次执行中删除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执行是否成功。可能有上百万种方法可以更好地做到这一点,但目前行之有效。我为重试执行设置了一个侦听器。您可以在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个测试的一部分:

总结报告


我知道这不是您要寻找的东西,但是我会帮助您为他们服务,直到他们将功能添加到TestNG。


糟糕,我忘了在主侦听器中添加条件,以仅在重试套件发生并且成功的情况下才更新最终报告。现在添加。
罗德里戈·瓦蒙德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.