在JUnit 3中,我可以得到当前运行的测试的名称,如下所示:
public class MyTest extends TestCase { public void testSomething() { System.out.println("Current test is " + getName()); ... } }
这将打印"当前测试是testSomething".
在JUnit 4中是否有任何开箱即用或简单的方法可以做到这一点?
背景:显然,我不想只打印测试的名称.我想加载存储在与测试同名的资源中的特定于测试的数据.你知道,约定优于配置和所有这些.
JUnit 4.7似乎使用了TestName-Rule添加了这个功能.看起来这会得到方法名称:
import org.junit.Rule; public class NameRuleTest { @Rule public TestName name = new TestName(); @Test public void testA() { assertEquals("testA", name.getMethodName()); } @Test public void testB() { assertEquals("testB", name.getMethodName()); } }
从JUnit 4.9开始,TestWatchman
该类已被弃用,有利于TestWatcher
该类,该类具有调用:
@Rule public TestRule watcher = new TestWatcher() { protected void starting(Description description) { System.out.println("Starting test: " + description.getMethodName()); } };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中有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(Simple Logging Facade for Java)使用参数化消息提供了一些巧妙的改进.将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() { } }
试试这个:
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
注:此DOES NOT如果你的测试的子类工作的TestCase!测试运行但@Rule代码从未运行过.
一种令人费解的方法是通过继承org.junit.runners.BlockJUnit4ClassRunner来创建自己的Runner.
然后你可以做这样的事情:
public class NameAwareRunner extends BlockJUnit4ClassRunner { public NameAwareRunner(Class> aClass) throws InitializationError { super(aClass); } @Override protected Statement methodBlock(FrameworkMethod frameworkMethod) { System.err.println(frameworkMethod.getName()); return super.methodBlock(frameworkMethod); } }
然后,对于每个测试类,您需要添加@RunWith(NameAwareRunner.class)注释.或者,如果您不想每次都记住它,可以将该注释放在Test超类上.当然,这限制了您对跑步者的选择,但这可能是可以接受的.
此外,可能需要一点功夫才能将当前的测试名称从Runner和您的框架中获取,但这至少会让您获得名称.