上一節介紹了基於 junit4 實現 junitperf,可是能夠發現定義變量的方式依然不夠優雅。html
那能夠讓用戶使用起來更加天然一些嗎?java
有的,junit5 爲咱們帶來了更增強大的功能。git
拓展閱讀:github
淺談性能測試ide
基於 junit4 分析 junitperf 源碼,junit4 99% 的人都不知道的祕密!性能
咱們首先回顧一下 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
咱們只是指定了一個簡單的 @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 中的常規註解,此處不作贅述。
咱們重點看一下剩餘的兩個註解。
咱們之前在寫單元測試的時候,都會寫一個 @Test
註解,你會發現 junit5 中連這個註解都省略了。
那麼,他去哪裏了呢?
答案就是 @TestTemplate
聲明的註解,就是用來標識這個方法是單元測試的方法,idea 也會認的,這一點很是的靈活強大。
這個註解,給咱們的註解進行了賦能。
看名字,就是一個拓展,拓展的實現,就是咱們指定的類 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 實現了 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 註解沒有什麼區別。
不得不感慨一句,長江後浪推前浪,前浪死在沙灘上。