軟件測(cè)試中可測(cè)性一般是指對(duì)系統(tǒng)的可控性、可觀測(cè)性進(jìn)行的評(píng)估,借以反映系統(tǒng)設(shè)計(jì)、實(shí)現(xiàn)對(duì)測(cè)試的友好程度和相應(yīng)的測(cè)試成本。可測(cè)性在測(cè)試階段會(huì)對(duì)系統(tǒng)的測(cè)試成本及關(guān)聯(lián)產(chǎn)品代碼的Patch次數(shù)產(chǎn)生重大影響。如何提高可測(cè)性成為軟件生命周期特別是前期(設(shè)計(jì)階段、coding階段)重要的一環(huán)。 下面就讓匯智動(dòng)力的老師來(lái)為大家講解一下實(shí)際項(xiàng)目中可測(cè)性相關(guān)的實(shí)戰(zhàn)經(jīng)驗(yàn)和對(duì)應(yīng)的改進(jìn)措施。

  1 提高可測(cè)性的切入點(diǎn)

  可測(cè)性的評(píng)估和改進(jìn)最早開(kāi)始于兩個(gè)階段:

  a. 新項(xiàng)目的設(shè)計(jì)階段;

  b. 已有項(xiàng)目新功能、新策略的提測(cè)階段。

  這些是提高團(tuán)隊(duì)設(shè)計(jì)的系統(tǒng)可測(cè)性和維持系統(tǒng)的設(shè)計(jì)高可測(cè)性的關(guān)鍵時(shí)間點(diǎn)。測(cè)試人員會(huì)利用各種場(chǎng)合、機(jī)會(huì)強(qiáng)化開(kāi)發(fā)人員對(duì)于可測(cè)性的重視:

  可測(cè)性的重要性每次設(shè)計(jì)討論會(huì), 測(cè)試負(fù)責(zé)人必提醒大家在設(shè)計(jì)時(shí)注意可測(cè)性。否則設(shè)計(jì)出來(lái)的功能很可能需要進(jìn)行重構(gòu)。

  可控性

  每次晨會(huì)中的討論環(huán)節(jié), 測(cè)試負(fù)責(zé)人會(huì)提醒模塊設(shè)計(jì)人員,設(shè)計(jì)的功能需要必要的外部控制、執(zhí)行動(dòng)作支持,否則QA無(wú)法精確控制過(guò)程及縮短測(cè)試耗時(shí)。

  可觀測(cè)性每個(gè)功能進(jìn)行測(cè)試設(shè)計(jì)階段,提前和開(kāi)發(fā)人員溝通必要的功能,觀察結(jié)果集合可以系統(tǒng)外部獲得,錯(cuò)誤結(jié)果可以被暴露而不是由內(nèi)部邏輯完全消化。

  那可控性和可觀測(cè)性又指哪些方面呢? 如何向開(kāi)發(fā)人員合理的解釋可測(cè)性?

  1.1 可控性

  可控性指系統(tǒng)的狀態(tài)可受外部控制改變,而不是由內(nèi)部模塊自發(fā)的完成。

  舉個(gè)常見(jiàn)的例子:

  A. 當(dāng)某文件存在的時(shí)候,該模塊自動(dòng)退出;

  B. 當(dāng)某pid.lock文件存在時(shí),該模塊不能啟動(dòng),即使啟動(dòng)也退出。

  上面的狀態(tài)改變都是由一個(gè)外部的文件控制,擁有可控性。

  說(shuō)到這里,問(wèn)題來(lái)了,擁有可控性就萬(wàn)事大吉了嗎? 請(qǐng)大家思考,你在實(shí)際項(xiàng)目過(guò)程中遇到過(guò)哪些有可控性但可控性較差的情況?

  1.2 可觀測(cè)性

  可觀測(cè)性指系統(tǒng)內(nèi)的重要狀態(tài)、信息可通過(guò)一定手段由外部獲得。可觀測(cè)性不僅能觀測(cè)系統(tǒng)的輸出是否符合設(shè)計(jì)要求,還影響該系統(tǒng)是否可控。系統(tǒng)的必要狀態(tài)信息在系統(tǒng)測(cè)試控制階段起決定作用。沒(méi)有準(zhǔn)確的狀態(tài)信息,測(cè)試人員無(wú)法判斷是否要進(jìn)行下一步的控制變更。無(wú)法控制狀態(tài)變更,可控性又從何談起?

  口說(shuō)無(wú)憑,我們來(lái)看幾個(gè)作者實(shí)際項(xiàng)目中遇到的真實(shí)案例。

  2 實(shí)戰(zhàn)分析

  [1] 垃圾回收GC

  垃圾回收GC模塊是常見(jiàn)的系統(tǒng)內(nèi)模塊,相信很多測(cè)試人員遇到過(guò)下面場(chǎng)景或者類似場(chǎng)景:

  開(kāi)發(fā)人員終于在大吼一聲后宣布垃圾回收模塊完成,她的描述如下:

  1) 該模塊定時(shí)自動(dòng)觸發(fā)。觸發(fā)條件是每天晚上1點(diǎn)。

  2) 該模塊觸發(fā)后每秒的處理量是N/s。是根據(jù)線上情況得到的經(jīng)驗(yàn)值,硬編碼到代碼中。

  然后,就沒(méi)有然后了。

  測(cè)試人員一陣迷茫,這就是全部的詢問(wèn)換來(lái)的基本上是“它都是全自動(dòng)的了,你還想要什么的”表情。

  因此這個(gè)新功能完成后的二次返工是必然的了。

  首先,該模塊的可控性太差。測(cè)試環(huán)境不可以等待每天晚上1點(diǎn)這個(gè)時(shí)刻,必須有外部能影響這個(gè)”全自動(dòng)“的手段提供。否則全量的系統(tǒng)測(cè)試用例回歸會(huì)被限定在固定測(cè)試時(shí)間點(diǎn)且無(wú)法調(diào)整和更改。

  其次,該模塊的每秒處理量必須能更改到符合測(cè)試環(huán)境。測(cè)試環(huán)境基本上都是真實(shí)環(huán)境的放縮,特別是分布式系統(tǒng)等大規(guī)模應(yīng)用。測(cè)試環(huán)境機(jī)器無(wú)論是數(shù)量還是類型都遠(yuǎn)低于實(shí)際環(huán)境。這種條件下,參數(shù)的定量調(diào)整是必須要完成的輔助支持。

  再次,沒(méi)有必要的描述如何判斷哪些文件/數(shù)據(jù)被GC掉了。無(wú)法觀測(cè)到執(zhí)行結(jié)果集帶來(lái)的后果是無(wú)法精確的預(yù)期測(cè)試結(jié)果。

  而相應(yīng)的改進(jìn)措施就是解決上面提到的問(wèn)題。

  [2] 系統(tǒng)內(nèi)部狀態(tài)信息

  為了保證存儲(chǔ)的數(shù)據(jù)高可用,分布式系統(tǒng)會(huì)采取多機(jī)存儲(chǔ)副本方法。即一個(gè)數(shù)據(jù)被N(>=2)個(gè)機(jī)器以一定的算法存儲(chǔ)相同的數(shù)據(jù)副本。這個(gè)時(shí)候經(jīng)常會(huì)遇到的問(wèn)題:

  a) 機(jī)器間的數(shù)據(jù)由于數(shù)據(jù)復(fù)制順序的不同,會(huì)有數(shù)據(jù)差異。a、b、c三臺(tái)機(jī)器,a、b機(jī)器可能已完成一次數(shù)據(jù)的更新到最新數(shù)據(jù)版本data1,c還處于老版本data0.

  b) 由于版本差異,內(nèi)部必須維護(hù)副本revision的版本號(hào)以進(jìn)行數(shù)據(jù)同步和異常處理。

  這種情況, 好的設(shè)計(jì)原則上要保證多機(jī)副本的必要狀態(tài)信息被外部獲取。

  A. 數(shù)據(jù)的副本分布信息、副本的revision版本號(hào)等需要提供接口獲得

  B.由于機(jī)器宕機(jī)造成的副本分布變化要能夠及時(shí)反映和更新。(比如帶一定間隔周期的更新)

  只有在這種必要信息被獲取的情況下,測(cè)試人員才能更好的掌握系統(tǒng)狀態(tài)并根據(jù)系統(tǒng)狀態(tài)進(jìn)行清晰的測(cè)試結(jié)果預(yù)期。

  [3] 參數(shù)的熱設(shè)定

  參數(shù)的熱設(shè)定是經(jīng)常碰到的問(wèn)題。一個(gè)系統(tǒng)越復(fù)雜、可定制,它可設(shè)定的參數(shù)就越多。一個(gè)好的設(shè)計(jì)應(yīng)該能熱設(shè)定其中的參數(shù),然后執(zhí)行重新加載動(dòng)作。

  舉個(gè)實(shí)際的例子, 下面的配置文件是一個(gè)系統(tǒng)的存儲(chǔ)節(jié)點(diǎn)配置文件截圖。該截圖僅展示了大約1/5的配置參數(shù)。

  a. 如果參數(shù)不可重新熱加載,那么測(cè)試用例執(zhí)行過(guò)程中都必須進(jìn)行進(jìn)程的重啟。

  進(jìn)程的重啟勢(shì)必造成單個(gè)測(cè)試用例的時(shí)間拉長(zhǎng),復(fù)雜系統(tǒng)成百+的測(cè)試用例會(huì)造成總體測(cè)試時(shí)間的拉長(zhǎng)。每個(gè)多消耗1-2分鐘,整體就是小時(shí)級(jí)別的時(shí)間消耗。這對(duì)Slow build或完整性測(cè)試集執(zhí)行來(lái)說(shuō)是個(gè)災(zāi)難。可測(cè)性也比較差。

  b. 參數(shù)不可熱加載會(huì)在系統(tǒng)運(yùn)維期間失去熱調(diào)整參數(shù)的機(jī)會(huì),可能導(dǎo)致系統(tǒng)的間斷性停服務(wù)。這對(duì)基礎(chǔ)服務(wù)來(lái)說(shuō)是個(gè)噩夢(mèng),上層依賴于基礎(chǔ)服務(wù)的應(yīng)用可能成百上千,停服的代價(jià)過(guò)于大。一些gdb強(qiáng)行attach進(jìn)程進(jìn)行等修改變量的臨時(shí)方法由于進(jìn)程狀態(tài)的不確定性因素會(huì)帶來(lái)不小的風(fēng)險(xiǎn)。作者負(fù)責(zé)的項(xiàng)目曾出現(xiàn)gdb熱修改帶來(lái)集群主控節(jié)點(diǎn)宕機(jī)停集群的慘痛經(jīng)歷。

  參數(shù)的熱設(shè)定和加載雖然增加了一定的邏輯復(fù)雜度,但對(duì)比帶來(lái)的收益是值得付出并實(shí)踐的。

  [4] 系統(tǒng)使用信息統(tǒng)計(jì)

  系統(tǒng)使用信息的統(tǒng)計(jì)在如下方面特別重要:

  1) 產(chǎn)品線運(yùn)營(yíng)數(shù)據(jù),為產(chǎn)品運(yùn)營(yíng)、后續(xù)產(chǎn)品改進(jìn)等環(huán)節(jié)提供一手資料

  2) 運(yùn)用系統(tǒng)、集群狀態(tài)信息監(jiān)控以解決運(yùn)維過(guò)程中發(fā)生的問(wèn)題

  3) 利用系統(tǒng)狀態(tài)信息進(jìn)行內(nèi)部運(yùn)行狀態(tài)判定,以測(cè)試是否達(dá)預(yù)期

  1和2雖然不直接涉及可測(cè)性,但測(cè)試人員在系統(tǒng)設(shè)計(jì)階段需要進(jìn)行這方面的考慮以防止系統(tǒng)開(kāi)發(fā)后期進(jìn)行的功能性重構(gòu)帶來(lái)測(cè)試整體架構(gòu)重構(gòu)。系統(tǒng)接近尾聲進(jìn)行的功能性重構(gòu)對(duì)測(cè)試人員來(lái)說(shuō)是個(gè)非常頭疼的問(wèn)題。測(cè)試用例依賴的統(tǒng)計(jì)信息等接口可能被大量使用,這類的更改帶來(lái)不小的用例調(diào)整、更正工作。

  測(cè)試人員在信息統(tǒng)計(jì)的設(shè)計(jì)階段需要了解系統(tǒng)在現(xiàn)有的設(shè)計(jì)基礎(chǔ)上可能衍生的二期、三期甚至更后期的功能,以提前影響當(dāng)前的功能設(shè)計(jì),提高數(shù)據(jù)、接口、操作方面的可擴(kuò)展性。為以后可能產(chǎn)生的新功能打好可測(cè)性基礎(chǔ)。少埋坑、多考慮場(chǎng)景適應(yīng)性。

  上面的場(chǎng)景是作者在實(shí)際測(cè)試項(xiàng)目中經(jīng)常遇到的,因此抽取出來(lái)做個(gè)示例。實(shí)際的項(xiàng)目測(cè)試遇到的場(chǎng)景遠(yuǎn)比這些復(fù)雜、多樣且不可預(yù)知。這個(gè)時(shí)候需要大家多思考場(chǎng)景,多根據(jù)已有的經(jīng)驗(yàn)進(jìn)行防御性準(zhǔn)備。

  那有沒(méi)有通用的提供可測(cè)性的方法呢?

  3 提高可測(cè)性的通用方法

  摒棄原有的開(kāi)發(fā)人員只進(jìn)行單純的代碼單元測(cè)試的觀念,讓開(kāi)發(fā)人員也進(jìn)行系統(tǒng)級(jí)測(cè)試。作者在實(shí)踐過(guò)程中最推崇的方法就是此條。具體地說(shuō),開(kāi)發(fā)人員進(jìn)行的是系統(tǒng)級(jí)測(cè)試,禁止刷行覆蓋率型的單純函數(shù)覆蓋UT。由系統(tǒng)級(jí)接口或者功能來(lái)驅(qū)動(dòng)整個(gè)測(cè)試過(guò)程。無(wú)法直接進(jìn)行驅(qū)動(dòng)的測(cè)試行為需要撰寫(xiě)模擬器或者模擬模塊進(jìn)行。這樣開(kāi)發(fā)人員會(huì)切身的感受到可控性和可觀測(cè)性的重要性。進(jìn)而推動(dòng)系統(tǒng)在這兩個(gè)方面的實(shí)現(xiàn)更易用和便于測(cè)試。由此而來(lái)的良性循環(huán)能讓系統(tǒng)整體可測(cè)性始終處于較好水平。

  測(cè)試人員深度了解被測(cè)系統(tǒng),能夠在可測(cè)性出現(xiàn)問(wèn)題的時(shí)候及時(shí)指出問(wèn)題所在。只有深度了解被測(cè)系統(tǒng),詳細(xì)分析系統(tǒng)實(shí)現(xiàn)邏輯和代碼,做到可黑盒、可白盒測(cè)試的程度,才能提前預(yù)測(cè)可測(cè)性薄弱環(huán)節(jié),提前預(yù)防這樣的事情發(fā)生。在可測(cè)性出現(xiàn)問(wèn)題時(shí),及時(shí)介入和提出建設(shè)性意見(jiàn)。在需要進(jìn)行測(cè)試代碼植入以方便測(cè)試流暢進(jìn)行等方面親自動(dòng)手,協(xié)助開(kāi)發(fā)人員解決問(wèn)題。

  可測(cè)性問(wèn)題可能出現(xiàn)在系統(tǒng)的各個(gè)方面,但只要在系統(tǒng)生命周期的各個(gè)環(huán)節(jié)嚴(yán)格要求并輔以正確的方法,可測(cè)性問(wèn)題就不會(huì)成為軟件測(cè)試中不可攻破的難關(guān)。各位朋友,你遇到過(guò)哪樣的可測(cè)性難題呢?如果讓你從設(shè)計(jì)階段就貫徹好的可測(cè)性要求并在整個(gè)流程中嚴(yán)格遵守,能否解決你的難題呢?