日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JavaScript覆盖率统计实现

發(fā)布時間:2023/11/30 javascript 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaScript覆盖率统计实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

主要需求

1、 支持browser & nodejs

由于javascript既能夠在瀏覽器環(huán)境執(zhí)行,也能夠在nodejs環(huán)境執(zhí)行,因此須要能夠統(tǒng)計兩種環(huán)境下單元測試的覆蓋率情況。

2、 透明、無縫

用戶寫單元測試用例的時候,不須要為了支持覆蓋率統(tǒng)計多寫代碼,之前寫的用例無需改動就能夠直接統(tǒng)計覆蓋率情況。

原理

javascript覆蓋率的相關(guān)文章比較少。以下的圖是通過閱讀開源javascript覆蓋率工具istanbul及開源測試框架Karma的覆蓋率插件karma-coverage得出的。

javascript覆蓋率統(tǒng)計的核心思想是,在源碼對應(yīng)的位置注入統(tǒng)計代碼,當(dāng)代碼執(zhí)行之后,依據(jù)統(tǒng)計代碼統(tǒng)計的數(shù)據(jù)確定程序執(zhí)行的路徑,終于生成覆蓋率統(tǒng)計報告。



1. 轉(zhuǎn)換(instrument)

  • 使用開源工具Esprima對源碼進行語法分析生成語法樹
  • 在語法樹對應(yīng)的位置注入統(tǒng)計代碼。在程序運行到這個位置的時候?qū)?yīng)的全局變量賦值,確保運行之后可以依據(jù)全局變量知道代碼的運行流程
  • 使用開源工具Escodegen依據(jù)注入之后的語法樹生成對應(yīng)的javascript代碼,即轉(zhuǎn)換之后的代碼(instrumented code)

注:這里進行語法分析的優(yōu)點是,針對書寫不規(guī)范的代碼(比方一行多個語句),依舊可以非常好統(tǒng)計出分支覆蓋和組合覆蓋等信息。

2. 運行(run)

這一步須要先加載轉(zhuǎn)換后的代碼:

  • nodejs:直接通過對require語句進行hook來無縫實現(xiàn),后面會具體介紹
  • 瀏覽器環(huán)境:須要將轉(zhuǎn)換后的代碼傳給瀏覽器。假設(shè)是karma之類的帶server的測試框架,須要通過socket傳輸至瀏覽量器,運行完之后再將包括覆蓋率信息的運行結(jié)果傳回server。生成測試報告

然后運行單元測試。產(chǎn)生的統(tǒng)計信息會掛在全局變量this以下。

對于瀏覽器環(huán)境,this就是window,而對于nodejs環(huán)境this就是global。

3. 生成報告(report)

這一步會依據(jù)全局標(biāo)量中的覆蓋率信息生成特定格式的報告,如html、lcov、cobertura、teamcity等。

一個樣例

//source code function abs(num){if(abs > 0)return num;elsereturn -num; } //instrumented code var __cov_iypKC$dWI6uJFmvxThycaA = (Function('return this'))(); if (!__cov_iypKC$dWI6uJFmvxThycaA.__coverage__) { __cov_iypKC$dWI6uJFmvxThycaA.__coverage__ = {}; } __cov_iypKC$dWI6uJFmvxThycaA = __cov_iypKC$dWI6uJFmvxThycaA.__coverage__; if (!(__cov_iypKC$dWI6uJFmvxThycaA['/Users/lonfee88/Codes/testframe/coverage-jasmine-istanbul-karma/abs.js'])) {__cov_iypKC$dWI6uJFmvxThycaA['/Users/lonfee88/Codes/testframe/coverage-jasmine-istanbul-karma/abs.js'] = {"path":"/Users/lonfee88/Codes/testframe/coverage-jasmine-istanbul-karma/abs.js","s":{"1":1,"2":0,"3":0,"4":0},"b":{"1":[0,0]},"f":{"1":0},"fnMap":{"1":{"name":"abs","line":1,"loc":{"start":{"line":1,"column":-15},"end":{"line":1,"column":17}}}},"statementMap":{"1":{"start":{"line":1,"column":-15},"end":{"line":6,"column":1}},"2":{"start":{"line":2,"column":1},"end":{"line":5,"column":14}},"3":{"start":{"line":3,"column":2},"end":{"line":3,"column":13}},"4":{"start":{"line":5,"column":2},"end":{"line":5,"column":14}}},"branchMap":{"1":{"line":2,"type":"if","locations":[{"start":{"line":2,"column":1},"end":{"line":2,"column":1}},{"start":{"line":2,"column":1},"end":{"line":2,"column":1}}]}}}; } __cov_iypKC$dWI6uJFmvxThycaA = __cov_iypKC$dWI6uJFmvxThycaA['/Users/lonfee88/Codes/testframe/coverage-jasmine-istanbul-karma/abs.js']; function abs(num){__cov_iypKC$dWI6uJFmvxThycaA.f['1']++;__cov_iypKC$dWI6uJFmvxThycaA.s['2']++;if(abs>0){__cov_iypKC$dWI6uJFmvxThycaA.b['1'][0]++;__cov_iypKC$dWI6uJFmvxThycaA.s['3']++;return num;}else{__cov_iypKC$dWI6uJFmvxThycaA.b['1'][1]++;__cov_iypKC$dWI6uJFmvxThycaA.s['4']++;return-num;}}

node.js集成覆蓋率

通過hook能夠直接無縫的載入轉(zhuǎn)換后的代碼。能夠?qū)σ韵聝煞N語句進行hook:

  • require
  • vm.createScript

對require進行hook的代碼是通過對Module._extensions['.js']進行賦值實現(xiàn)的:

function hookRequire(matcher, transformer, options) {options = options || {};var fn = transformFn(matcher, transformer, options.verbose),postLoadHook = options.postLoadHook &&typeof options.postLoadHook === 'function' ? options.postLoadHook : null;Module._extensions['.js'] = function (module, filename) {var ret = fn(fs.readFileSync(filename, 'utf8'), filename);if (ret.changed) {//加載instrument之后的代碼并執(zhí)行module._compile(ret.code, filename);} else {//加載原來的代碼并執(zhí)行originalLoader(module, filename);}if (postLoadHook) {postLoadHook(filename);}}; }

hook使覆蓋率的集成變得簡單。甚至不須要寫代碼,比方Mocha的覆蓋率集成,僅僅須要改用例如以下的調(diào)用方式就可以:

istanbul cover _mocha -- -R spec test/spec

瀏覽器集成覆蓋率

瀏覽器集成覆蓋率就略微麻煩一點。好在istanbul提供了API:

  • 轉(zhuǎn)換代碼(調(diào)用istanbul的Instrumenter接口)
  • 將instrumented code發(fā)送到瀏覽器(自己實現(xiàn))
  • 將包括覆蓋率信息的運行結(jié)果發(fā)回server(自己實現(xiàn))
  • 依據(jù)返回的覆蓋率信息生成覆蓋率報告(調(diào)用istanbul的Reporter接口)
  • 轉(zhuǎn)載于:https://www.cnblogs.com/jzdwajue/p/6900462.html

    總結(jié)

    以上是生活随笔為你收集整理的JavaScript覆盖率统计实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。