本文來自網易雲社區css
做者:倪志風java
最近一直對測試覆蓋率方面的內容比較感興趣,雖然不少項目都早已經用上了Jacoco來實現測試覆蓋率的統計,可是不多看到實際項目中基於覆蓋率統計來指導測試的實踐。這篇文章是我近期基於代碼變動風險(CR)平臺 (http://cr.qa.netease.com/)對猛獁大數據系統的後臺調度組件Azakban的一個小版本的測試實踐。
mysql
我的認爲,代碼覆蓋率應該是對一個版本測試狀況的一個重要考量。不能說代碼覆蓋率高,就是沒有風險。可是,相反,我以爲若是代碼覆蓋率很低,那就是客觀地存在較大風險,說明咱們測試的充分度不夠。CR平臺,實際上是基於jacoco覆蓋率統計的結果之上,將提測版本與基準版本(一般是上一個線上穩定版本)的代碼庫進行比對,統計出一個版本提測後開發變動代碼的覆蓋狀況。另外,藉助了其餘開源工具(ckjm、javancss等)展現了代碼中類之間的相互調用關係以及複雜度信息等等。git
下面是我在猛獁4.8.5版本中,藉助CR平臺對Azkaban相關需求的測試實踐:sql
例子一: 數據庫
1. 看需求和JIRA 服務器
開發寫的需求: 併發
「 補數據優化,加強順序性,優化實例生成數量:原來有的邏輯是Trigger每一個一分鐘觸發一次,而後產生一個補數據實例到分發隊列,分發隊列每次分發前,先檢查有沒有正在運行的實例,若是沒有就隨機選擇一個實例分發下去執行。若是有,從新放回隊列。這個邏輯存在的問題是,會產生大量的實例在分發隊列,耗費內存和CPU時間。如今作的優化是:Trigger每次觸發前,先檢查分發隊列以及已經分發下去的實例裏邊是否有相關的補數據實例。若是有,則跳過此次觸發。另外能夠經過 az.backfill.concurrent.num 指定補數據實例產生的併發度(範圍1~100,缺失默認值 1)。」工具
看着可能有點暈,我稍微將它簡化一下就是: gitlab
a. 補數據調度,本來可能會產生大量併發執行的實例,如今限制併發實例數只能是1。即:前一次實例執行完成後,後一次調度實例纔會生成。
b. 提供參數, az.backfill.concurrent.num來控制容許的併發實例數量,該參數的範圍是1-100。
至於JIRA,我這邊就不重複添圖了,大體跟需求內容差很少。
2. 查看Gitlab:
開發提交gitlab代碼時與jira作了關聯,點擊連接能夠直接跳轉到gitlab:
能夠看到該jira影響的類有兩個,分別是:GlobleAttribute.java (只添加了一行常量定義)和 TriggerManager.java
3. 查看CR:
開始測試該功能前,先看一眼CR的覆蓋狀況(CR以前執行過自動化測試用例和其餘手工測試用例):
能夠看到,在表格裏沒有出現GlobleAttribute.java(不知是不是由於該類只添加了一行常量定義,改動過小的緣故),而TriggerManager.java類的改動部分覆蓋率爲63.6%。點進去再仔細看下新修改的行的覆蓋狀況:
能夠看到「新修改」的未覆蓋部分(紅色)主要是由於 if (t.getContext().containsKey(GlobleAttribute.AZ_BACKFILL_INSTANCES_NUM))判斷沒有命中,由於該需求引入了新的參數 az.backfill.concurrent.num 指定補數據實例產生的併發度 。而該參數咱們還並無設置過。
此外,下面的未覆蓋部分, if 判斷的後半段 flow.getScheduleType().equals(ScheduleType.BACKFILL)未命中的緣由是由於咱們還並無執行過補數據的調度。
4. 執行手工測試
對一個做業流設置補數據調度100次,指定補數據實例產生的併發度爲5(設置參數az.backfill.concurrent.num 的值爲5),驗證補數據調度按照既定場景正確執行。
5. 測試結果
查數據庫顯示,補數據調度按照順序執行, 可是實例個數始終爲1。
顯然,該需求的基本功能生效了(從之前的併發實例數不受限,如今實例個數爲1),可是併發度參數並無生效。
6. 結果分析排查
從新執行覆蓋率統計,再來看一眼CR平臺的新的結果:
能夠看到,覆蓋率有必定的提高。可是爲何併發參數設置沒有生效呢? 來看一眼服務器上的執行日誌,拉到日誌的最後,看到有一條頻繁打印的日誌:「backfill trigger 3959, .......」:
再對照一下CR平臺上變動的代碼:
能夠看到,下面這部分「新修改」的代碼應該打印的日誌還處於「未覆蓋」的狀態。往上看,發現紅框中圈出的代碼段裏打印的日誌 恰好就是服務器上後臺的日誌。看一眼判斷條件: 「判斷該做業流是否已經有執行實例正在執行中,且該正在執行中的做業流實例的開始時間距離如今不到10分鐘 」 。
這樣就初步解釋了 目前階段爲何咱們沒看到「新修改」日誌打印,以及實例沒有生成的直接緣由。即: 被以前的判斷條件錯誤攔截了。
等待10分鐘,咱們繼續查看數據庫的結果,發現併發的實例數仍爲1。 再看一眼CR的覆蓋狀況:
能夠看到,剛纔未覆蓋的這段日誌打印,在10分鐘過去後被執行了。爲了確認該數據的準確性,再看一眼日誌,此次咱們直接搜索「Reach az.backfill.instances.num ......」這條日誌:
能夠看到,日誌確實出現了變化。也就是說,服務器執行的代碼進入了判斷: 「到達了補數據實例個數的上限 isReachBackfillInstanceNum(t)」 。
然而,咱們設置的上限明明是5,爲何卻顯示已經達到上限,而數據庫裏的實際併發數仍是1呢?
再看一眼,變動代碼中未覆蓋的變動行:
能夠發現,在isReachBackfillInstanceNum(t)方法中,恰好找到了咱們想要的內容:默認的補數據實例個數backfillInstancesNum爲1,當調度t的上下文信息context中包含參數GlobalAttribute.AZ_BACKFILL_INSTANCES_NUM時,就用該對應的值賦值給backfillInstancesNum。且會對該範圍進行1-100的判斷。
而這段代碼正好沒有被執行。
再次進入源碼查看,發現了個驚人的事情:
這個AZ_BACKFILL_INSTANCES_NUM參數的實際key值,應該是az.backfill. instances.num,而開發兄弟在需求和jira中寫的都是「az.backfill. concurrent.num」。
此時,個人心情是複雜的。此處須要省略1000字。
如你所知,後續修改參數key後,從新測試,成功測試經過。經過後的覆蓋率統計狀況:
惟一沒有覆蓋的行,是由於設置的併發參數的值是5,在該1-100範圍內,因此沒有進入該判斷。
例子二:
篇幅有限,再來簡單介紹另外個利用CR平臺完善測試的例子。
需求:
將執行節點的流實例併發數量的值寫進db,在節點服務啓動時,優先從db中讀取加載進內存。若是db中不包含,再從配置文件讀取。
簡單測試後, 看下CR平臺的覆蓋狀況:
能夠看到,對於基本的正常功能,咱們仍是覆蓋到了。 可是仍有大部分語句沒有覆蓋,而這部分未覆蓋的內容其實就是查詢數據庫時發生異常狀況。
知道未覆蓋的緣由,就好辦了,咱們只要製造數據庫查詢異常就能夠模擬該場景。
測試方式:
執行數據庫語句alter table executors drop column threads_num; 將mysql中executor表的threads_num字段給刪掉。而後從新啓動executor。並確保executor能夠正常工做。
再次執行覆蓋率統計,查看CR平臺的結果:
能夠看到,這下「新修改」的代碼所有覆蓋了。能夠妥妥地在jira上標上這功能測試經過。
總結
最近看了一些業界的測試方法,發現基於覆蓋率統計的白盒測試的熱度正在逐漸提高,包括騰訊、去哪兒等一些公司都有基於覆蓋率統計指導測試的很多實踐。包括分析代碼增量覆蓋率,分析每條用例對覆蓋率的貢獻來精簡測試用例集、剔除無效用例,基於執行覆蓋統計將每條用例與代碼模塊相對應等等。所幸,咱們也有CR平臺,基於CR平臺,咱們後續能夠作的事情應該還有不少。
網易雲免費體驗館,0成本體驗20+款雲產品!
更多網易研發、產品、運營經驗分享請訪問網易雲社區。
相關文章:
【推薦】 責任鏈模式的使用-NettyChannelPipeline和MinaIoFilterChain分析
【推薦】 用戶研究如何獲取更爲真實的用戶信息