web-dev-qa-db-ja.com

TestNGでテスト名を取得する

JUnitのように現在実行中のテスト名を取得できますか( getName() または rules を使用)?

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

追伸スタックトレースに基づく自己作成ツールを使用したくありません。

18
Stan Kurilin

TestNGのドキュメントによると: http://testng.org/doc/documentation-main.html 問題の解決に役立つ可能性のあるリスナーを実装できます。

セクション5.16 TestNGリスナー、特にIInvokedMethodListener(javadoc: http://testng.org/javadocs/org/testng/IInvokedMethodListener.html )を見てください。 beforeInvocationにフックしてメソッド名を取得し、どこかに保持して、テストで使用できます。もちろん、リスナーの実装ですぐに詳細を使用することもできます。

6
Chris R

@BeforeMethodアノテーションでより良い解決策を見つけました:

import Java.lang.reflect.Method;

public class Test
{ 

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

    ...
}

(ソリューションに基づく このスレッドから

47
Dmitry

TestNGを使用する場合、@BeforeTestアノテーション

Test 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"
}
12

メソッドでITestContext inパラメータを宣言し、必要な情報をすべて取得します。

7
Cedric Beust

IInvokedMethodListenerなどのリスナーに渡された値を保持する場合は注意が必要です。これは、単純な実装(既存の回答に含まれるものを含む)はスレッドセーフではないためです。 TestNGはテストを同時に実行できるため、別のテストのリスナーから格納された値を確認することが可能です。 2つのテストtestA()testB()の例を次に示します。

  1. beforeInvocation(testA)ストアtestA
  2. beforeInvocation(testB)ストアtestB上書きtestA
  3. testA()testBを取得します(!!)
  4. testB()testBを取得します

以下のTestMethodCaptureクラスは、リスナーとそのテストを ThreadLocal を介して関連付けることにより、この競合状態を正しく処理し、同時に実行されているテストが互いに上書きしないようにします。

さらに良いことに、これはテストの名前を取得するだけに限定されず、関連付けられている ITestNGMethod および ITestResult インスタンスの両方への参照を保持します現在のテストなので、メソッドの classtest 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 を使用していない場合(なぜでしょうか??)、次のようなcheckNotNUll()メソッドを追加して、このコンパイルを行うことができます。

_private static <T> T checkNotNull(T o, String msg, Object param) {
  if (o == null) {
    throw new NullPointerException(String.format(msg, param));
  }
  return o;
}
_
5
dimo414