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

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

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

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

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


当前回答

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。

其他回答

JUnit 4没有任何开箱即用的机制让测试用例获得自己的名称(包括在设置和拆卸过程中)。

@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 );
    }
};

我有一个扩展TestCase的Junit4测试类,所以@Rule的示例不能工作(正如在其他回答中提到的那样)。

然而,如果你的类扩展了TestCase,你可以使用getName()来获取当前的测试名称,这样可以工作:

@Before
public void setUp() {
  System.out.println("Start test: " + getName());
}

@After
public void tearDown() {
  System.out.println("Finish test: " + getName());
}
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) {
    }
}

在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());
}