Search code examples
javatestng

How to rerun skipped tests in testNG?


I am using TestNG for my tests. In some tests, test data gets generated so in afterMethod I am checking if extra data was generated. If so I delete it. But sometimes for any reason data removing request doesn't return a successful response and I got an exception. In this case, all next test cases in class will be skipped. Is there a way to do not skip the remaining tests in the class if some exception was gotten in AfterMethod? Or Is it possible to re-run skipped tests?

@AfterMethod(alwaysRun = true)
public void clearData() throws Exception {
    throw new Exception();
}

@Test
public void testOne() {
    //Do something
}

@Test
public void testTwo() {
    //Do something
}

Solution

  • try-catch would be the best solution, because any exceptions generated out of the methods should be handled by that method instead of the testng framework.

    @AfterMethod
    public void clearData() throws Exception {
        try{
            // do something....
        } catch(Exception e) {
            // do nothing....
        }
    }
    

    But it is possible to re-run the skipped test with a little workaround (a long one! ). (Note: I would still suggest the try-catch approach).

    Create an AfterSuite method with alwaysRun set to true.

    public class YourTestClass {
        private static int counter = 5; //desired number of maximum retries
        
        // all your current code.......
        
        @AfterSuite(alwaysRun = true)
        public void afterSuite(ITestContext ctx) {
            IResultMap skippedTests = ctx.getSkippedTests();
    
            while(skippedTests.size() > 0 && (counter--) > 0) {
                List<XmlInclude> includeMethods
                    = skippedTests.getAllMethods()
                                  .stream()
                                  .map(m -> new XmlInclude(m.getMethodName()))
                                  .collect(Collectors.toList());
                XmlClass xmlClass = new XmlClass(this.getClass().getName());
                xmlClass.setIncludedMethods(includeMethods);
                
                XmlTest test = ctx.getCurrentXmlTest();
                List<XmlClass> classes = test.getXmlClasses();
                classes.remove(0);
                classes.add(xmlClass); 
    
                TestRunner newRunner = new TestRunner(new Configuration(),
                                                      ctx.getSuite(),
                                                      test,
                                                      false,
                                                      null,
                                                      new ArrayList<>());
                newRunner.run();
    
                Set<String> newPassed = newRunner.getPassedTests().getAllResults()
                                                 .stream()
                                                 .map(ITestResult::getName)
                                                 .collect(Collectors.toSet());
                IResultMap passedTests = ctx.getPassedTests();
                Iterator<ITestResult> iter = skippedTests.getAllResults().iterator();
                while(iter.hasNext()) {
                    ITestResult result = iter.next();
                    if(newPassed.contains(result.getName())) {
                        result.setStatus(ITestResult.SUCCESS);
                        passedTests.addResult(result, result.getMethod());
    
                        //remove the test from list of skipped tests.
                        iter.remove();
                    }
                }     
            }
        }
    }