我在之前的项目中编写了 Mocha 测试。它的好处是 Istanbul 尔代码覆盖率工具。它非常有用而且很酷。 现在我正在为我当前的项目使用 pytest。有些服务是 Nodejs 应用程序。现在我的问题是,当我使用 pytest 时,有没有办法获得 Nodejs 应用程序的代码覆盖率?
最佳答案
结合istanbul
和coverage
工具的覆盖率报告有两个主要问题需要解决:
- 当然,
coverage
对 javascript 文件一无所知,因此我们必须在覆盖率运行中以某种方式注册它们 - 这将通过实现自定义插件来完成。 - 我们必须将
istanbul
的覆盖率报告转换为coverage
可以理解的格式。
设置
由于代码片段太大,无法直接放入答案中,所以我准备了一个git repository您可以使用以下命令重现测试运行(当然您可以根据需要重用代码):
$ git clone https://github.com/hoefling/stackoverflow-52124836
$ cd stackoverflow-52124836/
$ yarn install
首先生成 Istanbul 尔报道报告:
$ yarn test
yarn run v1.9.4
warning package.json: No license field
$ istanbul cover _mocha js
Array
#length
✓ should be 0 when the array is empty
✓ should be 1 when the array has one element
✓ should be 2 when the array has two elements
Array
#indexOf()
✓ should return -1 when the value is not present
4 passing (5ms)
=============================================================================
Writing coverage object [/private/tmp/stackoverflow-52124836/coverage/coverage.json]
Writing coverage reports at [/private/tmp/stackoverflow-52124836/coverage]
=============================================================================
=============================== Coverage summary ===============================
Statements : 100% ( 14/14 )
Branches : 100% ( 0/0 )
Functions : 100% ( 8/8 )
Lines : 100% ( 14/14 )
================================================================================
现在使用 pytest
运行 python 测试:
$ python -m pytest -sv --cov=py --cov=js --cov-report=term-missing
=================================== test session starts ===================================
platform darwin -- Python 3.6.4, pytest-3.7.3, py-1.5.4, pluggy-0.7.1 --
/Users/hoefling/.virtualenvs/stackoverflow/bin/python
cachedir: .pytest_cache
rootdir: /private/tmp/stackoverflow-52124836, inifile:
plugins: cov-2.5.1
collected 1 item
py/test_spam.py::test_spam PASSED
---------- coverage: platform darwin, python 3.6.4-final-0 -----------
Name Stmts Miss Cover Missing
-------------------------------------------------------
js/array.length.spec.js 14 0 100%
js/array.spec.js 8 0 100%
py/test_spam.py 2 0 100%
-------------------------------------------------------
TOTAL 24 0 100%
================================ 1 passed in 0.56 seconds =================================
js
/py
目录
这些只是一些可供使用的示例测试文件。为了简化设置,istanbul
收集测试代码的覆盖率。
mycov
包含覆盖
插件。有关如何编写覆盖率插件的详细信息,请参阅 Plug-in classes ;这里我只是解释一下相关的地方:
class IstanbulPlugin(coverage.plugin.CoveragePlugin, coverage.plugin.FileTracer):
def file_reporter(self, filename):
return FileReporter(filename)
def file_tracer(self, filename):
return None
def find_executable_files(self, src_dir):
yield from (str(p) for p in pathlib.Path(src_dir).rglob('*.js')
if not any(d in p.parts for d in ('node_modules', 'coverage',)))
插件类除了搜索 javascript 文件并将它们注册为 coverage
run(find_executable_files
方法)中的执行文件之外,什么也不做。它根本不记录代码覆盖率!它还为 javascript 文件注册一个简单的文件报告器 impl:
class FileReporter(coverage.plugin.FileReporter):
def source(self):
with open(self.filename) as fp:
js = fp.read()
return js
def lines(self):
return {i + 1 for i, line in enumerate(self.source().split(os.linesep)) if line.strip()}
记者按原样返回javascript文件的源代码,可执行行都是不为空的代码行。
注1:
这个 impl 还不够!例如,行和 block 注释行将被计为可执行文件。您需要调整lines
方法;最好是使用一些 JavaScript 代码解析器来提取有关可执行行的信息。
注2:
istanbul
和 coverage
都从 1 开始计算行数,而不是从 0 开始计算行数,因此行号发生了变化。
现在您需要通过coverage_init
注册插件:
# mycov/__init__.py
def coverage_init(reg, options):
reg.add_file_tracer(IstanbulPlugin())
并在.coveragerc
中添加自定义插件:
[run]
plugins = mycov
将istanbul
报告附加到coverage
现在 coverage
知道要考虑 javascript 文件,我们将把 js 覆盖率与 python 合并。 conftest.py
中的装置 append_istanbul_coverage
负责此操作。
@pytest.fixture(autouse=True)
def append_istanbul_coverage(cov):
yield
with open('coverage/coverage.json') as fp:
data = json.load(fp)
converted = {'lines': {item['path']: line_numbers(item) for item in data.values()}}
text = "!coverage.py: This is a private format, don't read it directly!" + json.dumps(converted)
istanbul_cov = coverage.data.CoverageData()
with io.StringIO(text) as fp:
istanbul_cov.read_fileobj(fp)
cov.data.update(istanbul_cov)
每次测试运行时, fixture 将自动执行一次,当所有测试完成时,将运行 yield
之后的代码。 cov
fixture由 pytest-cov 提供;我们用它来访问当前的覆盖数据对象。首先,我们阅读 Istanbul 尔的报道;然后将其转换为 coverage
可以理解的字符串 - 这只是普通的 json
,前面添加了特殊消息。之后,剩下的就是更新当前的覆盖范围
数据,我们就完成了!
关于javascript - 当用 python (pytest) 编写测试时,有没有办法实现 Nodejs 代码覆盖率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52124836/