Java 获取JUnit4中当前正在执行的测试的名称
在JUnit 3中,我可以得到当前正在运行的测试的名称,如下所示:Java 获取JUnit4中当前正在执行的测试的名称,java,unit-testing,junit,Java,Unit Testing,Junit,在JUnit 3中,我可以得到当前正在运行的测试的名称,如下所示: public class MyTest extends TestCase { public void testSomething() { System.out.println("Current test is " + getName()); ... } } public class NameAwareRunner extends BlockJUnit4ClassRunne
public class MyTest extends TestCase
{
public void testSomething()
{
System.out.println("Current test is " + getName());
...
}
}
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);
}
}
Starting JUnit-test: MyTest testA
Starting JUnit-test: MyTest testB
它将打印“当前测试是testSomething”
在JUnit4中有没有现成的或简单的方法来实现这一点
背景:显然,我不想只打印测试的名称。我想加载存储在与测试同名的资源中的特定于测试的数据。您知道,还有所有这些。JUnit4没有任何现成的机制让测试用例获得自己的名称(包括在设置和拆卸期间)。我建议您将测试方法名称与测试数据集分离。我将建模一个DataLoaderFactory类,该类从您的资源中加载/缓存测试数据集,然后在您的测试用例中调用一些接口方法,该方法返回测试用例的测试数据集。将测试数据绑定到测试方法名称假设测试数据只能使用一次,在大多数情况下,我建议在多个测试中使用相同的测试数据来验证业务逻辑的各个方面 一种复杂的方法是通过将org.junit.runners.BlockJUnit4ClassRunner子类化来创建自己的Runner 然后,您可以执行以下操作:
public class MyTest extends TestCase
{
public void testSomething()
{
System.out.println("Current test is " + getName());
...
}
}
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);
}
}
Starting JUnit-test: MyTest testA
Starting JUnit-test: MyTest testB
公共类NameAwarRunner扩展了BlockJUnit4ClassRunner{
public nameAwarerRunner(类aClass)引发初始化错误{
超级(aClass);
}
@凌驾
受保护语句methodBlock(FrameworkMethod FrameworkMethod){
System.err.println(frameworkMethod.getName());
返回super.methodBlock(frameworkMethod);
}
}
然后,对于每个测试类,您需要添加@RunWith(nameAwarerRunner.class)注释。或者,如果不想每次都记住该注释,可以将其放在测试超类上。当然,这限制了你对跑步者的选择,但这是可以接受的
此外,从运行程序中获取当前测试名称并将其输入到框架中可能需要一些技巧,但这至少可以为您获取名称。JUnit 4.7添加了它似乎正在使用的此功能。看起来这将为您获取方法名称:
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());
}
}
String testName=null;
StackTraceElement[]trace=Thread.currentThread().getStackTrace();
对于(int i=trace.length-1;i>0;--i){
StackTraceElement ste=跟踪[i];
试一试{
Class cls=Class.forName(ste.getClassName());
Method=cls.getDeclaredMethod(ste.getMethodName());
Test annotation=method.getAnnotation(Test.class);
if(注释!=null){
testName=ste.getClassName()+“+ste.getMethodName();
打破
}
}catch(classnotfounde异常){
}捕获(无此方法例外){
}捕获(安全异常e){
}
}
考虑使用SLF4J(Java的简单日志外观)使用参数化消息提供了一些简洁的改进。将SLF4J与JUnit4规则实现相结合可以提供更高效的测试类日志记录技术
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() {
}
}
JUnit 4.9.x及更高版本
自JUnit 4.9以来,该类已被弃用,取而代之的是具有调用功能的类:
@Rule
public TestRule watcher = new TestWatcher() {
protected void starting(Description description) {
System.out.println("Starting test: " + description.getMethodName());
}
};
注意:包含的类必须声明为public
JUnit4.7.x-4.8.x
以下方法将打印类中所有测试的方法名称:
@Rule
public MethodRule watchman = new TestWatchman() {
public void starting(FrameworkMethod method) {
System.out.println("Starting test: " + method.getName());
}
};
请尝试以下方法:
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());
}
}
输出如下所示:
public class MyTest extends TestCase
{
public void testSomething()
{
System.out.println("Current test is " + getName());
...
}
}
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);
}
}
Starting JUnit-test: MyTest testA
Starting JUnit-test: MyTest testB
注意:如果您的测试是测试用例的子类,则该不起作用!测试会运行,但@规则代码永远不会运行。您可以使用
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());
}
};
基于前面的评论并进一步考虑,我创建了TestWather的扩展,您可以在JUnit测试方法中使用它:
public class ImportUtilsTest {
private static final Logger LOGGER = Logger.getLogger(ImportUtilsTest.class);
@Rule
public TestWatcher testWatcher = new JUnitHelper(LOGGER);
@Test
public test1(){
...
}
}
测试助手类是下一个:
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());
}
}
享受吧 JUnit 5及以上
在JUnit5中,您可以插入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"));
}
请参阅更多:,。在JUnit5中充当JUnit4中TestName规则的替代品
从文件中:
TestInfo用于注入有关当前测试或测试的信息
容器到@Test、@RepeatedTest、@parameteredtest、,
@测试工厂、@beforeach、@AfterEach、@BeforeAll和@aftereall
方法
要检索当前执行的测试的方法名,有两个选项:String TestInfo.getDisplayName()
和
方法TestInfo.getTestMethod()
仅检索当前测试方法的名称TestInfo.getDisplayName()
可能不够,因为测试方法的默认显示名称是methodName(TypeArg1,TypeArg2,…TypeArg3)
在
@DisplayName(“…”)
中复制方法名称不是一个好主意
作为替代方案,您可以使用
TestInfo.getTestMethod()
返回一个可选对象。
如果在测试方法中使用检索方法,则您甚至不需要测试可选的包装值
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.Test;
@Test
void doThat(TestInfo testInfo) throws Exception {
Assertions.assertEquals("doThat(TestInfo)",testInfo.getDisplayName());
Assertions.assertEquals("doThat",testInfo.getTestMethod().get().getName());
}
JUnit5通过ExtensionContext
优势:
通过在每次(ExtensionContext上下文)之后重写,您可以获得ExtensionContext
的新增功能
上面的代码在JUnit4中给了您什么?JUnit3测试扩展了定义getName()的TestCase。JUnit 4测试不扩展基类,因此根本没有getName()方法。我有一个类似的问题,我想设置测试名称,因为我使用的是参数化的运行程序,它只给我编号的测试用例。使用test或TestWatcher的可爱解决方案。。。只是想知道(大声地)是否有必要这样做?通过查看Gradle给出的计时输出图表,可以发现测试是否运行缓慢。您永远不需要知道测试的操作顺序?有没有现成的m