Can I retrieve currently running test name like in JUnit (using getName() or rules)?
@Test
public void fooBar(){
System.out.println(magic()); //should print "fooBar"
}
P.S. I don't want use some self-written tool based on stack traces.
According the to TestNG documentation at: http://testng.org/doc/documentation-main.html you can implement listeners that might be able to help you with your problem.
Look at section 5.16 TestNG Listeners, and in particular the IInvokedMethodListener (javadoc: http://testng.org/javadocs/org/testng/IInvokedMethodListener.html). You can hook into the beforeInvocation to grab the method name, hold onto it somewhere, and then use it in your test. You could of course, just use the the details immediately in your listener implementation.
I found better solution with @BeforeMethod annotation:
import java.lang.reflect.Method;
public class Test
{
@BeforeMethod
public void handleTestMethodName(Method method)
{
String testName = method.getName();
...
}
...
}
(based on solution from this thread)
When you use TestNG you can use @BeforeTest
annotation
Try set test name
in testng.xml file test tag:
<test name="Check name test" >
and use this metod:
@BeforeTest
public void startTest(final ITestContext testContext) {
System.out.println(testContext.getName()); // it prints "Check name test"
}
Declare an ITestContext
in parameter in your method and grab whatever information you need from it.
According the to TestNG documentation at: http://testng.org/doc/documentation-main.html you can implement listeners that might be able to help you with your problem.
Look at section 5.16 TestNG Listeners, and in particular the IInvokedMethodListener (javadoc: http://testng.org/javadocs/org/testng/IInvokedMethodListener.html). You can hook into the beforeInvocation to grab the method name, hold onto it somewhere, and then use it in your test. You could of course, just use the the details immediately in your listener implementation.
You need to be careful when holding onto the values passed into listeners like IInvokedMethodListener
as a naive implementation (including those in existing answers) will not be thread-safe. Since TestNG can run tests concurrently it's possible to see the stored value from a different test's listener. Here's an example with two tests, testA()
and testB()
:
beforeInvocation(testA)
stores testA
beforeInvocation(testB)
stores testB
overwriting testA
testA()
retrieves testB
(!!)testB()
retrieves testB
The TestMethodCapture
class below handles this race condition correctly by associating the listener and its test via a ThreadLocal
, ensuring that concurrently running tests will not overwrite each other.
Even better, it's not limited to just retrieving the test's name, it holds a reference to both the ITestNGMethod
and ITestResult
instances associated with the current test, so you can also inspect the method's class, test groups, and parameters.
You can use it like so:
@Listeners(TestMethodCapture.class)
public class TestMethodCaptureTest {
@Test
public void fooBar() {
// will print "fooBar"
System.out.println(TestMethodCapture.getTestMethod().getMethodName());
}
}
And here's the class itself:
/**
* 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());
}
}
If you aren't using Guava (why not??) you can add a checkNotNUll()
method like this to make this compile:
private static <T> T checkNotNull(T o, String msg, Object param) {
if (o == null) {
throw new NullPointerException(String.format(msg, param));
}
return o;
}
checkNotNull()
is coming from Guava. I would strongly encourage using this library in any Java project, but this method is essentially a nice wrapper around if (foo == null) throw NullPointerException();
so you could just replace these calls with a similar conditional. –
Metastasize Easiest way is to use Reporter.getCurrentTestResult().getName();
. This gives you the name of the currently running test.
This is especially useful when you want to retrieve the test name from some common utility or logging class and don't want to force all your tests to pass the name.
© 2022 - 2024 — McMap. All rights reserved.