Получить тестовое имя на TestNG
Можно ли получить текущее тестовое имя, например, в JUnit (используя getName() или правила)?
@Test
public void fooBar(){
System.out.println(magic()); //should print "fooBar"
}
P.S. Я не хочу использовать какой-то самоналоженный инструмент, основанный на трассировке стека.
Ответы
Ответ 1
Согласно документации TestNG по адресу: http://testng.org/doc/documentation-main.html
вы можете реализовать слушателей, которые могли бы помочь вам в решении вашей проблемы.
Посмотрите раздел 5.16 Слушатели TestNG и, в частности, IInvokedMethodListener (javadoc: http://testng.org/javadocs/org/testng/IInvokedMethodListener.html). Вы можете подключиться к beforeInvocation, чтобы захватить имя метода, удержать его где-нибудь и затем использовать его в своем тесте. Разумеется, вы можете просто использовать данные непосредственно в своей реализации.
Ответ 2
Я нашел лучшее решение с аннотацией @BeforeMethod:
import java.lang.reflect.Method;
public class Test
{
@BeforeMethod
public void handleTestMethodName(Method method)
{
String testName = method.getName();
...
}
...
}
(на основе решения из этого потока)
Ответ 3
Когда вы используете TestNG, вы можете использовать аннотацию @BeforeTest
Попробуйте установить тест name
в тестовом теге testng.xml:
<test name="Check name test" >
и используйте этот метод:
@BeforeTest
public void startTest(final ITestContext testContext) {
System.out.println(testContext.getName()); // it prints "Check name test"
}
Ответ 4
Объявите параметр ITestContext
в вашем методе и возьмите с собой любую необходимую информацию.
Ответ 5
Вам нужно быть осторожным, если удерживать значения, переданные в такие слушатели, как IInvokedMethodListener
, поскольку наивная реализация (в том числе в существующих ответах) не будет потокобезопасной. Поскольку TestNG может одновременно запускать тесты, можно увидеть сохраненное значение от другого тестового слушателя. Здесь пример с двумя тестами testA()
и testB()
:
-
beforeInvocation(testA)
хранит testA
-
beforeInvocation(testB)
хранит testB
перезапись testA
-
testA()
извлекает testB
(!!)
-
testB()
извлекает testB
Приведенный ниже класс TestMethodCapture
правильно обрабатывает это состояние гонки, связывая слушателя и его тест с помощью ThreadLocal
, гарантируя, что одновременно запущенные тесты не перезаписывают друг друга.
Более того, он не ограничивается просто получением имени теста, он содержит ссылку на ITestNGMethod
и ITestResult
экземпляры, связанные с текущим тестом, поэтому вы также можете проверить метод class, тестовые группы, и 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 name. This class is thread-safe.
*
* <p>Register this class as a
* <a href="#" onclick="location.href='http://testng.org/doc/documentation-main.html#testng-listeners'; return false;">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 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;
}