blog icon indicating copy to clipboard operation
blog copied to clipboard

划词翻译、单元测试与测试覆盖率

Open lmk123 opened this issue 10 years ago • 2 comments

看标题就知道,事情还得从划词翻译说起。

最近我着手准备开发 v6.0 版的划词翻译,这意味着划词翻译将第六次被完全重写。只是这一次我发现,划词翻译实际上可以分解成多个项目:

  • chrome.storage 的使用可以优化一下,于是有了chrome-storage-wrapper
  • 用在内容脚本和 popup 页的翻译窗口可以分离出来,于是有了 selection-widget
  • 多个翻译接口的整合也可以分离出来,也就是正准备开发的 translation.js

开发 chrome-storage-wrapper 的时候,我就已经用 Jasmine 写了一套测试用例;在开发 selection-widget 的时候,我决定全面启用单元测试。初期写测试用例的时候觉得有点痛苦,写用例的时间几乎要赶上开发时间了,但是测试用例写完之后就发现好处了:下一次更改代码的时候,只需运行一次测试就知道哪些地方做了不兼容的更改,这间接的消灭了很多隐藏的 bug。

我觉得,单元测试就好像是一个项目坚强的后盾,我可以放心的修改代码,单元测试会告诉我还需要改其他哪些地方。

就这样,我一下子就爱上了单元测试。selection-widget 是一个前端项目,使用 Karma 及它丰富的插件可以很容易的运行测试并生成测试覆盖率,完全不需要动脑筋。

现在我着手准备开发 translation.js,我觉得这个项目可以做成浏览器端和 node.js 端通用的模块——除了发起 HTTP 请求的方式不同,其它逻辑实际上是共通的。使用 Browserify 能写浏览器端与 node.js 端通用的代码, superagent 则是一个浏览器端和 node.js 端都能用的 ajax 库,真是感谢万能的开源社区!

那么问题就来了——node.js 的程序如何进行单元测试并生成测试覆盖率呢?

我非常喜欢 Jasmine 的语法,所以首先考虑使用它进行单元测试,而它也提供了一个在 node.js 端使用 Jasmine 的文档,按照上面的做法试了一下,成功!说起来测试 node.js 端的代码比测试浏览器代码简单多了,不需要把文件全都加载到浏览器里,只需在测试用例里 require() 一下就好了!

下一个问题就是如何生成测试覆盖率了,毫无疑问要用到 Istanbul——也就是 karma-coverage 的核心模块。

没想到这个厉害的模块用起来这么简单——当我看到它的项目主页上写着 istanbul cover test.js 的时候吃了一鲸。只是这个命令的参数必须要是一个脚本,所以我不能从命令行运行 jasmine 来测试,需要写成一个启动测试的 js 文件——说起来很高端,其实直接照抄 Jasmine 里的代码就行了:

// test-runner.js
const jasmine = new (require('jasmine'))();

jasmine.loadConfigFile('spec/support/jasmine.json');
jasmine.execute();

然后在项目根目录使用 istanbul cover test-runner.js 就行了!

大功告成,只是为了能在项目主页上加一个 coverage | 99% 这样的图标,还需要将覆盖率数据上传到 Coveralls,这个功能参考 karma-coveralls 就知道怎么写了,原理就是把一个 locv.info 文件通过 Coveralls 提供的模块上传上去就行了。

就写这么多了,明天就付诸行动!

来自第二天的我的备注:上面说的功能都完成了,见 lmk123/translation.js

lmk123 avatar Oct 29 '15 15:10 lmk123

:+1: Jasmine 应该是前端界单元测试类库No1吧。我也非常喜欢。 不过jasmine-ajax不能在node里面用测试XMLHttpRequest。 其它几个工具倒是经常见人用,但是没用过,有空也试下。

SiZapPaaiGwat avatar Oct 30 '15 13:10 SiZapPaaiGwat

@simongfxu node.js 里可以用 nock 来模拟 http 请求与响应

lmk123 avatar Nov 01 '15 07:11 lmk123