我可以像 JUnit 中那样检索当前正在运行的测试名称(使用 getName() 或 rules)吗?
@Test
public void fooBar(){
System.out.println(magic()); //should print "fooBar"
}
附注我不想使用一些基于堆栈跟踪的自写工具。
我通过@BeforeMethod注释找到了更好的解决方案:
import java.lang.reflect.Method;
public class Test
{
@BeforeMethod
public void handleTestMethodName(Method method)
{
String testName = method.getName();
...
}
...
}
(基于解决方案来自此线程)
当你使用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"
}
在您的方法中声明一个
ITestContext
参数,并从中获取您需要的任何信息。
根据 TestNG 文档:http://testng.org/doc/documentation-main.html 您可以实现可能能够帮助您解决问题的侦听器。
请参阅第 5.16 节 TestNG 侦听器,特别是 IInvokedMethodListener(javadoc:http://testng.org/javadocs/org/testng/IInvokedMethodListener.html)。 您可以挂接到 beforeInvocation 来获取方法名称,将其保留在某处,然后在测试中使用它。 当然,您可以立即在侦听器实现中使用详细信息。
在保留传递给诸如
IInvokedMethodListener
之类的侦听器的值时需要小心,因为幼稚的实现(包括现有答案中的实现)将不是线程安全的。由于 TestNG 可以同时运行测试,因此可以从不同测试的侦听器中查看存储的值。这是一个包含两个测试的示例,testA()
和 testB()
:
beforeInvocation(testA)
商店testA
beforeInvocation(testB)
存储 testB
覆盖 testA
testA()
检索testB
(!!)testB()
检索testB
下面的
TestMethodCapture
类通过ThreadLocal
关联侦听器及其测试来正确处理此竞争条件,确保同时运行的测试不会相互覆盖。
更好的是,它不仅限于检索测试的名称,它还保存对与当前测试关联的
ITestNGMethod
和 ITestResult
实例的引用,因此您还可以检查方法的 class, 测试组和参数。
你可以像这样使用它:
@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;
}
最简单的方法是使用
Reporter.getCurrentTestResult().getName();
。这将为您提供当前正在运行的测试的名称。
当您想要从某些常用实用程序或日志记录类检索测试名称并且不想强制所有测试都传递该名称时,这特别有用。