【问题标题】:How to wrap all junit tests?如何包装所有junit测试?
【发布时间】:2021-12-21 11:00:49
【问题描述】:

如何创建一个自动包装每个@Test 方法的junit5 扩展/规则/拦截器。

示例:想象一下测量执行时间:

class TimeExension {
    runTest() {
         StopWatch w = new StopWatch();
         w.start();

         //actually run the original test
         test.run();
 
         w.stop();
    }
}

这如何应用于任何测试类?

【问题讨论】:

标签: java junit junit5


【解决方案1】:

更新:对于 JUnit 5,您可以使用 @ExtendWith 注释而不是规则。例如,您可以使用 JUnit5 示例中显示的TimingExtension

一个完整的例子(部分取自the previously mentioned example):

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.ExtensionContext;

import java.lang.reflect.Method;
import java.util.logging.Logger;

import static org.junit.jupiter.api.Assertions.assertEquals;

class TimingExtension implements BeforeTestExecutionCallback, AfterTestExecutionCallback {

    private static final Logger logger = Logger.getLogger(TimingExtension.class.getName());

    private static final String START_TIME = "start time";

    @Override
    public void beforeTestExecution(ExtensionContext context) throws Exception {
        getStore(context).put(START_TIME, System.currentTimeMillis());
    }

    @Override
    public void afterTestExecution(ExtensionContext context) throws Exception {
        Method testMethod = context.getRequiredTestMethod();
        long startTime = getStore(context).remove(START_TIME, long.class);
        long duration = System.currentTimeMillis() - startTime;

        logger.info(() ->
                String.format("Method [%s] took %s ms.", testMethod.getName(), duration));
    }

    private ExtensionContext.Store getStore(ExtensionContext context) {
        return context.getStore(ExtensionContext.Namespace.create(getClass(), context.getRequiredTestMethod()));
    }

}

@ExtendWith(TimingExtension.class)
class MyFirstJUnitJupiterTests {


    @Test
    void addition() {
        assertEquals(2, 1 + 1);
    }

}

在这种情况下,输出将是这样的:

dec. 21, 2021 12:19:31 DU. TimingExtension afterTestExecution
INFO: Method [addition] took 6 ms.

Process finished with exit code 0

旧答案: 为此,在 JUnit 4 中,您可以使用 TestWatchers、带规则的秒表。下面是一些例子:

  • (1) 用于超时
  • (2) 在测试通过或失败时做一些事情
  • (3) 计算执行时间
import org.junit.Rule;
import org.junit.rules.TestWatcher;
import org.junit.rules.Timeout;
import org.junit.runner.Description;

class TestBase {
    @Rule
    public Timeout globalTimeout = Timeout.seconds(3);

    @Rule
    public TestWatcher watchman = new TestWatcher() {

        @Override
        protected void failed(Throwable e, Description description) {
            TestDescription td = description.getAnnotation(TestDescription.class);
            System.out.println("Failed: " + td.desc()[0]);

        }

    @Override
        protected void succeeded(Description description) {
            
        }


     @Rule
     public Stopwatch stopwatch = new Stopwatch() {
         @Override
         protected void succeeded(long nanos, Description description) {
             
         }

         @Override
         protected void failed(long nanos, Throwable e, Description description) {
             
         }

     };
}

【讨论】:

  • junit5! 中已弃用规则!
  • 对不起,用一个没有规则的工作 JUnit5 示例更新了我的答案
【解决方案2】:

可能InvocationInterceptor就是答案:

public class TestDurationReportExtension implements InvocationInterceptor {
    @Override
    public void interceptTestMethod(Invocation<Void> invocation,
            ReflectiveInvocationContext<Method> invocationContext,
            ExtensionContext extensionContext) throws Throwable {
 
        long beforeTest = System.currentTimeMillis();
        try {
            invocation.proceed();
        } finally {
            long afterTest = System.currentTimeMillis();
            long duration = afterTest - beforeTest;
             
            String testClassName = invocationContext.getTargetClass().getSimpleName();
            String testMethodName = invocationContext.getExecutable().getName();
            System.out.println(String.format("%s.%s: %dms", testClassName, testMethodName, duration));
        }
    }
}

用于:

@ExtendWith(TestDurationReportExtension.class)
public class DemoTest { .. }

创意来自:https://www.mscharhag.com/java/junit5-custom-extensions

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-03
    • 2017-10-11
    • 2012-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多