基於 junit5 實現 junitperf 源碼分析

前言

上一節介紹了基於 junit4 實現 junitperf,可是能夠發現定義變量的方式依然不夠優雅。html

那能夠讓用戶使用起來更加天然一些嗎?java

有的,junit5 爲咱們帶來了更增強大的功能。git

拓展閱讀:github

淺談性能測試ide

基於 junit4 分析 junitperf 源碼,junit4 99% 的人都不知道的祕密!性能

junit5

沒有對比,就沒有傷害

咱們首先回顧一下 junit4 的寫法:單元測試

public class HelloWorldTest {

    @Rule
    public JunitPerfRule junitPerfRule = new JunitPerfRule();

    /**
     * 單一線程,執行 1000ms,默認以 html 輸出測試結果
     * @throws InterruptedException if any
     */
    @Test
    @JunitPerfConfig(duration = 1000)
    public void helloWorldTest() throws InterruptedException {
        System.out.println("hello world");
        Thread.sleep(20);
    }

}

再看一下 junit5 的寫法:測試

public class HelloWorldTest {

    @JunitPerfConfig(duration = 1000)
    public void helloTest() throws InterruptedException {
        Thread.sleep(100);
        System.out.println("Hello Junit5");
    }

}

JunitPerfRule 居然神奇的消失了?這一切是怎麼作到的呢?ui

讓咱們一塊兒揭開 junit5 神祕的面紗。lua

Junit5 更增強大的特性

@JunitPerfConfig

咱們只是指定了一個簡單的 @JunitPerfConfig 註解,那麼問題必定就出在這個註解裏。

定義以下:

import java.lang.annotation.*;

/**
 * 執行接口
 * 對於每個測試方法的條件配置
 * @author bbhou
 * @version 1.0.0
 * @since 1.0.0
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

@ExtendWith(PerfConfigProvider.class)
@TestTemplate
public @interface JunitPerfConfig {

    // 屬性省略

}

@Retention@Target 屬於 java 中的常規註解,此處不作贅述。

咱們重點看一下剩餘的兩個註解。

@TestTemplate

咱們之前在寫單元測試的時候,都會寫一個 @Test 註解,你會發現 junit5 中連這個註解都省略了。

那麼,他去哪裏了呢?

答案就是 @TestTemplate 聲明的註解,就是用來標識這個方法是單元測試的方法,idea 也會認的,這一點很是的靈活強大。

@ExtendWith

這個註解,給咱們的註解進行了賦能。

看名字,就是一個拓展,拓展的實現,就是咱們指定的類 PerfConfigProvider

PerfConfigProvider

咱們來看一下 PerfConfigProvider 的實現。

public class PerfConfigProvider implements TestTemplateInvocationContextProvider {

    @Override
    public boolean supportsTestTemplate(ExtensionContext context) {
        return context.getTestMethod()
                .filter(m -> AnnotationSupport.isAnnotated(m, JunitPerfConfig.class))
                .isPresent();
    }

    @Override
    public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContexts(ExtensionContext context) {
        return Stream.of(new PerfConfigContext(context));
    }

}

實現很是簡單,首先是一個過濾。

只有定義了 @JunitPerfConfig 註解的方法,纔會生效。

下面就是咱們自定義實現的上下文 PerfConfigContext。

PerfConfigContext

PerfConfigContext 實現了 TestTemplateInvocationContext,而且對原生的 ExtensionContext 進行了簡單的封裝。

public class PerfConfigContext implements TestTemplateInvocationContext {

    // 省略內部屬性

    @Override
    public List<Extension> getAdditionalExtensions() {
        return Collections.singletonList(
                (TestInstancePostProcessor) (testInstance, context) -> {
                    final Class clazz = testInstance.getClass();
                    // Group test contexts by test class
                    ACTIVE_CONTEXTS.putIfAbsent(clazz, new ArrayList<>());

                    EvaluationContext evaluationContext = new EvaluationContext(testInstance,
                            method,
                            DateUtil.getCurrentDateTimeStr());
                    evaluationContext.loadConfig(perfConfig);
                    evaluationContext.loadRequire(perfRequire);
                    StatisticsCalculator statisticsCalculator = perfConfig.statistics().newInstance();
                    Set<Reporter> reporterSet = getReporterSet();
                    ACTIVE_CONTEXTS.get(clazz).add(evaluationContext);
                    try {
                        new PerformanceEvaluationStatement(evaluationContext,
                                statisticsCalculator,
                                reporterSet,
                                ACTIVE_CONTEXTS.get(clazz),
                                clazz).evaluate();
                    } catch (Throwable throwable) {
                        throw new JunitPerfRuntimeException(throwable);
                    }
                }
        );
    }
}

寫到這裏,咱們就會發現又回到了和 junit4 類似的地方。

不明白的小夥伴能夠去看一下原來的實現,這裏不作贅述。

剩下的部分,和原來 junit4 的實現都是一致的。

小結

能夠發現 junit5 爲咱們提供的拓展能力更增強大靈活,他能夠讓咱們定義屬於本身的註解。

這個註解用起來讓用戶和使用原有的 junit5 註解沒有什麼區別。

不得不感慨一句,長江後浪推前浪,前浪死在沙灘上。

參考資料

https://github.com/houbb/junitperf

https://github.com/junit-team/junit4/wiki/Rules

相關文章
相關標籤/搜索