How to get data provider method from TestNG data provider name?

流过昼夜 提交于 2019-12-25 03:00:26

问题


Does anyone know how TestNG figures out what the data provider method is based on the data provider name specified for a test method?

I found this solution: https://gist.github.com/ae6rt/3805639

However, it doesn't take into account that the data provider could be:

  • defined in a completely different class, or
  • defined in a parent class, and
  • the method can be either static, or not static.

I tried to hack something together on my own, but then I figured that I can't possibly be the first person to try to solve the problem, especially because obviously TestNG must have a solution to that.

Does anyone know how TestNG does it, and how to get access to that business logic?

I'm trying to figure out the "total test count" at start up as discussed here: How to get total amount of tests (incl. taking data providers into account) at TestNG start?


回答1:


This might be a very late answer, but still posting it.

The below samples show how it can be done using TestNG. I am using TestNG 7.0.0-beta1 (latest released version as of today).

Scenario 1 : Data provider resides in the same class.

import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;

@Listeners(DataProviderTrackingListener.class)
public class DataProviderInSameClass {

  @Test(dataProvider = "dp")
  public void testMethod(int i) {
    System.err.println(i);
  }

  @DataProvider(name = "dp")
  public Object[][] getData() {
    return new Object[][] {{1}, {2}};
  }
}

Scenario 2 : Data provider resides in a base class.

import org.testng.annotations.DataProvider;

public class BaseClass {
  @DataProvider(name = "dp")
  public Object[][] getData() {
    return new Object[][] {{1}, {2}};
  }
}

import org.testng.annotations.Listeners;
import org.testng.annotations.Test;

@Listeners(DataProviderTrackingListener.class)
public class DataProviderInBaseClass extends BaseClass {

  @Test(dataProvider = "dp")
  public void testMethod(int i) {
    System.err.println(i);
  }
}

Scenario 3 : Data provider resides in a completely different class.

import org.testng.annotations.Listeners;
import org.testng.annotations.Test;

@Listeners(DataProviderTrackingListener.class)
public class DataProviderInDifferentClass {

  @Test(dataProvider = "dp", dataProviderClass = BaseClass.class)
  public void testMethod(int i) {
    System.err.println(i);
  }
}

The listener which extracts all of this information and shows it to you

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Optional;
import org.testng.ITestListener;
import org.testng.ITestResult;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class DataProviderTrackingListener implements ITestListener {

  @Override
  public void onTestStart(ITestResult result) {
    Test test = result.getMethod().getConstructorOrMethod().getMethod().getAnnotation(Test.class);
    if (test == null) {
      return;
    }
    Method method = null;
    Class<?> foundInClass = null;
    if (isDataProviderPresentInDifferentClass(test)) {
      method = extractDataProviderMethodFrom(test.dataProviderClass());
      foundInClass = test.dataProviderClass();
    } else {
      Class<?> currentClass = result.getInstance().getClass();
      while (currentClass != Object.class) {
        Optional<Method> methods =
            Arrays.stream(currentClass.getDeclaredMethods())
                .filter(
                    eachMethod -> {
                      DataProvider dataProvider = eachMethod.getAnnotation(DataProvider.class);
                      return (dataProvider != null
                          && dataProvider.name().equals(test.dataProvider()));
                    })
                .findFirst();
        if (methods.isPresent()) {
          method = methods.get();
          foundInClass = currentClass;
          break;
        }
        currentClass = currentClass.getSuperclass();
      }
    }
    if (method != null) {
      String msg =
          String.format(
              "Data provider [%s] found in class [%s]", method.getName(), foundInClass.getName());
      System.err.println(msg);
    }
  }

  private static boolean isDataProviderPresentInDifferentClass(Test test) {
    return test.dataProviderClass() != Object.class;
  }

  private static Method extractDataProviderMethodFrom(Class<?> clazz) {
    Optional<Method> method =
        Arrays.stream(clazz.getMethods())
            .filter(eachMethod -> eachMethod.getAnnotation(DataProvider.class) != null)
            .findFirst();
    return method.orElse(null);
  }
}


来源:https://stackoverflow.com/questions/31238763/how-to-get-data-provider-method-from-testng-data-provider-name

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!