Search code examples
javaunit-testingautomated-teststestngjava-threads

TestNG: How to link IConfigurationListener2.beforeConfiguration ITestResult to ITestListener.onTestStart


I have 2 TestNG listeners which report logging information to a log file for debugging information. These are IConfigurationListener2 and ITestListener. The test run in multiple threads.

My issue is that I need to link the ITestResult in the IConfigurationListener2.onConfigurationFailure() method to the ITestListener.onTestStart() ITestResult to retrieve the @Test ITestResult.getMethodName(). Is this possible?

TestListener Code is:

public class TestListener implements ITestListener{
    @Override
    public void onTestStart(ITestResult result) {       
        System.out.println("Starting test method:" + result.getMethod().getMethodName());
    }
}

IConfigurationListener2 is:

public class ConfigurationListener implements IConfigurationListener2 {
    @Override
    public void onConfigurationFailure(ITestResult result) {
        System.out.println("Failed to run " + result.getMethod().getMethodName()
            + " for the test method:" + <code needed>);
}

The TestNG Class is:

public class Script1 {

private int i =0;
@BeforeMethod
public void before(){
    System.out.println("Starting before");
    i++;
    if (i==1){
        throw new RuntimeException("forcing an exception");
    }
}

@Test(testName="script1")
public void script1_run(){
    System.out.println("Running script");
}

@Test(testName="script2")
public void script2_run(){
    System.out.println("Running script");
}
}

So how do I find out which @Test method the @beforeMethod failed for. I would like the log something like this:

Starting before
Starting test method:script1_run
Running script
Starting before
Failed to run before for the test method: script2_run

Thanks,


Solution

  • You need to merge your 2 listeners:

    public class MyNewListener implements IConfigurationListener2, ITestListener {
    
      private final ThreadLocal<ITestResult> currentTest = new ThreadLocal<>();
    
      @Override
      public void onTestStart(ITestResult result) {
        System.out.println("Starting test method:" + result.getMethod().getMethodName());
        currentTest.set(result);
      }
    
      @Override
      public void onConfigurationFailure(ITestResult result) {
        System.out.println("Failed to run " + result.getMethod().getMethodName()
                + " for the test method:" + currentTest.get().getMethod().getMethodName());
      }
    }
    

    The ThreadLocal is used to keep track across the parallel run.

    Disclaimer: I didn't test the listener in real life. Tell me if it is working or not.

    Edit: Tests are supposed to be skipped after a failed configuration method

    public class MyNewListener implements IConfigurationListener2, ITestListener {
    
      private final ThreadLocal<ITestResult> failedConfiguration = new ThreadLocal<>();
    
      @Override
      public void onTestStart(ITestResult result) {
        System.out.println("Starting test method:" + result.getMethod().getMethodName());
      }
    
      @Override
      public void onConfigurationFailure(ITestResult result) {
        failedConfiguration.set(result);
      }
    
      @Override
      public void onTestSkipped(ITestResult result) {
        System.out.println("Failed to run " + failedConfiguration.get().getMethod().getMethodName()
                + " for the test method:" + result.getMethod().getMethodName());
      }
    }