微服務(wù)測(cè)試的思考與項(xiàng)目演進(jìn)實(shí)踐
最近幾年,微服務(wù)架構(gòu)越來越火爆,逐漸被企業(yè)所采用。隨著軟件架構(gòu)的變化,對(duì)應(yīng)的軟件測(cè)試策略需要作何調(diào)整呢?本文將介紹微服務(wù)架構(gòu)下的測(cè)試策略,并結(jié)合分享在業(yè)務(wù)和架構(gòu)演變過程中,一個(gè)歷經(jīng)九年的項(xiàng)目測(cè)試策略的演進(jìn)。
關(guān)于微服務(wù)
微服務(wù)架構(gòu)是一種架構(gòu)模式,它提倡將單一應(yīng)用程序劃分成一組小的服務(wù),每個(gè)服務(wù)運(yùn)行在其獨(dú)立的進(jìn)程中,服務(wù)間采用輕量級(jí)通信機(jī)制互相溝通(通常是基于HTTP協(xié)議的RESTful API)。每個(gè)服務(wù)都圍繞著具體的業(yè)務(wù)進(jìn)行構(gòu)建,并且能夠被獨(dú)立部署到生產(chǎn)環(huán)境、預(yù)生產(chǎn)環(huán)境。
從微服務(wù)的概念可以看出它有如下好處:
- 每個(gè)服務(wù)可以獨(dú)立開發(fā)
- 處理的單元粒度更細(xì)
- 單個(gè)服務(wù)支持獨(dú)立部署和發(fā)布
- 更有利于業(yè)務(wù)的擴(kuò)展
同時(shí),獨(dú)立開發(fā)導(dǎo)致技術(shù)上的分離,HTTP通信加上Queue的機(jī)制增加了問題診斷的復(fù)雜度,對(duì)系統(tǒng)的功能、性能和安全方面的質(zhì)量保障帶來了很大的挑戰(zhàn)。另外,服務(wù)間的復(fù)雜依賴關(guān)系帶來了很多的不確定性,要實(shí)現(xiàn)獨(dú)立部署,對(duì)運(yùn)維也提出了更高的要求。微服務(wù)架構(gòu)的系統(tǒng)要特別關(guān)注這幾個(gè)方面:
- 服務(wù)間的依賴、連通性
- 服務(wù)的容錯(cuò)、可用性
- 數(shù)據(jù)的最終一致性
- 獨(dú)立部署
- 不確定性
測(cè)試策略的選擇
談到微服務(wù)的測(cè)試策略,很容易就想到了老馬推薦的文章《Microservices Testing》,該文推薦的微服務(wù)框架下的測(cè)試策略是這樣的:
經(jīng)典策略模型
這個(gè)策略模型強(qiáng)調(diào)測(cè)試分層以及每一層的恰當(dāng)覆蓋,整體符合金字塔結(jié)構(gòu)。它是最優(yōu)的嗎?
有人對(duì)此提出了質(zhì)疑...認(rèn)為策略模型應(yīng)該是蜂巢形狀的:
蜂巢模型
這個(gè)模型重點(diǎn)關(guān)注服務(wù)間的集成測(cè)試,兩端的單元測(cè)試和UI層E2E測(cè)試較少。
也有同事提出微服務(wù)下的測(cè)試結(jié)構(gòu)應(yīng)該是鉆石形狀的,服務(wù)間的集成依然是重點(diǎn),單元測(cè)試較少,而頂層增加了安全和性能等非功能測(cè)試。
鉆石模型
好像都有道理,到底選擇什么樣的策略模型好呢?不禁陷入了困境…...怎么辦?不妨先來聽聽我們項(xiàng)目的故事吧!
項(xiàng)目的故事
1. 測(cè)試策略的演進(jìn)
還是那個(gè)藍(lán)鯨項(xiàng)目,不知不覺進(jìn)入了第九個(gè)年頭。在這九年里,隨著業(yè)務(wù)的不斷發(fā)展,系統(tǒng)架構(gòu)也進(jìn)行了多次演進(jìn)和調(diào)整。相應(yīng)的,測(cè)試策略也發(fā)生了有意思的演進(jìn)變化。
測(cè)試策略的演進(jìn)
最初單一用戶系統(tǒng)、單體架構(gòu)的時(shí)候,嚴(yán)格按照測(cè)試金字塔來組織各層的自動(dòng)化測(cè)試。隨著功能的擴(kuò)展,大量mock的單元測(cè)試給重構(gòu)帶來了很大的不便。
企業(yè)系統(tǒng)開始開發(fā)的時(shí)候,我們調(diào)整了策略,減少單元測(cè)試的編寫,增加UI層E2E測(cè)試的覆蓋,測(cè)試結(jié)構(gòu)由原來的金字塔演變成上面梯形下面倒三角的形式。
后來,架構(gòu)調(diào)整,開始服務(wù)化。此時(shí),大量的E2E測(cè)試漸漸暴露出問題:
- CI上的測(cè)試執(zhí)行時(shí)間越來越長(zhǎng),而且定位問題的能力很弱,測(cè)試一旦失敗需要很長(zhǎng)時(shí)間修復(fù),測(cè)試人員好幾天也拿不到可以測(cè)試的版本,反饋周期過長(zhǎng);
- 由于服務(wù)化帶來的不穩(wěn)定因素增加,E2E測(cè)試沒法很好的覆蓋到需要的場(chǎng)景,測(cè)試人員就算拿到可測(cè)的版本也總有各種缺陷發(fā)生。
因此,項(xiàng)目引入契約測(cè)試,停止編寫新的E2E測(cè)試,將測(cè)試下移,分別用API測(cè)試和契約測(cè)試取代。
隨著功能的不斷增加,雖然E2E測(cè)試的量并不增加,但是其不穩(wěn)定性、維護(hù)難、定位難的問題有增無減,此時(shí)已經(jīng)很難由自動(dòng)化測(cè)試來保證產(chǎn)品的質(zhì)量。為了平衡成本和收益,項(xiàng)目考慮去掉大部分E2E測(cè)試,只保留少量的Smoke測(cè)試,將更多的測(cè)試下移。
同時(shí),技術(shù)雷達(dá)上新的技術(shù)“生產(chǎn)環(huán)境下的QA”出現(xiàn),項(xiàng)目也開始關(guān)心生產(chǎn)環(huán)境,并且在QA測(cè)試階段結(jié)合微服務(wù)的特點(diǎn)進(jìn)行對(duì)應(yīng)的探索式測(cè)試。
2. 應(yīng)對(duì)微服務(wù)的挑戰(zhàn)
前文提到過微服務(wù)帶來的挑戰(zhàn),下面來看項(xiàng)目是如何應(yīng)對(duì)這些挑戰(zhàn)的。
(1) 服務(wù)間的依賴、連通性
微服務(wù)架構(gòu)下,獨(dú)立開發(fā)的服務(wù)要整合起來最具挑戰(zhàn),如何保證服務(wù)間的依賴關(guān)系和連通性非常關(guān)鍵。前面已經(jīng)講過E2E集成測(cè)試有很大的挑戰(zhàn),并不適合,而消費(fèi)端驅(qū)動(dòng)的契約測(cè)試是個(gè)不錯(cuò)的選擇。項(xiàng)目正是利用契約測(cè)試去保證服務(wù)間的連通性,取代一部分E2E集成測(cè)試。
(2) 服務(wù)的容錯(cuò)、可用性
在系統(tǒng)負(fù)荷達(dá)到一定程度或者某個(gè)服務(wù)出現(xiàn)故障的時(shí)候,微服務(wù)架構(gòu)有兩種技術(shù)來確保系統(tǒng)的可用性:服務(wù)的熔斷和降級(jí)。服務(wù)的熔斷是指當(dāng)某個(gè)服務(wù)出現(xiàn)故障時(shí),為了保證系統(tǒng)整體的可用性,會(huì)關(guān)閉掉出現(xiàn)故障的服務(wù);服務(wù)的降級(jí)則是當(dāng)系統(tǒng)整體負(fù)荷過載的時(shí)候,考慮關(guān)閉某些外圍服務(wù)來保證系統(tǒng)的整體可用性。
對(duì)應(yīng)的測(cè)試包括:
- 熔斷:從性能角度,當(dāng)系統(tǒng)負(fù)載達(dá)到某個(gè)熔斷狀態(tài)的時(shí)候,服務(wù)是否能正確熔斷;同時(shí),從功能角度驗(yàn)證熔斷后系統(tǒng)的行為是否跟預(yù)期相符;
- 降級(jí):從業(yè)務(wù)的角度,要能區(qū)分出核心業(yè)務(wù)和外圍業(yè)務(wù),在需要降級(jí)的時(shí)候不能影響核心業(yè)務(wù);當(dāng)某個(gè)服務(wù)降級(jí)后,從功能角度驗(yàn)證系統(tǒng)行為是否跟預(yù)期相符。
(3) 數(shù)據(jù)的最終一致性
數(shù)據(jù)一致性
數(shù)據(jù)一致性是微服務(wù)特別需要關(guān)注的。舉個(gè)例子,電商平臺(tái)某個(gè)訂單支付成功以后,需要更新積分和訂單狀態(tài),當(dāng)訂單服務(wù)或者積分服務(wù)其中有一個(gè)出現(xiàn)故障的時(shí)候,就會(huì)導(dǎo)致最終的數(shù)據(jù)不一致性。
測(cè)試這種情況,從業(yè)務(wù)的角度分析哪些服務(wù)會(huì)導(dǎo)致數(shù)據(jù)不一致性,制造對(duì)應(yīng)的異常情況去測(cè)試數(shù)據(jù)的最終一致性。
(4) 獨(dú)立部署
微服務(wù)的獨(dú)立部署需要有CI、CD的支持,跟DevOps實(shí)踐分不開。同時(shí),更為關(guān)鍵的是需要契約測(cè)試來驗(yàn)證獨(dú)立部署后服務(wù)行為的正確性。項(xiàng)目在這方面的工作,請(qǐng)參考王健的文章:你的微服務(wù)敢獨(dú)立交付嗎?
(5) 不確定性
微服務(wù)架構(gòu)使得系統(tǒng)復(fù)雜度增加不少,很多的事情發(fā)生都是不可預(yù)測(cè)的,只能在其發(fā)生以后找到產(chǎn)生的原因。因此,也就沒法在預(yù)生產(chǎn)環(huán)境通過測(cè)試去發(fā)現(xiàn)在真實(shí)生產(chǎn)環(huán)境才會(huì)發(fā)生的issue,我們需要把目光轉(zhuǎn)移到生產(chǎn)環(huán)境,利用生產(chǎn)環(huán)境的不確定性、微服務(wù)的不可預(yù)測(cè)性來構(gòu)建反脆弱的系統(tǒng)。
項(xiàng)目在這方面主要采用的技術(shù)是生產(chǎn)環(huán)境下的QA。
3. 項(xiàng)目測(cè)試策略
從前面介紹的演進(jìn)過程可以看到,項(xiàng)目測(cè)試策略在不同階段結(jié)合參考了不同的策略模型:金字塔->近似鉆石(除非功能測(cè)試外,類似于鉆石模型)->蜂巢。后期全面服務(wù)化的時(shí)候,我們認(rèn)為蜂巢模型是比較適合的。
當(dāng)然,光有符合這個(gè)策略模型的自動(dòng)化測(cè)試是遠(yuǎn)遠(yuǎn)不夠的,我們項(xiàng)目還采用了針對(duì)微服務(wù)特點(diǎn)的探索式測(cè)試,保持持續(xù)交付節(jié)奏,踐行DevOps實(shí)踐,結(jié)合生產(chǎn)環(huán)境下的QA等技術(shù)把關(guān)注點(diǎn)右移到生產(chǎn)環(huán)境。
現(xiàn)在,項(xiàng)目整體測(cè)試策略演變成下圖的形式:
項(xiàng)目測(cè)試策略
- 項(xiàng)目采用的是敏捷迭代開發(fā)和持續(xù)交付的模式,每四周一個(gè)發(fā)布周期。
- 在開發(fā)過程中實(shí)現(xiàn)的自動(dòng)化測(cè)試是分層實(shí)現(xiàn)的:底層少量的單元測(cè)試,中間量最多的是API測(cè)試(類似于老馬策略模型里的組件測(cè)試),上面有一部分契約測(cè)試和少量的Smoke測(cè)試來保證服務(wù)間的契約和集成。除此之外,QA有手動(dòng)的探索式測(cè)試,其中包括針對(duì)微服務(wù)特點(diǎn)進(jìn)行的一些測(cè)試。整個(gè)測(cè)試結(jié)構(gòu)是類似于蜂巢模型的。
- 采用生產(chǎn)環(huán)境下的QA技術(shù),利用生產(chǎn)環(huán)境,進(jìn)行error監(jiān)控、用戶行為分析、用戶反饋收集,從而來影響和指導(dǎo)預(yù)生產(chǎn)環(huán)境的開發(fā)和測(cè)試工作。
- 利用DevOps實(shí)踐,做到高效的部署和監(jiān)控,跟生產(chǎn)環(huán)境下的QA結(jié)合,形成良性的環(huán)路,保證項(xiàng)目的正常交付。
測(cè)試策略再思考
項(xiàng)目上多次測(cè)試策略的調(diào)整,看似很簡(jiǎn)單,其實(shí)每次調(diào)整并不是一個(gè)輕松的過程,都是平衡利弊、綜合考慮多個(gè)因素才做出的決定。
分析整個(gè)調(diào)整過程,最后突然發(fā)現(xiàn):當(dāng)我們面對(duì)多個(gè)策略模型不知道如何選擇的時(shí)候,其實(shí)我們陷入了一個(gè)太過于關(guān)注測(cè)試結(jié)構(gòu)的誤區(qū),忘記了最初的目標(biāo)是什么。
1. 影響測(cè)試策略的因素
跳出誤區(qū),回到原點(diǎn),重新思考測(cè)試策略的目標(biāo)。影響策略的最關(guān)鍵因素是業(yè)務(wù)價(jià)值、質(zhì)量要求、痛點(diǎn)。
影響測(cè)試策略的因素
(1) 業(yè)務(wù)價(jià)值
帶來更大的業(yè)務(wù)價(jià)值、幫企業(yè)贏得更多的利潤(rùn),是軟件系統(tǒng)的目標(biāo);軟件測(cè)試是軟件系統(tǒng)成功的保障之一,業(yè)務(wù)價(jià)值也是測(cè)試策略的終極目標(biāo)。所有測(cè)試活動(dòng)都要圍繞這個(gè)目標(biāo)開展,考慮業(yè)務(wù)優(yōu)先級(jí),有效規(guī)避業(yè)務(wù)風(fēng)險(xiǎn)。
(2) 質(zhì)量要求
不同的系統(tǒng)、同一系統(tǒng)的不同利益干系人(參與的不同角色)對(duì)于質(zhì)量的定義和要求都可能是不同的,這毫無疑問是影響測(cè)試策略的一個(gè)關(guān)鍵因素。
對(duì)于僅有內(nèi)部用戶的系統(tǒng),關(guān)注的重心可能是系統(tǒng)的功能;而對(duì)外發(fā)布的產(chǎn)品,則要求更高,一個(gè)按鈕位置的不恰當(dāng)都可能帶來大量用戶的流失。
(3) 痛點(diǎn)
真正的痛點(diǎn)往往也是優(yōu)先級(jí)最高,迫切需要解決的。那些可以通過測(cè)試策略的調(diào)整來解決的痛點(diǎn),自然成為了關(guān)鍵的影響因素之一。比如,CI Pipeline出包太慢,為了提高出包的效率,一方面在Pipeline本身想辦法,另一方面調(diào)整自動(dòng)化測(cè)試的比例、執(zhí)行頻率等也是解決方案之一。
演進(jìn)式測(cè)試策略
處在不同階段的項(xiàng)目,在業(yè)務(wù)價(jià)值這個(gè)大目標(biāo)下,其他影響因素也是會(huì)不一樣的,跟技術(shù)架構(gòu)的演進(jìn)一樣,測(cè)試策略也應(yīng)該是演進(jìn)式的。
從目標(biāo)出發(fā),綜合所處階段各個(gè)方面的影響因素,制定出適合當(dāng)時(shí)的測(cè)試策略。隨著時(shí)間的推移,對(duì)策略進(jìn)行評(píng)估和度量,并進(jìn)一步改進(jìn)、提高,以更好的滿足需求。這就是目標(biāo)驅(qū)動(dòng)的演進(jìn)式測(cè)試策略。
演進(jìn)式測(cè)試策略
總結(jié)
微服務(wù)架構(gòu)下多個(gè)服務(wù)的整合是最具有挑戰(zhàn)的,對(duì)此最重要的是契約測(cè)試。契約測(cè)試有效保證服務(wù)間的契約關(guān)系不被破壞,確保服務(wù)的連通性,有助于實(shí)現(xiàn)真正的獨(dú)立部署和獨(dú)立交付。
微服務(wù)架構(gòu)引入的不確定性并不是壞事,可以利用這些不確定性,采用生產(chǎn)環(huán)境下的QA等技術(shù),增強(qiáng)系統(tǒng)的反脆弱性,從中獲益。
測(cè)試策略的影響因素不是唯一的,技術(shù)架構(gòu)并不是最關(guān)鍵的因素。微服務(wù)架構(gòu)下的測(cè)試策略跟其他架構(gòu)下的并不會(huì)有本質(zhì)的區(qū)別。
業(yè)務(wù)價(jià)值始終是我們的終極目標(biāo)。在這個(gè)終極目標(biāo)的驅(qū)動(dòng)下,測(cè)試策略不是制定完了就可以束之高閣的,需要在整個(gè)軟件系統(tǒng)構(gòu)建過程中不斷的度量和改進(jìn),是演進(jìn)式的。
【本文是51CTO專欄作者“ThoughtWorks”的原創(chuàng)稿件,微信公眾號(hào):思特沃克,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】