2011-12-21 6 views
12

Могу ли я получить текущее тестовое имя, например, в JUnit (с использованием getName() или rules)?Извлечь тестовое имя на TestNG

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

P.S. Я не хочу использовать какой-то самоналоженный инструмент, основанный на трассировке стека.

ответ

5

Согласно документации TestNG по адресу: http://testng.org/doc/documentation-main.html вы можете реализовать слушателей, которые могут помочь вам в решении вашей проблемы.

Посмотрите раздел 5.16 Слушатели TestNG, и в частности, IInvokedMethodListener (javadoc: http://testng.org/javadocs/org/testng/IInvokedMethodListener.html). Вы можете подключиться к beforeInvocation, чтобы захватить имя метода, удержать его где-нибудь и затем использовать его в своем тесте. Вы могли бы, конечно, просто использовать данные сразу в своей реализации.

+0

Этот ответ очень старый. Ответ Дмитрия - самый простой, требующий наименьших усилий. – gorbysbm

7

Объявите ITestContext в параметре в своем методе и возьмите всю необходимую информацию.

+0

На самом деле я не могу найти его в этом контексте интерфейса/suite/currentXmlTest name не содержит этой информации. –

+1

Ваш вопрос скорее является вопросом Java, чем TestNG, и поскольку вы не хотите использовать единственный способ, которым я это знаю (ходить по трассе стека), я не уверен, что еще сказать ... –

32

Я нашел лучшее решение с @BeforeMethod аннотацией:

import java.lang.reflect.Method; 

public class Test 
{ 

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

    ... 
} 

(на основе решения from this thread)

10

При использовании TestNG вы можете использовать @BeforeTest аннотации

Попробуйте установить тест name в TestNG. xml file test tag:

<test name="Check name test" > 

и использовать этот Metod:

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

Вы должны быть осторожны при проведении на значения, переданных в слушатель, как IInvokedMethodListener как наивная реализация (в том числе и в существующих ответах) не будет потокобезопасным. Так как TestNG может одновременно запускать тесты, можно увидеть сохраненное значение от слушателя другого теста. Вот пример с двумя тестами, testA() и testB():

  1. beforeInvocation(testA) магазинов testA
  2. beforeInvocation(testB) магазины testB перезапись testA
  3. testA() получает testB (!!)
  4. testB() извлекает testB

Класс TestMethodCapture правильно управляет этим состоянием гонки, связывая слушателя и его тест с помощью ThreadLocal, гарантируя, что одновременно выполняемые тесты не перезаписывают друг друга.

Еще лучше, если это не ограничивается только получением названия теста, она содержит ссылку на обоих ITestNGMethod и ITestResult случаев, связанных с текущим тестом, так что вы можете также проверить метод class, test groups и 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 (почему нет ??) вы можете добавить a checkNotNUll() метод, подобный этому, чтобы сделать эту информацию:

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

Не могли бы вы объяснить метод checkNotNull, который возвращается? Должен ли мы определить метод? Он показывает ошибку, что этот метод не определен. – nivasan89

+1

@ nivasan89 жаль, что я пропустил ваш комментарий. ['checkNotNull()'] (https://github.com/google/guava/wiki/PreconditionsExplained) поступает из [Guava] (https://github.com/google/guava). Я настоятельно рекомендую использовать эту библиотеку в любом Java-проекте, но этот метод по существу является хорошей оболочкой вокруг 'if (foo == null) throw NullPointerException();' поэтому вы можете просто заменить эти вызовы аналогичным условным. – dimo414

+1

Это должен быть принятый ответ. – Bass

Смежные вопросы