1、简介
NYC,一款开源的用于测试Javascript脚本代码覆盖率的工具,全称是什么不知道,暂且叫它“Now You’re Covered”吧。使用此工具可实现对JS脚本中:statement(语句)、line(行数)、function(函数)、branch(条件,循环等)的覆盖率统计能力。
2、Github网址:
https://github.com/istanbuljs/nyc
3、环境依赖
- Ubuntu 18.04
- Nodejs V14.15.4
4、安装教程
-
新建目录并进入
mkdir nyc_coverage cd nyc_coverage
-
初始化node项目
npm init
-
安装NYC工具
npm install nyc
5、使用方法
例如,对testcase.js脚本覆盖率的检测:
./node_modules/nyc/bin/nyc.js --reporter=json-summary --report-dir=./report --temp-dir=./nyc_output node ./testcase.js
NYC工具的使用需要指定一些参数,参数的指定可以采用配置文件的方式,也可以采用命令行的方式。此处我们采用命令行的方式。
检测结果存储于report文件夹的coverage-summary.json文件内,如下所示:
该文件从四个方面分别展示了每个脚本的测试覆盖率信息,以及所有脚本覆盖率信息的平均值。
注意:
-
NYC只能在当前文件夹下收集测试用例,所以必须将测试用例放在与
node_modules
平级的目录 -
如果需要统计多个测试用例的覆盖率平均值,需要将
clean
参数设置为false,保证每一次统计时不清空缓存文件夹。
参数介绍
-
all
:是否为包括依赖文件在内的所有的JS文件插桩。 -
check-coverage
: 检查覆盖率结果是否在阈值范围之内。 -
extension
: 测试用例中使用到的扩展文件。 -
include
: 引入测试用例使用到的依赖文件,例如使用require导入的模块。 -
exclude
: 排除一些文件,不进行覆盖率检测。 -
reporter
: 覆盖率报告生成的形式。 -
report-dir
: 覆盖率报告输出的位置。 -
skip-full
: 跳过展示覆盖率未达到100%的文件。 -
temp-dir
: 原始覆盖率信息输出的位置 -
clean
: 在执行用例前是否清空temp-dir
文件夹。 -
cache
: 是否保留插桩文件信息。
6、一个自动测试多个JS文件的python脚本
#!/usr/bin/env python
# coding=utf-8
import json
import os
import shutil
import subprocess
import sys
corpus_dir = r"/root/data/codeCoverage/corpus"
report_dir = r"/root/data/codeCoverage/report"
temp_dir = r"/root/data/codeCoverage/nyc_output"
os.chdir("/root/data/codeCoverage")
def coverage(file_path):
# calculate the coverage of simple file
cmd = ["timeout", "-s9", "60", "/root/data/codeCoverage/node_modules/nyc/bin/nyc.js",
"--reporter=json-summary", "--cache=false", "--report-dir=" + report_dir, "--temp-dir=" + temp_dir,
"--clean=false", "node", file_path]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.communicate()
def extractCoverage():
coverage_file = os.path.join(report_dir, "coverage-summary.json")
with open(coverage_file, "r", encoding="utf-8") as f:
content = f.read()
coverage_message = json.loads(content)
statement_cov = coverage_message['total']["statements"]['pct']
function_cov = coverage_message['total']["functions"]['pct']
branch_cov = coverage_message['total']["branches"]['pct']
line_cov = coverage_message['total']["lines"]['pct']
return [statement_cov, function_cov, branch_cov, line_cov]
def reset_dir(dir_path):
if not os.path.exists(dir_path):
os.mkdir(dir_path)
else:
shutil.rmtree(dir_path)
os.mkdir(dir_path)
if __name__ == '__main__':
i = 0
for root, dirs, files in os.walk(corpus_dir):
for file in files:
file_path = os.path.join(root, file)
if file_path.endswith(".js"):
process = "\rprocessing: {}".format(str(i))
sys.stdout.write(process)
coverage(file_path)
i += 1
coverages = extractCoverage()
print("\ncoverage results:")
print("statement coverages: %s" % coverages[0])
print("function coverages: %s" % coverages[1])
print("branch coverages: %s" % coverages[2])
print("line coverages: %s" % coverages[3])
print(f"\n------------------------------------------------------")
print("Coverage messages has been saved to '/root/data/codeCoverage/report/coverage-summary.json'")
print(f"------------------------------------------------------\n")