简介
istanbul 是一个 JavaScript 代码覆盖率工具,它可以帮助我们分析代码的测试覆盖率,从而帮助我们更好的编写测试用例。在这篇文章中,我们将通过阅读 istanbul 的源码来了解它是如何实现代码覆盖率的。
项目结构
- lib: 核心代码
- misc: 一些工具
- test: 测试用例
- .jshintignore:指定哪些文件和目录应该被 JSHint 忽略,JSHint 是一个 JavaScript 代码质量工具。
- .jshintrc:JSHint 的配置文件,定义代码质量检查的规则。
- .travis.yml:Travis CI 的配置文件,用于持续集成服务的设置。
- CHANGELOG.md:项目的变更日志,记录每个版本的更新内容。
- coverage.json.md:代码覆盖率报告的 JSON 文件的解释
- download-escodegen-browser.sh:一个 Shell 脚本,用于下载 escodegen 浏览器版本。
- generate-pages.sh:一个 Shell 脚本,可能用于生成项目的文档页面。
- ignoring-code-for-coverage.md:解释如何在代码覆盖率报告中忽略某些代码的文档。
- yui-coverage-comparison.md:关于 YUI(Yahoo User Interface)库的代码覆盖率比较的文档。
- yuidoc.json:YUIDoc 的配置文件,用于生成项目的文档。
核心代码
index.js
- 导出核心模块,包括
- Instrumenter
- Store
- Collector
- hook
- Report
- config
- Reporter
- utils
- VERSION
- Writer
- ContentWriter
- FileWriter
- _yuiLoadHook
- TreeSummarizer
- assetsDir
Instrumenter.js
-
首先对node.js环境和浏览器环境进行判断,同时针对新老版本作出不同的处理
-
定义语法对象 SYNTAX
-
定义AST节点生成器 astgen
-
定义AST节点遍历器 Walker,直接定义的构造函数。主要原型方法如下:
-
- startWalk(node) 从节点node开始游走遍历
-
- apply(node, walkFn, pathElement) 对节点node应用walkFn函数(遍历时的回调函数),pathElement是一个对象,用于记录当前节点的路径信息
-
-
定义defaultWalker,walkFn的默认实现
-
定义Instrumenter类,包括配置选项和Walker类配置
-
定义Instrumenter原型方法,这些原型方法会在Waler类配置中设为回调函数,对AST节点进行遍历,插入代码
-
**插桩原理:**通过esprima生成JS代码的AST,随后通过escodegen在AST转化为代码时重新生成代码,构造覆盖率统计的全局变量,插入计数器代码,从而实现代码覆盖率的统计