Java 获取 JUnit 4 中当前正在执行的测试的名称
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/473401/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get name of currently executing test in JUnit 4
提问by Dave Ray
In JUnit 3, I could get the name of the currently running test like this:
在 JUnit 3 中,我可以像这样获取当前正在运行的测试的名称:
public class MyTest extends TestCase
{
public void testSomething()
{
System.out.println("Current test is " + getName());
...
}
}
which would print "Current test is testSomething".
它将打印“当前测试是 testSomething”。
Is there any out-of-the-box or simple way to do this in JUnit 4?
在 JUnit 4 中是否有任何开箱即用或简单的方法来执行此操作?
Background: Obviously, I don't want to just print the name of the test. I want to load test-specific data that is stored in a resource with the same name as the test. You know, convention over configurationand all that.
背景:显然,我不想只打印测试名称。我想加载存储在与测试同名的资源中的特定于测试的数据。你知道,约定优于配置等等。
采纳答案by FroMage
JUnit 4.7 added this feature it seems using TestName-Rule. Looks like this will get you the method name:
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());
}
}
回答by cordellcp3
JUnit 4 does not have any out-of-the-box mechanism for a test case to get it's own name (including during setup and teardown).
JUnit 4 没有任何开箱即用的机制来让测试用例获得自己的名称(包括在设置和拆卸期间)。
回答by emeraldjava
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.
我建议您将测试方法名称与测试数据集分离。我会建模一个 DataLoaderFactory 类,它从您的资源加载/缓存测试数据集,然后在您的测试用例中调用一些接口方法,该方法返回测试用例的一组测试数据。将测试数据绑定到测试方法名称假设测试数据只能使用一次,在大多数情况下,我建议在多个测试中使用相同的测试数据来验证业务逻辑的各个方面。
回答by chris.f.jones
A convoluted way is to create your own Runner by subclassing org.junit.runners.BlockJUnit4ClassRunner.
一种复杂的方法是通过继承 org.junit.runners.BlockJUnit4ClassRunner 来创建您自己的 Runner。
You can then do something like this:
然后你可以做这样的事情:
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);
}
}
Then for each test class, you'll need to add a @RunWith(NameAwareRunner.class) annotation. Alternatively, you could put that annotation on a Test superclass if you don't want to remember it every time. This, of course, limits your selection of runners but that may be acceptable.
然后对于每个测试类,您需要添加一个 @RunWith(NameAwareRunner.class) 注释。或者,如果您不想每次都记住它,您可以将该注释放在 Test 超类上。当然,这会限制您对跑步者的选择,但这可能是可以接受的。
Also, it may take a little bit of kung fu to get the current test name out of the Runner and into your framework, but this at least gets you the name.
此外,从 Runner 中获取当前测试名称并进入您的框架可能需要一些功夫,但这至少可以让您获得名称。
回答by jnorris
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) {
}
}
回答by journeyman
Consider using SLF4J (Simple Logging Facade for Java) provides some neat improvements using parameterized messages. Combining SLF4J with JUnit 4 rule implementations can provide more efficient test class logging techniques.
考虑使用 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() {
}
}
回答by leojkelav
@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 );
}
};
回答by Duncan Jones
JUnit 4.9.x and higher
JUnit 4.9.x 及更高版本
Since JUnit 4.9, the TestWatchman
class has been deprecated in favour of the TestWatcher
class, which has invocation:
自 JUnit 4.9 起,TestWatchman
该类已被弃用,取而代之的是TestWatcher
具有调用的类:
@Rule
public TestRule watcher = new TestWatcher() {
protected void starting(Description description) {
System.out.println("Starting test: " + description.getMethodName());
}
};
Note: The containing class must be declared public
.
注意:必须声明包含类public
。
JUnit 4.7.x - 4.8.x
JUnit 4.7.x - 4.8.x
The following approach will print method names for all tests in a class:
以下方法将打印类中所有测试的方法名称:
@Rule
public MethodRule watchman = new TestWatchman() {
public void starting(FrameworkMethod method) {
System.out.println("Starting test: " + method.getName());
}
};
回答by Yavin5
Try this instead:
试试这个:
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());
}
}
The output looks like this:
输出如下所示:
Starting JUnit-test: MyTest testA
Starting JUnit-test: MyTest testB
NOTE: This DOES NOTwork if your test is a subclass of TestCase! The test runs but the @Rulecode just never runs.
注:此DOES NOT如果你的测试的子类工作的TestCase!测试运行,但@Rule代码从未运行。
回答by Coder
You can achieve this using Slf4j
and TestWatcher
您可以使用Slf4j
和实现此目的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());
}
};