javatestingtestngdataprovider

TestNG dataprovider skip after fail


For example I have code for test

@Test(dataprovider = "getData")
public void test(String data) {
    //perform some action using 'data'
}

@DataProvider
public Object[][] getData(){
    return new Object[][]{
        {"One"},
        {"Two"},
        {"Three"},
        {"Four"},
        {"Five"}
    };      
}

For example test with data {"Three"} will be failed. I need that tests for {"Four"}, {"Five"} will skipped or failed(if {"Three"} was failed). How can I do that? Thanks.


Solution

  • Note: This solution will not work when you try to run your data driven tests in parallel. This will only work if you run your data driven tests in sequential order.

    Here's how you can do this.

    1. Make sure you are using TestNG 7.0.0-beta1 (This is the latest released version as of today Dec 16 2018)
    2. Have your test class implement org.testng.IHookable interface.
    3. Now within the run() method set a boolean flag to indicate that downstream methods should be failed, if you found an exception (TestNG by default marks a test method as failed if it raises an exception)

    Below is a sample that shows all of this in action.

    import java.util.Arrays;
    import org.testng.Assert;
    import org.testng.IHookCallBack;
    import org.testng.IHookable;
    import org.testng.ITestListener;
    import org.testng.ITestResult;
    import org.testng.annotations.DataProvider;
    import org.testng.annotations.Listeners;
    import org.testng.annotations.Test;
    
    @Listeners(TestReporter.class)
    public class TestclassExample implements IHookable {
      private boolean hasFailures = false;
    
      @Test(dataProvider = "getData")
      public void test(String data) {
        if (data.equals("Three")) {
          Assert.fail("Simulating a failure for [" + data + "]");
        }
        System.err.println("executing test  for data [" + data + "]");
      }
    
      @DataProvider
      public Object[][] getData() {
        return new Object[][] {{"One"}, {"Two"}, {"Three"}, {"Four"}, {"Five"}};
      }
    
      @Override
      public void run(IHookCallBack callBack, ITestResult testResult) {
        if (hasFailures) {
          testResult.setStatus(ITestResult.FAILURE);
        } else {
          callBack.runTestMethod(testResult);
          if (testResult.getThrowable() != null) {
            hasFailures = true;
          }
        }
      }
    
      public static class TestReporter implements ITestListener {
    
        @Override
        public void onTestFailure(ITestResult result) {
          String msg =
              String.format(
                  "[%s()] failed for data %s",
                  result.getMethod().getMethodName(), Arrays.toString(result.getParameters()));
          System.err.println(msg);
        }
      }
    }
    

    Here's the output for the above code execution.

    executing test  for data [One]
    executing test  for data [Two]
    [test()] failed for data [Three]
    
    [test()] failed for data [Four]
    
    [test()] failed for data [Five]
    
    java.lang.AssertionError: Simulating a failure for [Three]
    
        at org.testng.Assert.fail(Assert.java:97)
        at com.rationaleemotions.stackoverflow.qn53781839.TestclassExample.test(TestclassExample.java:21)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:131)
        at org.testng.internal.MethodInvocationHelper$1.runTestMethod(MethodInvocationHelper.java:237)
        at com.rationaleemotions.stackoverflow.qn53781839.TestclassExample.run(TestclassExample.java:36)
        at org.testng.internal.MethodInvocationHelper.invokeHookable(MethodInvocationHelper.java:249)
        at org.testng.internal.Invoker.invokeMethod(Invoker.java:654)
        at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:792)
        at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1103)
        at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:140)
        at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:122)
        at org.testng.TestRunner.privateRun(TestRunner.java:739)
        at org.testng.TestRunner.run(TestRunner.java:589)
        at org.testng.SuiteRunner.runTest(SuiteRunner.java:398)
        at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:392)
        at org.testng.SuiteRunner.privateRun(SuiteRunner.java:354)
        at org.testng.SuiteRunner.run(SuiteRunner.java:302)
        at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
        at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96)
        at org.testng.TestNG.runSuitesSequentially(TestNG.java:1145)
        at org.testng.TestNG.runSuitesLocally(TestNG.java:1067)
        at org.testng.TestNG.runSuites(TestNG.java:997)
        at org.testng.TestNG.run(TestNG.java:965)
        at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:73)
        at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:123)
    
    
    ===============================================
    Default Suite
    Total tests run: 5, Passes: 2, Failures: 3, Skips: 0
    ===============================================