获取JUnit 4中当前正在执行的testing的名称

在JUnit 3中,我可以得到当前正在运行的testing的名称,如下所示:

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

这将打印“当前testing是testing的东西”。

在JUnit 4中是否有任何现成或简单的方法?

背景:显然,我不想只打印testing的名称。 我想加载存储在与testing同名的资源中的特定于testing的数据。 你知道, 约定configuration和所有这一切。

谢谢!

JUnit 4.7增加了这个function,它似乎使用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.x和更高版本

从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

以下方法将打印类中所有testing的方法名称:

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

考虑使用SLF4J(Simple Logging Facade for Java)使用参数化消息提供了一些简洁的改进。 将SLF4J与JUnit 4规则实现相结合可以提供更高效的testing类logging技术。

 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() { } } 

复杂的方法是通过inheritanceorg.junit.runners.BlockJUnit4ClassRunner来创build自己的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); } } 

然后对于每个testing类,您需要添加@RunWith(NameAwareRunner.class)注释。 或者,如果您不想每次都记住,则可以将该注释放在Test超类上。 这当然会限制你对选手的select,但这可能是可以接受的。

此外,可能需要一点功夫才能将当前的testing名称从Runner中移出并放入您的框架中,但这至less可以让您获得名称。

试试这个:

 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 

注意:如果您的testing是TestCase的一个子类,这不起作用! testing运行,但@Rule代码只是从来没有运行。

JUnit 4没有任何开箱即用的机制来获取自己的名字(包括在安装和拆卸过程中)。

JUnit 5中有dependency injection,它简化了提供给testing方法的元数据。 例如:

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

基于之前的评论,并进一步考虑我创build了TestWather的扩展,你可以在你的JUnittesting方法中使用这个扩展:

 private static final Logger LOGGER = Logger.getLogger(ImportUtilsTest.class); @Rule public TestWatcher testWatcher = new JUnitHelper(LOGGER); 

testing助手类是下一个:

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

请享用!

我build议你从testing数据集中分离testing方法名称。 我将build模一个DataLoaderFactory类,它从您的资源加载/cachingtesting数据集,然后在您的testing案例中调用一些接口方法,该方法返回testing用例的一组testing数据。 将testing数据绑定到testing方法名称上假设testing数据只能使用一次,在大多数情况下,我build议使用多个testing中使用的相同testing数据来validation业务逻辑的各个方面。

您可以使用Slf4jTestWatcher来实现这TestWatcher

 private static Logger _log = LoggerFactory.getLogger(SampleTest.class.getName()); @Rule public TestWatcher watchman = new TestWatcher() { @Override public void starting(final Description method) { _log.info("being run..." + method.getMethodName()); } };