【发布时间】:2012-01-25 16:00:31
【问题描述】:
我能否像在 JUnit 中一样检索当前正在运行的测试名称(使用 getName() 或 rules)?
@Test
public void fooBar(){
System.out.println(magic()); //should print "fooBar"
}
附:我不想使用一些基于堆栈跟踪的自写工具。
【问题讨论】:
我能否像在 JUnit 中一样检索当前正在运行的测试名称(使用 getName() 或 rules)?
@Test
public void fooBar(){
System.out.println(magic()); //should print "fooBar"
}
附:我不想使用一些基于堆栈跟踪的自写工具。
【问题讨论】:
根据 TestNG 文档:http://testng.org/doc/documentation-main.html 您可以实现可能能够帮助您解决问题的侦听器。
查看第 5.16 节 TestNG 侦听器,特别是 IInvokedMethodListener(javadoc:http://testng.org/javadocs/org/testng/IInvokedMethodListener.html)。您可以挂钩 beforeInvocation 以获取方法名称,在某处保留它,然后在测试中使用它。当然,您可以直接在侦听器实现中使用这些细节。
【讨论】:
在您的方法中声明一个ITestContext in 参数并从中获取您需要的任何信息。
【讨论】:
我用@BeforeMethod 注释找到了更好的解决方案:
import java.lang.reflect.Method;
public class Test
{
@BeforeMethod
public void handleTestMethodName(Method method)
{
String testName = method.getName();
...
}
...
}
(基于解决方案from this thread)
【讨论】:
使用TestNG时可以使用@BeforeTest注解
尝试在 testng.xml 文件的 test 标签中设置 test name:
<test name="Check name test" >
并使用此方法:
@BeforeTest
public void startTest(final ITestContext testContext) {
System.out.println(testContext.getName()); // it prints "Check name test"
}
【讨论】:
在保留传递给像 IInvokedMethodListener 这样的侦听器的值时需要小心,因为幼稚的实现(包括现有答案中的那些)不会是线程安全的。由于 TestNG 可以同时运行测试,因此可以从不同测试的侦听器中查看存储的值。这是一个包含两个测试的示例,testA() 和 testB():
beforeInvocation(testA)店铺testA
beforeInvocation(testB) 存储 testB 覆盖 testA
testA() 检索 testB (!!)testB() 检索 testB
下面的TestMethodCapture 类通过ThreadLocal 关联侦听器及其测试来正确处理这种竞争条件,确保同时运行的测试不会相互覆盖。
更好的是,它不仅限于检索测试的名称,它还包含与当前测试关联的ITestNGMethod 和ITestResult 实例的引用,因此您还可以检查方法的class、@987654325 @ 和 parameters。
你可以这样使用它:
@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;
}
【讨论】:
checkNotNull() 来自 Guava。我强烈建议在任何 Java 项目中使用这个库,但是这个方法本质上是对 if (foo == null) throw NullPointerException(); 的一个很好的包装,所以你可以用类似的条件替换这些调用。