转自玉伯的blog。
最近在用 Jasmine 给 KISSY 项目添加测试代码,遇到一个困惑:如何保证测试能完整覆盖到源码的所有分支?
用 Google 搜索了下 JavaScript Coverage 工具,琳琅满目。有商业版的 JavaScript Coverage Validator, 还有 FireBug 的不少扩展 JavaScript Code Coverage Tool for Firebug. 美中不足是,这些要么要花钱,要么已停止更新,杯具。
最后将目标锁定到免费开源一直更新的:JSCoverage. 不用不知道,一用立刻相见恨晚。下面简单介绍下。
下载安装非常简单,到 这里 下载 window 版本。完成后,将压缩包里的 jscoverage.exe 复制到C:\Windows\System32
. 安装完毕。
我们以 cookie 模块为范例。命令行模式,在 cookie 的上级目录 src 下输入:
jscoverage.exe cookie cookie_ --encoding=utf-8 --no-instrument=tests
运行后,就会生成 cookie_ 目录。原理是将需要检测的 js 文件重新编译,分析原始语句,并插入相应的监测代码。有兴趣的可以打开 cookie_/cookie.js 文件观摩。
--no-instrument=tests
是告诉 jscoverage 不要理会 tests 目录下的 js 文件。tests 目录下存放的是 Jasmine 测试文件,不需要监测。
接下来,在浏览器中通过服务器浏览就可以了: cookie_/jscoverage.html
在打开的页面中,点击 Summary, 可以看到:
非常清晰:cookie.js
的测试覆盖率为 91%, 点击 cookie.js
切换到 Source Tab, 可以具体看到哪些代码行没有执行。
一切就这么简单。利用 jscoverage-server.exe
, 还可以生成报告,这里就不细说了,具体请看 JSCoverage User Manual.
有了 Jasmine, 让我们可以大胆重构代码和添加新功能。
有了 JSCoverage, 则让我们对 Jasmine Specs 的覆盖率有了全局掌握,可以随心所欲。
希望这篇文章,能让你对 JS Test Coverage 工具有个初步了解。好了,继续干活。
上班途中想到的,到公司后一测,果然如此。看 test.js
:
function testFn(a, b, c) { var ret = 0; if(a || b || c) { ret++; } return ret; } testFn(1);
JSCoverage 覆盖率 100%:jscoverage.html?test.html
实际上,testFn(0, 1); testFn(0, 0, 1);
等情形都没覆盖到。原因很简单, if 语句中存在或,但 jscoverage 生成的代码,是以代码行为单位的:
_$jscoverage['test.js'][6]++; if ((a || b || c)) { _$jscoverage['test.js'][7]++; (ret++); }
能想到的一种完善方式:对于逻辑表达式,要进一步插入监测代码:
if (((_jsc() && a && _jsc()) || (_jsc() && b && _jsc()) || (_jsc() && c && _jsc()))) { // ... } // _jsc() 是 _$jscoverage['test.js'][n]++ 的示意写法
不过貌似把问题搞复杂了。
总之目前我们要知道:在 JSCoverage 里,100% != 100%.