「譯」JUnit 5 系列:架構體系

原文地址:http://blog.codefx.org/design/architecture/junit-5-architecture/
原文日期:29, Mar, 2016
譯文首發:Linesh 的博客:JUnit 5 系列:架構體系
個人 Github:http://github.com/linesh-simplicityhtml

如今,咱們已經知道了 如何配置 JUnit 5 環境如何寫一些測試,接下來就來看一點封面下的內容吧。本篇咱們將討論 JUnit 5 的架構體系,以及它之成形如此的緣由。前端

概述

本文章是這個 JUnit 5 系列的一部分:java

(若是不喜歡看文章,你能夠戳這裏看個人演講,或者看一下最近的 vJUG 講座,或者我在 DevoxxPL 上的 PPTgit

本系列文章都基於 Junit 5發佈的先行版 Milestone 2。它可能會有變化。若是有新的里程碑(milestone)版本發佈,或者試用版正式發行時,我會再來更新這篇文章。github

這裏要介紹的多數知識你均可以在 JUnit 5 用戶指南 中找到(這個連接指向的是先行版 Milestone 2,想看的最新版本文檔的話請戳這裏),而且指南還有更多的內容等待你發掘。下面的全部代碼均可以在 個人 Github 上找到。api

目錄

  • JUnit 4
  • JUnit 5
    • 分離的關注點
    • JUnit 5 的從新組織
    • 架構及體系
    • API 生命週期
  • Open test alliance
  • 回顧總結
  • 分享&關注

JUnit 4

除了 Hamcrest,JUnit 4沒有任何外部依賴,其全部的功能都被打包在一個構件(artifact)中。這徹底違反了單一職責原則,它被提供給開發者、IDE、構建工具、其餘測試框架、其餘擴展等使用,不一樣的使用者,依賴的都是一個一樣的構件。架構

而在這其中,只有開發者能——或者說曾經能——以最乾淨的方法來使用它。他們一般只須要 JUnit 的公共 API,不須要管其餘的。很是好。框架

但生態圈中的其餘成分則不是這樣使用 JUnit:測試框架、擴展,特別是 IDE 和構建工具的開發者,他們須要深刻到 JUnit 的深處,到它的細枝末節:非 public 的類、內部 API,甚至 private 字段。它們的正常工做極大地依賴於 JUnit 的實現細節。這使得 JUnit 維護團隊不能輕易地修改框架的這些內部實現,所以團隊的開發進度受到了很大的影響。ide

固然,這些工具的開發者們也並不是有意爲之。爲了實現那些咱們十分喜好的特性,他們不得不使用內部的 API,由於 JUnit 4 並無提供相應的 API:一個強大到足以知足工具開發者們需求的 API。工具

Junit Lambda 團隊開始着手於 JUnit 5 的開發,但願能讓這一切變得明朗起來。

JUnit 5

分離的關注點

退一步想,咱們不難辨識出,這裏至少有兩個不一樣的關注點須要分離:

  1. 一個支持測試代碼撰寫的 API
  2. 一個識別測試、運行測試的機制

再仔細思考一下第二點,咱們可能會問,「哪些測試?」這個固然是指 Junit 測試。「我知道,但具體是哪些版本的測試呢?」呃…「還有,具體是指什麼類型的測試?」好吧,你讓我給你……「只能跑那些老版本的 @Test 註解的測試麼?有沒有其餘新的方法來運行測試呢?……」行行行,都給我閉嘴!聽我講着。

爲了進一步將待識別測試的類型 與 實際運行它們 這兩個關注點解耦,上面的第二點須要細分:

  1. 一個支持測試代碼撰寫的 API
  2. 一個識別測試、運行測試的機制
    1. 一個識別、運行特定類型(好比,JUnit 5測試的機制)
    2. 另外一套協調上述機制的機制
    3. 上二者之間的 API

JUnit 5 的從新的組織

識別出這兩個關注點之後,「做爲平臺的 JUnit 」(用於運行咱們的測試)和「做爲工具的 JUnit 」(用於撰寫咱們的測試)這兩個概念的分離就清晰了。爲了完成這個完全的分離,JUnit 團隊決定將 JUnit 5 分紅三個子項目:

JUnit Jupiter
包含了咱們用於撰寫測試的 API(關注點1),以及一個能理解測試代碼的引擎(關注點2.1)。

JUnit Platform
提供了一套統一的 API 以運行測試,及基於 API 之上的一套工具(關注點2.2和2.3)。

JUnit Vintage
提供了一套引擎,用以在 JUnit 5 中運行 JUnit 3 和 JUnit 4 的測試(關注點2.1)。

架構與體系

JUnit 5 的架構體系徹底是遵循這個關注點分離思想的產物:

junit-jupiter-api(1)
開發者用於撰寫測試的 API,包含了咱們在JUnit 5 的基礎知識一節中所說起的全部註解、斷言等。

junit-platgorm-engine(2.3)
包含了一套全部測試引擎都必須實現的 API。這樣,不一樣的測試引擎之間能夠經過統一的接口被調用。引擎能夠跑正常的 JUnit 測試,但也能夠實現不一樣的引擎用以執行其餘框架寫成的測試,如 TestNGSpockCucumber 等。

junit-jupiter-engine(2.1)
junit-platform-engine API 的一個實現,專門用於執行 JUnit 5 撰寫的測試。

junit-vintage-engine(2.1)
junit-platform-engine API 的一個實現,專門用於執行 JUnit 3 或 JUnit 4 撰寫的測試。過去,JUnit 4 的構件 junit-4.12 充當了兩個角色:它既是開發人員用於實現測試的 API,又包含了用以執行測試的核心組件。這個引擎,能夠認爲是低版本的 JUnit 3/4 與 JUnit 5 之間的一個適配器。

junit-platform-launcher(2.2)
這部分使用了一個服務加載器 ServiceLoader 來發現測試引擎,並協調不一樣實現之間的執行。它提供了一個 API 給 IDE 和構建工具,使得它們可以與測試執行過程交互,好比,運行單個的測試、蒐集測試結果並展現等。

聽起來怎樣,很酷吧。

這部分架構對於咱們生態鏈前端的使用者來講基本是透明的。咱們的項目只須要引入一個用於編寫測試的 API 依賴,其他的組件讓工具去操心便可。

API 生命週期

如今來講說那些你們都在使用的內部 API。JUnit 5 團隊但願這個問題也能獲得解決,爲此給 JUnit 的 API 設立了生命週期。這裏,我將源碼中給出的部分解釋截取於此。

內部 API(internal)
不容許被 JUnit 開發者以外的任何人使用。這部分 API 可能被移除,而且不會事先通知。

已過期(Deprecated)
不該該再被使用的 API,它們可能在下次小版本發佈時被移除。

實驗階段(Experimental)
爲一些新的、實驗階段的特性所使用的 API,這些新特性可能會或已經被公開使用並接受反饋中。
可使用,但要謹慎。這些 API 將來可能被提高至 維護中穩定 級別,但也可能不帶提早通知就被移除。

維護中(Maintained)
使用該 API 的特性,至少在該大版本的下一個小版本發佈時不會發生向後不兼容的改變。若是將來有移除維護中 API 的計劃,它會先被打回到 已過期 階段。

穩定(Stable)
使用該 API 的特性,至少在下個大版本發佈以前不會發生向後不兼容的改變。

JUnit 對外公開的類都帶有一個 @API(usage) 註解,其中 usage 是上面幾個值中的其中一個。團隊但願這能給 API 的調用方以充足的信息,即他們所使用的 API 處於什麼生命週期中,同時,也但願給每一個團隊以自由,讓他們決定是否改變或移除過期 API 。

Open Test Alliance

其實還有一件事。Junit 5 的體系結構使得 IDE 和構建工具可以將其做爲中間層,以運行全部類型的測試框架(前提是該框架實現了其對應的引擎)。這樣的話,工具自己就不須要去實現框架相關的測試支持,它們只須要使用一套統一的藉口,便可實現測試發現、測試執行和結果收集。

是嘛,真的能夠嗎?

失敗的測試,一般使用異常來描述。但不一樣的測試框架和斷言庫之間並沒有一個統一的接口。相反,它們一般實現了各自不一樣的版本(常見的是繼承 AssertionErrorRuntimeException )。這就使得不一樣框架間的互操做變得更加複雜,也使得工具之間沒法簡單使用一套統一的接口。

爲了解決這個問題,Junit Lambda 團隊又分出來一個獨立的項目,The Open Test Alliance for the JVM。這是它們的提議:

基於 JUnit Lambda 團隊近來與來自Eclipse、Gradle 及 Intellij 等 IDE 和構建工具開發者所展開的討論,咱們呼籲要創建這樣一個開源項目:它用於提供一套基於 JVM的 測試庫與測試框架 間的最小公共接口集。

項目主要目標是,爲各測試框架(如 JUnit、TestNG、Spock 等)和三方斷言庫(Hamcrest、Assert 等)提供一個公共的異常集合。有了這個集合,IDE 和構建工具就能夠一個統一的接口對全部測試過程——如對失敗斷言、失敗假言斷定的處理、對測試執行過程的可視化、在 IDE 中生成測試結果報告等——進行處理。

截止目前,該項目的呼籲彷佛並未引發太多重視,或說是基本未獲得重視。若是你以爲這是個好的想法,你能夠經過一些方式來支持,好比向你常用的測試框架維護者發出聲音。

回顧總結

本篇咱們介紹了 JUnit 5 的架構設計,它將原有的 API 分紅了兩部分:編寫測試部分的 API 和 執行測試的引擎。這個引擎進一步地被切分紅三個部分:一個解析測試代碼的 API、一個測試執行器(launcher),和一些支持不一樣測試框架的引擎實現。這樣開發者只須要爲項目引入 API 部分的依賴(用於編寫測試),而測試框架的開發者們則只須要實現引擎部分的 API(其餘工做已經由 JUnit 處理了),構建工具方面也只須要實現 launcher API以協調測試執行。

下篇文章將會介紹 JUnit 5 的可拓展性。敬請期待。

相關文章
相關標籤/搜索