TestNG의 @Test뿐만 아니라 완전한 클래스를 다시 실행


9

며칠 동안 스택 오버 플로우를 탐색하여 @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

질문을 수정하고 샘플을 첨부 한 후 기대치가 무엇인지 알려주십시오. 그것은 다른 사람들이 당신의 기대에 부응하는 답변을 줄 수 있도록 돕습니다.
Krishnan Mahadevan

@AndiCover 작동하지 않는 해결 방법 (또는 testNG 논리를 파괴하는 해결 방법)에 대한 링크 : 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. 여기에서 두 번째 테스트 실행에서 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에 기능을 추가 할 때까지 당신을 도와줍니다.


재시도 스위트가 발생하고 성공한 경우에만 최종 보고서를 업데이트하기 위해 기본 리스너에 조건을 추가하는 것을 잊었습니다. 지금 추가되었습니다.
Rodrigo Vaamonde '12
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.