35

Basically, I have a teardown method that I want to log to the console which test was just run. How would I go about getting that string?

I can get the class name, but I want the actual method that was just executed.

public class TestSomething {

    @AfterMethod
    public void tearDown() {
        System.out.println("The test that just ran was: " + getTestThatJustRanMethodName());
    }

    @Test
    public void testCase() {
       assertTrue(1 == 1);
    }
}

...should output to the screen: "The test that just ran was: testCase"

However, I don't know the magic that getTestThatJustRanMethodName should actually be.

Lii
  • 11,553
  • 8
  • 64
  • 88
Zee Spencer
  • 3,460
  • 6
  • 29
  • 31

5 Answers5

50

Declare a parameter of type ITestResult in your @AfterMethod and TestNG will inject it:

@AfterMethod
public void afterMethod(ITestResult result) {
  System.out.println("method name:" + result.getMethod().getMethodName());
}
Marco Ferrari
  • 4,914
  • 5
  • 33
  • 53
Cedric Beust
  • 15,480
  • 2
  • 55
  • 55
  • tks, and i use 'Reporter.setCurrentTestResult(result);' to change the report stream to test method – naive Sep 28 '14 at 12:37
34

If you want to get the method name before the test is executed you can use the following:

import java.lang.reflect.Method;

@BeforeMethod
public void nameBefore(Method method)
{
    System.out.println("Test name: " + method.getName());       
}
JacekM
  • 4,041
  • 1
  • 27
  • 34
8

Just declare a java.lang.reflect.Method parameter.

 @BeforeMethod
 public void beforeTestMethod(Method testMethod){
    System.out.println("Before Testmethod: " + testMethod.getName());       
 }

But TestNG allows you to inject a lot more ;)

  • Any @Before method or @Test method can declare a parameter of type ITestContext.
  • Any @AfterMethod method can declare a parameter of type ITestResult, which will reflect the result of the test method that was just run.
  • Any @Before and @After methods can declare a parameter of type XmlTest, which contain the current tag.
  • Any @BeforeMethod (and @AfterMethod) can declare a parameter of type java.lang.reflect.Method. This parameter will receive the test method that will be called once this @BeforeMethod finishes (or after the method as run for @AfterMethod).
  • Any @BeforeMethod can declare a parameter of type Object[]. This parameter will receive the list of parameters that are about to be fed to the upcoming test method, which could be either injected by TestNG, such as java.lang.reflect.Method or come from a @DataProvider.
  • Any @DataProvider can declare a parameter of type ITestContext or java.lang.reflect.Method. The latter parameter will receive the test method that is about to be invoked.
René Link
  • 48,224
  • 13
  • 108
  • 140
2

Another (although not as simple as Cedric's answer) way that TestNG supports this is to register a listener:

@Listeners({MethodListener.class})
public class ListenerTest {

  @Test
  public void someTest() {
  }

}

Where the listener could look like this:

public class MethodListener implements IInvokedMethodListener {

  @Override
  public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {

  }

  @Override
  public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
    System.out.println(method.getTestMethod().getMethodName());
  }
}

This particular listener would print the method name (i.e. someTest) to the console. It would be executed after every executed test.

If you are generating the testSuite programmatically then you can add the listener as follows instead of adding @Listeners({MethodListener.class}) over each test class

    List<String> listeners = new ArrayList<String>();
    listeners.add(MethodListener.class.getName());
    testSuite.setListeners(listeners);
suku
  • 10,507
  • 16
  • 75
  • 120
Magnilex
  • 11,584
  • 9
  • 62
  • 84
  • You can just use testResult.getMethod().getMethodName(). No need to get IInvokedMethod. – Bochu Jun 16 '21 at 15:23
1

In my own project I access this data thanks to a JUnit @Rule.

String testName;
String className;

@Rule
public TestWatcher watcher = new TestWatcher() {
    public void starting(Description description) {
        testName = description.getMethodName();
        className = description.getClassName();
        logger.info("Starting test " + testName + " in class " + className);
    }
};
Zoette
  • 1,241
  • 2
  • 18
  • 49