11月阅读周·编写可测试的JavaScript代码:代码覆盖率之持久化覆盖率信息篇
背景
去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。
没有计划的阅读,收效甚微。
新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。
这个“玩法”虽然常见且板正,但是有效,已经坚持阅读十个月。
已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScript(中卷)》、《你不知道的JavaScript(下卷)》、《数据结构与算法JavaScript描述》、《WebKit技术内幕》、《前端架构:从入门到微前端》、《秒懂算法:用常识解读数据结构与算法》、《JavaScript权威指南》、《JavaScript异步编程设计快速响应的网络应用》。
当前阅读周书籍:《编写可测试的JavaScript代码》。
持久化覆盖率信息
持久化覆盖率信息,也就是将信息从浏览器的内存中取出来并保存在本地磁盘里。这里的“本地”是表示运行测试文件的Web服务器。每个页面在刷新时,页面上所加载的JavaScript的覆盖率信息都会被清除,因此在刷新页面之前,必须要把覆盖率信息保存到磁盘的某个地方,否则它将永远消失。
单元测试
在学会本地保存覆盖率信息之前,需要阅读本节内容。对于单元测试,持久化覆盖率信息和持久化单元测试结果有同样的问题——也就是说,需要向服务器发送POST或Ajax请求进行持久化。通常,不用Web服务器就可以运行单元测试:将HTML文件加载到浏览器中,然后运行测试即可。然而,要持久化测试结果和覆盖率信息的话,需要Web服务器的帮助才行。
YUI Test提供了一些辅助钩子,可以以各种格式获取该信息:
var testRunner = Y.Test.Runner;
testRunner.subscribe(testRunner.TEST_SUITE_COMPLETE_EVENT, getResults);
testRunner.run();
function getResults(data) {
var reporter = new Y.Test.Reporter('http://www.yourserver.com/path/to/target', Y.Test.Format.JUnitXML);
reporter.report(results);
}
在每一个测试套件的底部使用上述代码片段,元测试报告就会以JUnit XML格式发送到服务器上,该格式可以被Hudson/Jenkins和许多其他的构建工具所识别。YUI还提供了XML、JSON以及TAP格式的输出。对于XML和JSON格式,我们需要自己进行处理,但是对于TAP格式,Perl语言里有大量的工具可以识别它。
传递测试结果的时候,还可以顺便捎回覆盖率结果:
function getResults(data) {
// Use JUnitXML format for unit test results
var reporter = new Y.Test.reporter('http://www.yourserver.com/path/to/target', Y.Test.Format.JUnitXML);
// Toss in coverage results
reporter.addField('coverageResults', Y.Test.Runner.getCoverage(Y.Coverage.Format.JSON));
// Ship it
reporter.report(results);
}
reporter对象上的addField方法,允许向服务器回传任何数据。在本例中,我们回传的是覆盖率结果,将其编码为JSON,并和单元测试结果一起传递。注意,JSON是覆盖率信息的唯一智能输出形式,它是YUI覆盖率报表工具所期望的格式。
上述代码的最终结果是,向服务器发送携带results和coverageResults参数的POST请求。至此,这两块数据就可以保存到本地文件系统中了。
集成测试
使用Selenium对集成测试的覆盖率信息进行持久化遵循类似的模式。在运行Selenium测试之后,以及导航离开当前页面之前,必须进行覆盖率信息的收集并将其传递到服务器。Selenium提供的tearDown和after钩子可用于存放这些代码,以确保可以捕获覆盖率信息。
使用Selenium时,最好的办法是使用全局变量_yuitest_coverage,该变量保存了所有的覆盖率信息。使用Selenium1的示例代码如下:
String coverage = selenium.getEval('JSON.stringify(window._yuitest_coverage)');
使用Selenium2/WebDriver的示例代码如下:
String coverage = (String)((JavaScriptExecutor) driver).executeScript('return JSON.stringify(window._yuitest_coverage)');
然后简单地将coverage字符串输出到文件中,理想情况下,在测试之后会将其命名为像testClick.coverage.json这样的名称。
要记住,如果应用程序包含iframes框架,对iframe框架页面代码所生成的覆盖率信息不会被保存到顶级_yuitest_coverage变量。在顶级主窗口收集到代码覆盖率信息之后,需要告知Selenium1,要使用类似如下代码:
selenium.SelectFrame('src=foo.html');
使用上述代码,可以获取_yuitest_coverage变量的内容。
总结
可以使用任何Selenium选择符,选择要从中提取代码覆盖率的iframe。
确保要将每个iframe的_yuitest_coverage数据聚合到总覆盖率报告。
作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。
- 点赞
- 收藏
- 关注作者
评论(0)