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

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

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

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

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


当前回答

考虑使用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() {

  }
}

其他回答

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.

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

试试这个吧:

public class MyTest {
        @Rule
        public TestName testName = new TestName();

        @Rule
        public TestWatcher testWatcher = new TestWatcher() {
            @Override
            protected void starting(final Description description) {
                String methodName = description.getMethodName();
                String className = description.getClassName();
                className = className.substring(className.lastIndexOf('.') + 1);
                System.err.println("Starting JUnit-test: " + className + " " + methodName);
            }
        };

        @Test
        public void testA() {
                assertEquals("testA", testName.getMethodName());
        }

        @Test
        public void testB() {
                assertEquals("testB", testName.getMethodName());
        }
}

输出如下所示:

Starting JUnit-test: MyTest testA
Starting JUnit-test: MyTest testB

注意:如果你的测试是TestCase的子类,这是行不通的!测试运行了,但是@Rule代码从来没有运行过。

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