JUnit 4
除了 Hamcrest,JUnit 4沒有任何外部依賴,其所有的功能都被打包在一個構(gòu)件(artifact)中。這完全違反了單一職責(zé)原則,它被提供給開發(fā)者、IDE、構(gòu)建工具、其他測試框架、其他擴展等使用,不同的使用者,依賴的都是一個同樣的構(gòu)件。
而在這其中,只有開發(fā)者能——或者說曾經(jīng)能——以干凈的方法來使用它。他們通常只需要 JUnit 的公共 API,不需要管其他的。非常好。
但生態(tài)圈中的其他成分則不是這樣使用 JUnit:測試框架、擴展,特別是 IDE 和構(gòu)建工具的開發(fā)者,他們需要深入到 JUnit 的深處,到它的細(xì)枝末節(jié):非 public 的類、內(nèi)部 API,甚至 private 字段。它們的正常工作極大地依賴于 JUnit 的實現(xiàn)細(xì)節(jié)。這使得 JUnit 維護團隊不能輕易地修改框架的這些內(nèi)部實現(xiàn),因此團隊的開發(fā)進度受到了很大的影響。
當(dāng)然,這些工具的開發(fā)者們也并非有意為之。為了實現(xiàn)那些我們十分喜愛的特性,他們不得不使用內(nèi)部的 API,因為 JUnit 4 并沒有提供相應(yīng)的 API:一個強大到足以滿足工具開發(fā)者們需求的 API。
Junit Lambda 團隊開始著手于 JUnit 5 的開發(fā),希望能讓這一切變得明朗起來。
JUnit 5
分離的關(guān)注點
退一步想,我們不難辨識出,這里至少有兩個不同的關(guān)注點需要分離:
1、一個支持測試代碼撰寫的 API
2、一個識別測試、運行測試的機制
再仔細(xì)思考一下第二點,我們可能會問,“哪些測試?”這個當(dāng)然是指 Junit 測試。“我知道,但具體是哪些版本的測試呢?”呃…“還有,具體是指什么類型的測試?”好吧,你讓我給你……“只能跑那些老版本的 @Test 注解的測試么?有沒有其他新的方法來運行測試呢?……”行行行,都給我閉嘴!聽我講著。
為了進一步將待識別測試的類型 與 實際運行它們 這兩個關(guān)注點解耦,上面的第二點需要細(xì)分:
1、一個支持測試代碼撰寫的 API
2、一個識別測試、運行測試的機制
· 一個識別、運行特定類型(比如,JUnit 5測試的機制)
· 另一套協(xié)調(diào)上述機制的機制
· 上兩者之間的 API
JUnit 5 的重新的組織
識別出這兩個關(guān)注點以后,“作為平臺的 JUnit ”(用于運行我們的測試)和“作為工具的 JUnit ”(用于撰寫我們的測試)這兩個概念的分離清晰了。為了完成這個徹底的分離,JUnit 團隊決定將 JUnit 5 分成三個子項目:
JUnit Jupiter
包含了我們用于撰寫測試的 API(關(guān)注點1),以及一個能理解測試代碼的引擎(關(guān)注點2.1)。
JUnit Platform
提供了一套統(tǒng)一的 API 以運行測試,及基于 API 之上的一套工具(關(guān)注點2.2和2.3)。
JUnit Vintage
提供了一套引擎,用以在 JUnit 5 中運行 JUnit 3 和 JUnit 4 的測試(關(guān)注點2.1)。
架構(gòu)與體系
JUnit 5 的架構(gòu)體系完全是遵循這個關(guān)注點分離思想的產(chǎn)物:
junit-jupiter-api(1)
開發(fā)者用于撰寫測試的 API,包含了我們在 JUnit 5 的基礎(chǔ)知識 一節(jié)中所提及的所有注解、斷言等。
junit-platgorm-engine(2.3)
包含了一套所有測試引擎都必須實現(xiàn)的 API。這樣,不同的測試引擎之間可以通過統(tǒng)一的接口被調(diào)用。引擎可以跑正常的 JUnit 測試,但也可以實現(xiàn)不同的引擎用以執(zhí)行其他框架寫成的測試,如 TestNG 、 Spock 、 Cucumber 等。
junit-jupiter-engine(2.1)
junit-platform-engineAPI 的一個實現(xiàn),專門用于執(zhí)行 JUnit 5 撰寫的測試。
junit-vintage-engine(2.1)
junit-platform-engineAPI 的一個實現(xiàn),專門用于執(zhí)行 JUnit 3 或 JUnit 4 撰寫的測試。過去,JUnit 4 的構(gòu)件 junit-4.12 充當(dāng)了兩個角色:它既是開發(fā)人員用于實現(xiàn)測試的 API,又包含了用以執(zhí)行測試的核心組件。這個引擎,可以認(rèn)為是低版本的 JUnit 3/4 與 JUnit 5 之間的一個適配器。
junit-platform-launcher(2.2)
這部分使用了一個服務(wù)加載器 ServiceLoader 來發(fā)現(xiàn)測試引擎,并協(xié)調(diào)不同實現(xiàn)之間的執(zhí)行。它提供了一個 API 給 IDE 和構(gòu)建工具,使得它們能夠與測試執(zhí)行過程交互,比如,運行單個的測試、搜集測試結(jié)果并展示等。