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

Dav*_*Ray 231 java junit unit-testing

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

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

这将打印"当前测试是testSomething".

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

背景:显然,我不想只打印测试的名称.我想加载存储在与测试同名的资源中的特定于测试的数据.你知道,约定优于配置和所有这些.

Fro*_*age 367

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 显然更新版本的JUnit在`@ Before`之前执行`@ Rule` - 我是JUnit的新手,并且在我的`@ Before`中依赖于`TestName`没有任何困难. (41认同)
  • 有[更有效的方法可以做到这一点](http://stackoverflow.com/a/13987909/474189). (8认同)
  • 另请注意,@ before中不提供TestName :(请参阅:http://old.nabble.com/@Rule-TestName-not-available-in-@Before-methods...-td25198691.html (4认同)
  • 如果您使用参数化测试,"name.getMethodName()"将返回{testA [0],testA [1]等},因此我使用了一些类似于:assertTrue(name.getMethodName().matches("testA(\\ [ \\ d \\])"))?; (2认同)
  • @DuncanJones 为什么提议的替代方案“更有效”? (2认同)

Dun*_*nes 114

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());
   }
};
Run Code Online (Sandbox Code Playgroud)

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());
   }
};
Run Code Online (Sandbox Code Playgroud)


And*_*mov 11

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"));
}
Run Code Online (Sandbox Code Playgroud)

查看更多:JUnit 5用户指南,TestInfo javadoc.


小智 8

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

  }
}
Run Code Online (Sandbox Code Playgroud)


Yav*_*in5 7

试试这个:

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());
        }
}
Run Code Online (Sandbox Code Playgroud)

输出如下所示:

Starting JUnit-test: MyTest testA
Starting JUnit-test: MyTest testB
Run Code Online (Sandbox Code Playgroud)

注:此DOES NOT如果你的测试的子类工作的TestCase!测试运行但@Rule代码从未运行过.

  • 上帝在你的例子中为你的笔记祝福你. (3认同)

chr*_*nes 6

一种令人费解的方法是通过继承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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,对于每个测试类,您需要添加@RunWith(NameAwareRunner.class)注释.或者,如果您不想每次都记住它,可以将该注释放在Test超类上.当然,这限制了您对跑步者的选择,但这可能是可以接受的.

此外,可能需要一点功夫才能将当前的测试名称从Runner和您的框架中获取,但这至少会让您获得名称.


小智 5

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) {
    }
}
Run Code Online (Sandbox Code Playgroud)