不熟悉cdp的可以參見前文:Chrome remote debugging protocol在自動化測試中的應(yīng)用和實踐
cov的數(shù)據(jù)結(jié)構(gòu)
首先痰憎,使用takePreciseCoverage方法來拿到j(luò)s執(zhí)行數(shù)據(jù)罚勾,這個數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)是這樣的:
'result': {
'result': [{
'scriptId': '17',
'url':'https://www.xxxxxxxxx.com/browser/guide.js',
'functions': [{
'functionName': 'get',
'ranges': [{
'startOffset': 0,
'endOffset': 4273,
'count': 1
}],
'isBlockCoverage': False
},
}],
}],
}
......
一個result包含多個js的統(tǒng)計情況托启,每個url基本就是js的請求地址;在每個js的統(tǒng)計情況里屯耸,又有多個function的統(tǒng)計情況,每個function里的startOffset和endOffset指的是這個方法的被統(tǒng)計語句按字節(jié)位置來算的開始位置和結(jié)束位置线召,count代表這段語句是否被執(zhí)行到多矮,1代表是缓淹,0代表否塔逃。
因此,思路就是湾盗,拿到測試完成后的js統(tǒng)計數(shù)據(jù),然后通過每個js統(tǒng)計數(shù)據(jù)里的每個function的統(tǒng)計坐標值和統(tǒng)計狀態(tài)躏吊,和原始js數(shù)據(jù)比對,從而實現(xiàn)對js覆蓋狀況的總覽颜阐。
下面說一下具體流程。
過濾cov數(shù)據(jù)
cov數(shù)據(jù)(也就是上文的js統(tǒng)計數(shù)據(jù))不是直接可用的凳怨,因為首先獲取到的覆蓋率是十分全面的,全面到會有很多額外的你不想要的數(shù)據(jù)紫新,比如通用的js類庫李剖,還有dev tools操作時的js數(shù)據(jù)等等,所以第一步是過濾cov數(shù)據(jù)篙顺。
過濾分為兩步,第一步是過濾掉你不需要的js統(tǒng)計數(shù)據(jù)德玫,這里根據(jù)主域名來過濾,具體是寫了cov_domain_filter()這個方法(詳見源碼材彪,下同琴儿。)段化,接受一個數(shù)組造成,數(shù)組內(nèi)容是你要過濾的主域名列表,然后返回給你只留下含有主域名的js的統(tǒng)計數(shù)據(jù)谜疤。
第二步现诀,因為這個統(tǒng)計數(shù)據(jù)包含了所有的執(zhí)行狀態(tài)的統(tǒng)計,包括覆蓋到的和未覆蓋到的坐桩,我們只需要標注出未覆蓋到的代碼,就可以體現(xiàn)出覆蓋情況绵跷,因此這里進一步過濾了狀態(tài),只留下了未覆蓋到的代碼的統(tǒng)計情況碾局,具體方法是cov_not_count_filter()。
至此净当,我們的數(shù)據(jù)就過濾完成了。
合并cov數(shù)據(jù)
仔細研究了一下cov數(shù)據(jù)俘闯,發(fā)現(xiàn)每個js的統(tǒng)計數(shù)據(jù)里忽冻,會有相同的function的統(tǒng)計數(shù)據(jù)真朗,例如前面有一個function test僧诚,他的數(shù)據(jù)是{startoffset:10;endoffset:29},后面又可能存在一個unction test,他的數(shù)據(jù)是{startoffset:30;endoffset:60},當然他們的數(shù)據(jù)不一樣蹭睡,我猜測他是根據(jù)測試的進程赶么,不斷的在js的統(tǒng)計數(shù)據(jù)里追加方法統(tǒng)計數(shù)據(jù),這點沒有徹底的領(lǐng)悟作者的意圖辫呻。
出于后面的統(tǒng)計結(jié)果展示方便,這里我把這種數(shù)據(jù)都給合并了祟昭,例如前文的例子怖侦,把他的數(shù)據(jù)合并了就是{startoffset:10;endoffset:60}篡悟,這樣每個js的統(tǒng)計數(shù)據(jù)里匾寝,只可能存在一個方法,每個方法會有多個不可再合并的統(tǒng)計數(shù)據(jù)急凰,這里的方法是merge_same_func_ranges猜年。
對比和追加cov數(shù)據(jù)
如果只進行一次的測試過程的覆蓋率收集疾忍,那么這一步是不必要做的床三,但是,考慮到一個模塊可能要多個測試用例才能覆蓋完流程分支撇簿,那么要想獲得這個模塊的覆蓋率,就只有在每個用例完成后补疑,將收集的cov數(shù)據(jù)和前一次的進行對比和追加。
這里是寫的很痛苦了诊胞,因為cov的數(shù)據(jù)結(jié)構(gòu)不是我是谷歌制定的锹杈,本身對于為什么要這么設(shè)計也并不理解充分,這個數(shù)據(jù)結(jié)構(gòu)層級非常的深竭望,所以要對比并進行追加就非常的繁瑣,這里用了大量的列表推導式來代替for循環(huán),否則for循環(huán)會更多影钉,這個方法是make_covdata_file掘剪。
將cov數(shù)據(jù)最終展示
cov數(shù)據(jù)處理完,還需要一個網(wǎng)頁進行展示廉赔,這里是用了一個模板類匾鸥,通過設(shè)立html模板,將數(shù)據(jù)替換扫腺,再生成從而實現(xiàn)了簡單的網(wǎng)頁展示村象,如果你有更高的需求可以自行進行設(shè)計攒至。
這里要說的是著色器模塊迫吐,也就是給數(shù)據(jù)上背景色,設(shè)計上是通過對未覆蓋的代碼兩端插入背景色的html代碼來實現(xiàn)未覆蓋代碼的醒目展示志膀,這里存在一個算法問題鳖擒,因為你不能直接根據(jù)代碼的起始坐標(也就是startoffset和endoffset)直接插入背景色html代碼,因為當你第一次插入的時候是沒問題的蒋荚,但你要在下一個坐標插入的時候,就會出問題惊奇,因為你之前插入了代碼的緣故播赁,對下一個坐標而言,已經(jīng)不是真實坐標了容为,需要加上之前背景色代碼的偏移量。
這里我不(jiu)得(shi)已(lan)采用了一個非常犧牲性能的辦法竭缝,就是直接拿cov數(shù)據(jù)復制出副本沼瘫,用需要加背景的代碼的起始坐標拿出這部分的字符串抬纸,然后在副本里搜索并添加背景代碼耿戚,然后再替換回去(捂臉哭)。
最終的展示效果
這里我做了一個簡單的本地文件作為示例坛猪,看一下最終結(jié)果皂股。
為了方便演示,整個profiler模塊被我集成進了之前的一個ui測試框架里就斤,例子也直接扔進去了,只需要把這個項目clone下來洋机,然后把環(huán)境變量修改為你的,再運行process模塊就可以體驗绷旗,當然你也可以直接使用這個模塊。
項目地址:https://github.com/icesword0760/uitest-keyword
一些tips
1.不能用于壓縮混淆后的js上庄岖;
2.因為展示部分的著色器算法性能損耗過大角骤,所以如果你要生成報告的話會很慢,有興趣的可以自己重寫這部分启搂。
3.php項目,結(jié)合博客里的php覆蓋率統(tǒng)計方法牢撼,可以和這個模塊一起做到前后端代碼覆蓋率統(tǒng)計疑苫。