在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
#############################################################

其他回答

基于前面的评论,并进一步考虑我创建了一个TestWather的扩展,你可以在你的JUnit测试方法中使用:

public class ImportUtilsTest {
    private static final Logger LOGGER = Logger.getLogger(ImportUtilsTest.class);

    @Rule
    public TestWatcher testWatcher = new JUnitHelper(LOGGER);

    @Test
    public test1(){
    ...
    }
}

测试助手类是下一个:

public class JUnitHelper extends TestWatcher {
private Logger LOGGER;

public JUnitHelper(Logger LOGGER) {
    this.LOGGER = LOGGER;
}

@Override
protected void starting(final Description description) {
    LOGGER.info("STARTED " + description.getMethodName());
}

@Override
protected void succeeded(Description description) {
    LOGGER.info("SUCCESSFUL " + description.getMethodName());
}

@Override
protected void failed(Throwable e, Description description) {
    LOGGER.error("FAILURE " + description.getMethodName());
}
}

享受吧!

在JUnit 5中,TestInfo代替了JUnit 4中的TestName规则。

从文档中可以看到:

TestInfo用于注入有关当前测试的信息 容器到@Test, @RepeatedTest, @ParameterizedTest, @TestFactory, @BeforeEach, @AfterEach, @BeforeAll和@AfterAll 方法。

要检索当前执行测试的方法名,您有两个选项:String TestInfo.getDisplayName()和 TestInfo.getTestMethod()方法。

仅检索当前测试方法的名称TestInfo.getDisplayName()可能不够,因为测试方法的默认显示名称是methodName(TypeArg1, TypeArg2,…TypeArg3)。 在@DisplayName("..")中复制方法名并不一定是个好主意。

作为你可以使用的替代方案 返回一个Optional<Method>对象的TestInfo.getTestMethod()。 如果在测试方法中使用检索方法,则甚至不需要测试Optional包装值。

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.Test;

@Test
void doThat(TestInfo testInfo) throws Exception {
    Assertions.assertEquals("doThat(TestInfo)",testInfo.getDisplayName());
    Assertions.assertEquals("doThat",testInfo.getTestMethod().get().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。

String testName = null;
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
for (int i = trace.length - 1; i > 0; --i) {
    StackTraceElement ste = trace[i];
    try {
        Class<?> cls = Class.forName(ste.getClassName());
        Method method = cls.getDeclaredMethod(ste.getMethodName());
        Test annotation = method.getAnnotation(Test.class);
        if (annotation != null) {
            testName = ste.getClassName() + "." + ste.getMethodName();
            break;
        }
    } catch (ClassNotFoundException e) {
    } catch (NoSuchMethodException e) {
    } catch (SecurityException e) {
    }
}

I'd suggest you decouple the test method name from your test data set. I would model a DataLoaderFactory class which loads/caches the sets of test data from your resources, and then in your test case cam call some interface method which returns a set of test data for the test case. Having the test data tied to the test method name assumes the test data can only be used once, where in most case i'd suggest that the same test data in uses in multiple tests to verify various aspects of your business logic.