在JUnit 3中,我可以像这样获得当前运行的测试的名称:

public class MyTest extends TestCase
{
    public void testSomething()
    {
        System.out.println("Current test is " + getName());
        ...
    }
}

它会打印“当前测试是testSomething”。

在JUnit 4中是否有任何开箱即用或简单的方法来做到这一点?

背景:显然,我不想只打印测试的名称。我希望加载存储在与测试同名的资源中的特定于测试的数据。你知道,约定比配置更重要。


当前回答

更简单的方法是将此逻辑放在setUp()和tearDown()方法中。 参考下面的代码,以获得更好的清晰度,

import java.lang.reflect.Method;

@BeforeMethod
void setUp(Method method) {
  log.info("###############################################");
  log.info("Running Test: {}", method.getName());
}

@AfterMethod
void tearDown(Method method) {
  log.info("Finished Test: {}", method.getName());
    log.info("###############################################");
}


@Test
public void testMethodName() {
  // Method logic implementation...
}

以下是上述测试执行的输出,

#############################################################
Running Test: testMethodName
// Logs related to method execution...
Finished Test: testMethodName
#############################################################

其他回答

@ClassRule
public static TestRule watchman = new TestWatcher() {
    @Override
    protected void starting( final Description description ) {
        String mN = description.getMethodName();
        if ( mN == null ) {
            mN = "setUpBeforeClass..";
        }

        final String s = StringTools.toString( "starting..JUnit-Test: %s.%s", description.getClassName(), mN );
        System.err.println( s );
    }
};

JUnit 4.9。X及以上

从JUnit 4.9开始,TestWatchman类已经被弃用,取而代之的是TestWatcher类,它有以下调用:

@Rule
public TestRule watcher = new TestWatcher() {
   protected void starting(Description description) {
      System.out.println("Starting test: " + description.getMethodName());
   }
};

注意:包含类必须声明为public。

JUnit 4.7。X - 4.8.x

下面的方法将打印类中所有测试的方法名称:

@Rule
public MethodRule watchman = new TestWatchman() {
   public void starting(FrameworkMethod method) {
      System.out.println("Starting test: " + method.getName());
   }
};

JUnit 5及更高版本

在JUnit 5中,您可以注入TestInfo,这简化了对测试方法的测试元数据注入。例如:

@Test
@DisplayName("This is my test")
@Tag("It is my tag")
void test1(TestInfo testInfo) {
    assertEquals("This is my test", testInfo.getDisplayName());
    assertTrue(testInfo.getTags().contains("It is my tag"));
}

更多信息:JUnit 5用户指南,TestInfo javadoc。

考虑使用SLF4J (Java的简单日志Facade)使用参数化消息提供了一些整洁的改进。将SLF4J与JUnit 4规则实现相结合可以提供更有效的测试类日志记录技术。

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.MethodRule;
import org.junit.rules.TestWatchman;
import org.junit.runners.model.FrameworkMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoggingTest {

  @Rule public MethodRule watchman = new TestWatchman() {
    public void starting(FrameworkMethod method) {
      logger.info("{} being run...", method.getName());
    }
  };

  final Logger logger =
    LoggerFactory.getLogger(LoggingTest.class);

  @Test
  public void testA() {

  }

  @Test
  public void testB() {

  }
}

我通常使用这样的方法:

/** Returns text with test method name
    @param offset index of method on call stack to print, 1 for a caller of this method.
    */
    static String getName(int offset)
    { 
        Throwable t = new Throwable();
        t.fillInStackTrace();
        return 
               t.getStackTrace()[offset].getMethodName()+":"+t.getStackTrace()[offset].getLineNumber(); 
    };

这正是Exception在打印堆栈跟踪时所使用的。 根据具体的上下文,您可能需要计算出正确的偏移值。它是粗糙的,原始的,坚韧的,没有使用任何花哨的现代期货。