Chạy lại lớp hoàn chỉnh và không chỉ @Test trong TestNG


9

Tôi đã duyệt stackoverflow trong một số ngày, cố gắng tìm cách chạy lại toàn bộ lớp kiểm tra, và không chỉ là một @Testbước. Nhiều người nói rằng điều này không được hỗ trợ với TestNG vàIRetryAnalyzer , trong khi một số đã đăng tải cách giải quyết, điều đó không thực sự hiệu quả. Có ai quản lý để làm điều đó? Và chỉ cần làm rõ lý do cho việc này, để tránh những câu trả lời không có mục đích: TestNG là một công cụ không chỉ dành cho các nhà phát triển. Có nghĩa là cũng được sử dụng từ các trình kiểm tra sw để kiểm tra e2e. Các xét nghiệm E2e có thể có các bước phụ thuộc vào từng bước trước đó. Vì vậy, có hợp lệ để chạy lại toàn bộ lớp kiểm tra, thay vì đơn giản @Test, có thể dễ dàng thực hiện thông qua IRetryAnalyzer.

Một ví dụ về những gì tôi muốn đạt được sẽ là:

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"));

}

}

Hãy nói rằng testStep_2thất bại, tôi muốn chạy lại class DemoTestvà không chỉtestStep_2


Bạn có thể chỉ cho chúng tôi cách giải quyết không hiệu quả không?
AndiCover

Vui lòng chỉnh sửa câu hỏi của bạn, bao gồm một mẫu và cho chúng tôi biết những gì bạn mong đợi. Điều đó sẽ đi một chặng đường dài trong việc giúp đỡ người khác cho bạn một câu trả lời đáp ứng mong đợi của bạn.
Krishnan Mahadevan

@AndiCover Liên kết đến cách giải quyết mà không làm việc (hoặc là cách giải quyết mà phá hủy TestNG logic): stackoverflow.com/questions/25781098/... stackoverflow.com/questions/50241880/... stackoverflow.com/questions/53736621/...
gandalf_the_cool

Câu trả lời:


1

Được rồi, tôi biết rằng bạn có thể muốn một số tài sản dễ dàng mà bạn có thể chỉ định trong @B BeforeClass của mình hoặc một cái gì đó tương tự, nhưng chúng tôi có thể cần phải chờ đợi để thực hiện điều đó. Ít nhất tôi cũng không thể tìm thấy nó.

Sau đây là xấu như địa ngục nhưng tôi nghĩ rằng nó làm công việc, ít nhất là trong một quy mô nhỏ, nó còn lại để xem cách nó hành xử trong các kịch bản phức tạp hơn. Có thể với nhiều thời gian hơn, điều này có thể được cải thiện thành một cái gì đó tốt hơn.

Được rồi, vì vậy tôi đã tạo một Lớp kiểm tra tương tự như của bạn:

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.");
        }

    }


Tôi có Listenerlớp siêu chỉ trong trường hợp tôi muốn mở rộng lớp này sang các lớp khác, nhưng bạn cũng có thể đặt người nghe trong lớp kiểm tra của mình.

@Listeners(TestListener.class)
public class TestConfig {
   protected static boolean retrySuccessful = false;
   protected static boolean fail = true;
}


Ba trong số 4 phương pháp trên có a RetryAnalyzer. Tôi rời khỏi testStep_4mà không có nó để đảm bảo rằng những gì tôi đang làm tiếp theo sẽ không gây rối với phần còn lại của việc thực hiện. Nói RetryAnalyzersẽ không thực sự thử lại (lưu ý rằng phương thức trả về false), nhưng nó sẽ làm như sau:

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;
    }

}


Điều này sẽ tạo ra một thực thi bên trong thực thi của bạn. Nó sẽ không gây rối với báo cáo, và ngay khi nó kết thúc, nó sẽ tiếp tục với việc thực hiện chính của bạn. Nhưng nó sẽ "thử lại" các phương thức trong nhóm đó.

Vâng, tôi biết, tôi biết. Điều này có nghĩa là bạn sẽ thực hiện bộ thử nghiệm của mình mãi mãi trong một vòng lặp vĩnh cửu. Đó là lý do tại sao RetryAnnotationTransformer. Trong đó, chúng tôi sẽ xóa RetryAnalyzer khỏi lần thực hiện thứ hai của các thử nghiệm đó:

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);
    }

}


Bây giờ chúng tôi có vấn đề cuối cùng của chúng tôi. Bộ kiểm tra ban đầu của chúng tôi không biết gì về việc thực hiện "thử lại" ở đó. Đây là nơi nó trở nên thực sự xấu xí. Chúng tôi cần nói với phóng viên của chúng tôi những gì vừa xảy ra. Và đây là phần mà tôi khuyến khích bạn cải thiện. Tôi đang thiếu thời gian để làm một cái gì đó đẹp hơn, nhưng nếu tôi có thể, tôi sẽ chỉnh sửa nó vào một lúc nào đó.

Đầu tiên, chúng ta cần biết liệu thực thi retryTestNG có thành công hay không. Có thể có một triệu cách để làm điều này tốt hơn, nhưng bây giờ điều này hoạt động. Tôi thiết lập một trình nghe chỉ để thực hiện thử lại. Bạn có thể thấy nó ở TestRetrytrên, và nó bao gồm những điều sau đây:

public class TestListenerRetry extends TestConfig implements ITestListener {

    (...)

    @Override
    public void onFinish(ITestContext context) {
        if (context.getFailedTests().size()==0 && context.getSkippedTests().size()==0) {
            successful = true;
        }
    }

}

Bây giờ, Trình lắng nghe của bộ chính, bộ bạn đã thấy ở trên trong siêu hạng TestConfigsẽ xem liệu nó có chạy hay không và nó có hoạt động tốt không và sẽ cập nhật báo cáo:

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());
                    }

                }

            }

        }


    }

}

Báo cáo sẽ hiển thị 3 bài kiểm tra đã qua (khi chúng được thử lại) và một bài kiểm tra thất bại vì nó không phải là một phần của 3 bài kiểm tra khác:

Báo cáo cuối kỳ


Tôi biết đó không phải là thứ bạn đang tìm kiếm, nhưng tôi giúp nó phục vụ bạn cho đến khi họ thêm chức năng vào TestNG.


Rất tiếc .. Tôi đã quên thêm một điều kiện trong Trình nghe chính để chỉ cập nhật báo cáo cuối cùng nếu bộ Retry xảy ra và nó đã thành công. Đã thêm ngay bây giờ.
Rodrigo Vanhoe 11/12/19
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.