在TestNG上检索测试名称

时间:2011-12-21 21:28:56

标签: java testng

我可以像在JUnit中一样检索当前正在运行的测试名称(使用getName()rules)吗?

@Test
public void fooBar(){
     System.out.println(magic()); //should print "fooBar"
}

P.S。我不想使用一些基于堆栈跟踪的自编工具。

5 个答案:

答案 0 :(得分:43)

我找到了更好的@BeforeMethod注释解决方案:

import java.lang.reflect.Method;

public class Test
{ 

    @BeforeMethod
    public void handleTestMethodName(Method method)
    {
        String testName = method.getName(); 
        ...
    }

    ...
}

(基于解决方案from this thread

答案 1 :(得分:12)

使用TestNG时,您可以使用@BeforeTest注释

尝试在testng.xml文件测试标记中设置测试name

<test name="Check name test" >

并使用此方法:

@BeforeTest
public void startTest(final ITestContext testContext) {
    System.out.println(testContext.getName()); // it prints "Check name test"
}

答案 2 :(得分:7)

在方法中的参数中声明ITestContext,并从中获取所需的任何信息。

答案 3 :(得分:6)

根据TestNG文档:http://testng.org/doc/documentation-main.html 您可以实现可能能够帮助您解决问题的侦听器。

请参阅第5.16节TestNG Listeners,特别是IInvokedMethodListener(javadoc:http://testng.org/javadocs/org/testng/IInvokedMethodListener.html)。您可以挂钩到beforeInvocation以获取方法名称,在某处保留它,然后在测试中使用它。当然,您可以在监听器实现中立即使用详细信息。

答案 4 :(得分:5)

在保持传递给IInvokedMethodListener等侦听器的值时需要小心,因为天真的实现(包括现有答案中的那些)将不是线程安全的。由于TestNG可以同时运行测试,因此可以从不同的测试用户那里查看存储的值。以下是两个测试的示例,testA()testB()

  1. beforeInvocation(testA)存储testA
  2. beforeInvocation(testB)存储testB覆盖testA
  3. testA()检索testB(!!)
  4. testB()检索testB
  5. 下面的TestMethodCapture类通过ThreadLocal关联监听器及其测试来正确处理此竞争条件,确保同时运行的测试不会相互覆盖。

    更好的是,它不仅限于检索测试的名称,它还包含对与当前测试相关联的ITestNGMethodITestResult实例的引用,因此您还可以检查方法classtest groupsparameters

    您可以像这样使用它:

    @Listeners(TestMethodCapture.class)
    public class TestMethodCaptureTest {
      @Test
      public void fooBar() {
        // will print "fooBar"
        System.out.println(TestMethodCapture.getTestMethod().getMethodName());
      }
    }
    

    这就是班级本身:

    /**
     * Captures the currently executing test method so it can be accessed by the test,
     * e.g. to retrieve the test method's name. This class is thread-safe.
     *
     * <p>Register this class as a
     * <a href="http://testng.org/doc/documentation-main.html#testng-listeners">TestNG
     * listener</a>, then access the method and result from test code with the static
     * {@link #getTestMethod} and {@link #getTestResult} methods.
     * 
     * <p>Annotating a test class with {@code @Listeners(TestMethodCapture.class)} is the
     * suggested way to enable capturing if your test's correctness will depend on this
     * listener being enabled.
     */
    public class TestMethodCapture implements IInvokedMethodListener {
      private static ThreadLocal<ITestNGMethod> currentMethods = new ThreadLocal<>();
      private static ThreadLocal<ITestResult> currentResults = new ThreadLocal<>();
    
      @Override
      public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
        currentMethods.set(method.getTestMethod());
        currentResults.set(testResult);
      }
    
      @Override
      public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
        currentMethods.remove();
        currentResults.remove();
      }
    
      public static ITestNGMethod getTestMethod() {
        return checkNotNull(currentMethods.get(),
          "Did you forget to register the %s listener?", TestMethodCapture.class.getName());
      }
    
      /**
       * Parameters passed from a data provider are accessible in the test result.
       */
      public static ITestResult getTestResult() {
        return checkNotNull(currentResults.get(),
          "Did you forget to register the %s listener?", TestMethodCapture.class.getName());
      }
    }
    

    如果您没有使用Guava(为什么不?),您可以添加这样的checkNotNUll()方法进行编译:

    private static <T> T checkNotNull(T o, String msg, Object param) {
      if (o == null) {
        throw new NullPointerException(String.format(msg, param));
      }
      return o;
    }