0

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

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

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

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

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

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

我正在尝试计算启动时的“总测试计数”,如下所述: 如何在 TestNG 开始时获取测试总数(包括考虑数据提供者)?

4

1 回答 1

2

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

下面的示例展示了如何使用 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);
  }
}
于 2018-12-16T17:43:01.690 回答