How to Change a Test Name When Using TestNG DataProvider

Hello everybody, One of the great features of TestNG is TestNG DataProvider. TestNG DataProvider simply provides a way to run one test with different data with multiplying the test code. General usage is like below:

public class DataProviderChangeName{

   @DataProvider(name = "role")
   public static Object[][] roles() {
       return new Object[][] {{"Developer"},{"Team Lead"},{"QA"},{"Business Analyst"},{"DevOps Eng"},{"PMO"} };
   }

   @Test(dataProvider = "role")
   public void createUser(String role) {
// some testing stuff
   }
}

Whenever you run that test, you will have a report with 6 execution results and the name of the test are always the same cause we execute. You will only see the parameters that have been sent to the test function. But in case you implement a reporting mechanize, you never see those parameters because testNG get the test name during execution. You will get lost in the results.

TestNG provides us a way to change the test name during execution. Then how we implement it?

First, create a Thread Local String object to store your test case name.

private ThreadLocal<String> testName = new ThreadLocal<>();

Secondly, implement a BeforeMethod function to override your test name before the execution.

@BeforeMethod
public void BeforeMethod(Method method, Object[] testData){
   testName.set(method.getName() + "_" + testData[0]);
}

Third, you need to implement ITest interface into your test. After implementing it, it will tell you to override getName() method. This where you get the test name, so we need to modify this one.

@Override
public String getTestName() {
   return testName.get();
}

Finally, run your test, you will realize that the test name is fetched by our overridden getTestName() method.

Sample Source Code

package util;

import org.testng.ITest;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.lang.reflect.Method;

public class DataProviderChangeName implements ITest {

   private ThreadLocal<String> testName = new ThreadLocal<>();

   @DataProvider(name = "role")
   public static Object[][] roles() {
       return new Object[][] {{"Developer"},{"Team Lead"},{"QA"},{"Business Analyst"},{"DevOps Eng"},{"PMO"} };
   }

   // 1. Verify create staff invitations (Doctor) with valid authToken and parameters (Positive scenario)
   @Test(dataProvider = "role")
   public void createUser(String role) {

   }

   @BeforeMethod
   public void BeforeMethod(Method method, Object[] testData){
       testName.set(method.getName() + "_" + testData[0]);
   }

   @Override
   public String getTestName() {
       return testName.get();
   }

But this change will only affect TestNG’s built-in reports. In case you are using 3rd party library like ExtentReports to generate test execution reports. You need to do one more thing to show this modified name in your reports.

Pass a ITestContext object to your @BeforeMethod and use setAttribute to set modified name in to the context object. You should make an if-else condition incase the name is not changed because some tests don’t use DataProvider so the name is not changed.

@BeforeMethod
public void BeforeMethod(Method method, Object[] testData, ITestContext ctx) {
   if (testData.length > 0) {
      testName.set(method.getName() + "_" + testData[0]);
      ctx.setAttribute("testName", testName.get());
   } else
      ctx.setAttribute("testName", method.getName());
}

Then in your reporting class, you need to get the modified name via iTestResult object by using below usage.

@Override
public void onTestStart(ITestResult iTestResult) {

    testWatcher.set(extent.createTest(iTestResult.getTestContext().getAttribute("testName").toString()));

}

Thanks.
Canberk Akduygu

22 thoughts on “How to Change a Test Name When Using TestNG DataProvider”

  1. Hi,
    Thank you for the explanation. But while using above example I am getting the same test-instance-name=”PMO” for all the test-method in testng-results.xml. How I will be able to get the test-method name as the name of my dataprovider value in the testng-results.xml

    Reply
  2. Hi,
    Thank you for the explanation, but while using the above example I am getting the same value in test-instance-name of test-method in testng-results.xml file for all the different value parameter of data-provider.

    What I am expecting is the test-method should display name or test-instance-name differently so that test failure can be identified easily.
    Thanks in advance.

    Reply
  3. I should definitely see a sample project. The one I describe above is a real life project and it’s working fine. May be you can create a simple project in github and we can solve the problem.

    Reply
  4. I will try to do that but my question is even if I try to run the source code provided by you above testng-results.xml file is generating same test-instance-name i.e. test-instance-name=”PMO”(which the last object of data provider) and same name i.e. name=”createUser” for the the class test-method parameters.

    Reply
  5. Thank you for your reply. I have been taking help from different blogs and StackOverflow but unsuccessful. Please help me to find the solution. This is something which I tried.

    public class DataProviderChangeName implements ITest {
    private static ThreadLocal testNames = new ThreadLocal(){
    @Override
    protected String initialValue() {
    return “”;
    }
    };

    @Test (dataProvider = “dp”)
    public void testMethod(int number, String text) {
    String txt = “Thread Id [” + Thread.currentThread().getId() + “] with value (” + number + “,” + text + “)”;
    testNames.set(txt);
    }

    @DataProvider (name = “dp”)
    public static Object[][] getData() {
    return new Object[][] {
    {1, “Poetry”},
    {2, “Novels”},
    {3, “TextBooks”}
    };
    }

    @Override
    public String getTestName() {
    return testNames.get();
    }
    }

    Looking forward for your reply.
    Thanks in advance

    Reply
  6. Actually, whenever I trigger the tests via suite.xml names are changing in html report but I have problem with gradle test command. That might be an issue with TestNG version. We should investigate on TestNG github page

    Reply
  7. Hi Thank you!

    @Override
    public void onTestStart(ITestResult iTestResult) {

    testWatcher.set(extent.createTest(iTestResult.getTestContext().getAttribute(“testName”).toString()));

    }

    I can”t find testWatcher, can you tell me how to invoke testWatcher , Thanks.

    Reply
  8. Hi, I have a question related to the article written by you.I tried your solution but didn’t worked for me, may be I would have done something wrong.
    I have posted my query on stackoverflow and haven’t received any response yet, here is the link for the same:

    https://stackoverflow.com/questions/56776684/is-there-any-way-to-show-my-dataprovider-values-in-testng-report-summary

    Can you please answer the same either on the comments here or on the stackoverflow it would be a great help.
    Looking forward,
    Thanks in advance.

    Reply
  9. If DataProvider is set in parellel , then all the threads are getting same name (name of the first test)
    how to fix this? Please help

    Reply
  10. Thanks a lot for providing this interesting example.

    Can you please tell me how I could achieve this using Allure reports not Extent?
    I assume I would need to change something here:

    @Override
    public void onTestStart(ITestResult iTestResult) {

    testWatcher.set(extent.createTest(iTestResult.getTestContext().getAttribute(“testName”).toString()));

    }

    Also, would appreciate a github repo is one is available.

    Thanks!

    Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.