如何从TestNG数据提供程序名称获取数据提供程序方法?

时间:2015-07-06 06:10:24

标签: testng testng-dataprovider

有没有人知道TestNG如何根据为测试方法指定的数据提供者名称确定数据提供者方法是什么?

我找到了这个解决方案: https://gist.github.com/ae6rt/3805639

但是,它没有考虑到数据提供者可能是:

  • 在完全不同的类中定义,或
  • 在父类中定义,
  • 该方法可以是静态的,也可以不是静态的。

我试图自己一起破解某些东西,但后来我认为我可能不是第一个尝试解决问题的人,特别是因为显然TestNG必须有解决方案。

有谁知道TestNG是如何做到的,以及如何访问该业务逻辑?

我试图找出"总测试次数"在启动时如下所述: How to get total amount of tests (incl. taking data providers into account) at TestNG start?

1 个答案:

答案 0 :(得分:0)

这可能是一个很晚的答案,但仍会发布。

以下示例显示了如何使用TestNG来完成。我正在使用TestNG 7.0.0-beta1(今天的最新发行版本)。

方案1:数据提供者位于同一类中。

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}};
  }
}

方案2:数据提供者位于基类中。

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);
  }
}

方案3:数据提供者位于完全不同的类中。

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);
  }
}

提取所有信息并将其显示给您的监听器

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);
  }
}