Đượ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ó Listener
lớ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_4
mà 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 RetryAnalyzer
sẽ 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ó ở TestRetry
trê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 TestConfig
sẽ 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:
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.