微服務(wù)架構(gòu)中測試的復(fù)雜度進(jìn)一步增加,了解測試的類型可用幫助我們盡早交付軟件與保持軟件高質(zhì)量之間的平衡
1. 測試象限
面向技術(shù)的測試:首先幫助開發(fā)人員構(gòu)建系統(tǒng)的測試,這個象限里的測試大都是可用自動化測試的,例如性能測試和小范圍的單元測試
面向業(yè)務(wù)的測試:幫助非技術(shù)背景的人了解系統(tǒng)是如何工作的。
支持團(tuán)隊(duì):幫助開發(fā)人員是否正確實(shí)現(xiàn)了功能,幫助業(yè)務(wù)人員了解系統(tǒng)是否實(shí)現(xiàn)了正確的功能
評價產(chǎn)品:非功能測試(響應(yīng)時間,可擴(kuò)展性,性能測試、安全測試)及可用性測試
2. 測試范圍:測試金字塔
Mike Cohn在《Scrum敏捷軟件開發(fā)》介紹了測試金字塔,描述了不同的自動化測試類型
金字塔模型可用幫組我們思考:1)不同的測試類型應(yīng)該覆蓋的范圍;2)為不同的測試類型投入多大的比例
1) 單元測試:通常只測試一個函數(shù)和方法調(diào)用
a. 通過TDD(Test-Driven Design,測試驅(qū)動開發(fā))寫的測試
b. 基于屬性(?)的測試技術(shù)所產(chǎn)生的測試
單元測試的主要目的:對于功能是否正常快速給出反饋;對于代碼重構(gòu)非常重要。
2) 服務(wù)測試:繞開用戶界面,直接針對服務(wù)的測試
a. 獨(dú)立應(yīng)用程序中,服務(wù)測試可能只測試為用戶界面提供服務(wù)的一些類
b. 包含多個服務(wù)的系統(tǒng),一個服務(wù)測試只測試其中一個單獨(dú)服務(wù)的功能
服務(wù)測試比單元測試的范圍大,比單元測試更難定位問題。和端到端測試相比,服務(wù)測試包含的組件已經(jīng)少多了。
3) 端到端測試:用戶界面是系統(tǒng)功能的集成點(diǎn),所以改成了端到端的測試。會覆蓋整個系統(tǒng),通常需要打開一個瀏覽器來操作GUI。
1) 權(quán)衡:
越靠近金字塔頂端
a. 優(yōu)勢:測試覆蓋的范圍越大;同時對被測試的功能也越有信心
b. 劣勢:需要更長的時間運(yùn)行測試,反饋周期變長。測試失敗后,比較難定位哪個功能被破壞。
越靠近金字塔的底部:
a. 優(yōu)勢:測試會越快,反饋周期變短,測試失敗后更容易定位被破壞的功能,持續(xù)集成的構(gòu)建時間也很短
b. 劣勢:只測試了一行代碼,很難有充足的信心認(rèn)為系統(tǒng)作為一個整體依然正常工作
當(dāng)范圍更大的測試(比如服務(wù)測試或者端到端的測試)失敗后,會嘗試一個單元測試來重現(xiàn)問題,以便能更快的速度捕獲同樣的錯誤。
2) 比例:
好的經(jīng)驗(yàn)法則:順著金字塔向下,下面一層的測試數(shù)量要比上面一層多一個數(shù)量級。
3. 實(shí)現(xiàn)服務(wù)測試
服務(wù)測試只要測試一個單獨(dú)服務(wù)的功能,為了隔離其他的相關(guān)服務(wù),需要一種方法給所有的外部合作者打樁。
1) 打樁,是指為被測試的服務(wù)的請求創(chuàng)建一些有著預(yù)測響應(yīng)的服務(wù)
步驟:
a. 對于每一個下游服務(wù),都需要一個打樁服務(wù),在運(yùn)行服務(wù)測試的時候啟動它們;
b. 另外需要配置被測試的服務(wù),在測試過程中連接這些打樁服務(wù)
c. 為了模擬真實(shí)的服務(wù),需要配置打樁服務(wù)為被測試服務(wù)的請求發(fā)回響應(yīng)
2) Mock與打樁
Martin ?Fowler把Mock和打樁統(tǒng)稱為測試替身(Test Double),如何權(quán)衡兩者,請參考《測試驅(qū)動的面向?qū)ο筌浖_發(fā)》
Mock和打樁的對比:
Mock的優(yōu)勢:
1) 會進(jìn)一步驗(yàn)證請求本身是否被正確調(diào)用,如果與期望請求不匹配,測試便會失敗
2) 驗(yàn)證預(yù)期的副作用是否發(fā)生
Mock的劣勢:
1) 過度使用mock會讓測試變得脆弱
3)智能的打樁服務(wù)
Mountebank(http://www.mbtest.org),可以發(fā)送命令告訴它需要打樁什么端口、使用哪種協(xié)議以及當(dāng)收到請求時該響應(yīng)什么內(nèi)容
4. 端到端的測試
通過用戶界面的測試覆蓋其涉及的所有服務(wù)。從另外一個層面講,用戶界面也集成了其涉及的所有的服務(wù)。所以運(yùn)行端到測試需要部署多個服務(wù)。
會經(jīng)常碰到的兩個問題:
1) 應(yīng)該使用服務(wù)的哪個版本?是生產(chǎn)環(huán)境的版本還是全部使用新版本進(jìn)行驗(yàn)證?
2) 不同的用戶界面測試會有很多的重疊測試,會重復(fù)部署這些重疊的服務(wù)。有沒有更好的辦法處理?
方法:讓多個流水線扇入(fan in)到一個獨(dú)立的端到端測試的階段
任意一個服務(wù)在任何時候只要發(fā)生變化,都會運(yùn)行針對這些服務(wù)的測試。如果測試通過,便會觸發(fā)端到端測試。
5. 端到端測試的缺點(diǎn)
1) 脆弱的測試:測試失敗的原因有時和服務(wù)的功能沒有任何關(guān)系
2) 測試緩慢:端到端測試需要大量的時間,進(jìn)而會造成大量的堆積
3) 元版本:所有服務(wù)在這些版本下可以一起工作,為何不一起部署?為何不給整個系統(tǒng)使用同一個版本號?這樣做舊丟棄了微服務(wù)的主要優(yōu)勢之一:獨(dú)立于其他服務(wù)單獨(dú)部署一個服務(wù)的能力
把多個服務(wù)一起部署不可避免地會導(dǎo)致服務(wù)的耦合
6. 消費(fèi)者驅(qū)動契約的測試
替代端到端測試的一個解決方案
CDC:Customer-Driven Contract消費(fèi)者驅(qū)動的契約
使用CDC時,我們會定義服務(wù)(或生產(chǎn)者)的消費(fèi)者的期望者的期望。這些期望會變成對生產(chǎn)者運(yùn)行的測試代碼,成為生產(chǎn)者CI流水線的一部分。如果這些契約被破壞,生產(chǎn)者就無法部署。另外,只運(yùn)行CDC測試,周期更短,也更可靠。
1) Pact:CDC測試的工具,現(xiàn)在已經(jīng)開源,使用Ruby語言編寫,現(xiàn)在支持包括JVM和.Net的版本
a. 使用Ruby DSL來定義生產(chǎn)者的期望
b. 啟動一個本地mock服務(wù)器,并對其運(yùn)行期望來生成Pack規(guī)范文件(標(biāo)準(zhǔn)的JSON規(guī)范)
c. 在生成者端,使用JSON Pact規(guī)范來驅(qū)動對生產(chǎn)者API的調(diào)用
d. 驗(yàn)證響應(yīng)來測試消費(fèi)者的規(guī)范是否被滿足
7. 跨功能的測試
非功能性需求,是對系統(tǒng)展現(xiàn)的一些特性的一個總結(jié)的術(shù)語,包括一個網(wǎng)頁的響應(yīng)時間,系統(tǒng)可以支持的用戶數(shù)量等。
使用跨功能需求(CFR, Cross-Functional Requirement)來替換非功能需求,因?yàn)檫@些系統(tǒng)行為是很多橫切工作融合的結(jié)果。
很多CFR只能在生產(chǎn)環(huán)境測試。
8. MTTR優(yōu)于MTBF,平均修復(fù)時間優(yōu)于平均故障間隔時間
MTBF:Mean Time Between Failures,平均故障間隔時間
MTTR:Mean Time To Repair,平均修復(fù)時間
減少修復(fù)時間的技術(shù):良好的監(jiān)控+盡快回滾。使用監(jiān)控盡早發(fā)現(xiàn)生產(chǎn)中的問題,盡快回滾減少對客戶的影響。