8

这是一个项目和输出的链接,您可以使用它来重现我在下面描述的问题。

我正在对多个版本的 python使用tox覆盖。我的 tox.ini 文件如下所示:

[tox]
envlist =
    py27
    py34

[testenv]
deps =
    coverage

commands =
    coverage run --source=modules/ -m pytest
    coverage report -m

我的问题是覆盖将只使用一个版本的python(在我的例子中是py27)运行,而不是py27和py34。每当我的代码执行依赖于 python 版本时,这就是一个问题,例如:

def add(a, b):
    import sys
    if sys.version.startswith('2.7'):
        print('2.7')
    if sys.version.startswith('3'):
        print('3')
    return a + b

针对上述代码运行覆盖将错误地报告第 6 行(“print('3')”)对于 py27 和 py34 都是“缺失”的。它应该只适用于 py34。

我知道为什么会这样:覆盖安装在我的基本操作系统(使用 python2.7)上。因此,当tox运行时,它会注意到已经安装了 coverage,并从基本操作系统继承了 coverage,而不是将其安装在它创建的 virtualenv 中。

这对于 py27 来说很好,但会导致 py34 的覆盖率报告中的结果不正确。我有一个临时的解决方法:我需要一个稍早版本的覆盖(相对于安装在我的基本操作系统上的那个),这样 tox 将被迫在 virtualenv 中安装一个单独的覆盖副本。例如

[testenv]
deps =
    coverage==4.0.2
    pytest==2.9.0
    py==1.4.30

我不喜欢这种解决方法,但它是我目前找到的最好的。关于强制 tox 在其 virtualenv 中安装当前版本的覆盖率的任何建议,即使我已经在我的基本操作系统上安装了它?

4

2 回答 2

9

我今天遇到了这个问题,但找不到简单的答案。因此,为了将来参考,这是我提出的解决方案。

  1. 创建一个envlist包含将要测试的每个 Python 版本和一个用于cov.
  2. 对于所有版本的 Python,设置COVERAGE_FILE环境变量以将.coverage文件存储在{envdir}.
  3. 对于cov环境,我使用两个命令。
    1. coverage combine结合报告,以及
    2. coverage html生成报告,并在必要时使测试失败。
  4. 创建一个.coveragerc文件,其中包含一个[paths]列出source=位置的部分。
    1. 第一行是找到实际源代码的地方。
    2. 随后的几行是将被 `coverage combine' 消除的子路径。

毒物.ini:

[tox]
envlist=py27,py36,py35,py34,py33,cov

[testenv]
deps=
    pytest
    pytest-cov
    pytest-xdist
setenv=
    py{27,36,35,34,33}: COVERAGE_FILE={envdir}/.coverage
commands=
    py{27,36,35,34,33}: python -m pytest --cov=my_project  --cov-report=term-missing --no-cov-on-fail
    cov: /usr/bin/env bash -c '{envpython} -m coverage combine {toxworkdir}/py*/.coverage'
    cov: coverage html --fail-under=85

.coveragerc:

[paths]
source=
    src/
    .tox/py*/lib/python*/site-packages/

配置中最奇特的部分是调用coverage combine. 以下是命令的细分:

  • tox不处理 Shell 扩展{toxworkdir}/py*/.coverage,因此我们需要调用 shell ( bash -c) 来获得必要的扩展。
    • 如果有人愿意,您可以单独输入所有路径,而不是跳过所有这些循环,但这会增加.coverage每个环境的维护和文件依赖性pyNN
  • /usr/bin/env bash -c '...'以确保我们获得正确版本的bash. 使用完整路径来env避免设置whitelist_externals.
  • '{envpython} -m coverage ...'确保我们为环境调用正确的python和。coveragecov
  • 注意:这个解决方案的不幸问题是covenv 依赖于它的调用,py{27,36,35,34,33}它有一些不太理想的副作用。
    • 我的建议是只调用covthrough tox
    • 永远不要调用tox -ecov,因为
      • 由于缺少.coverage文件,它可能会失败,或者
      • 它可能会给出奇怪的结果(结合不同的测试)。
    • 如果您必须将其作为子集 ( tox -epy27,py36,cov) 调用,则首先清除.tox目录 ( rm -rf .tox) 以避免丢失.coverage文件问题。
于 2017-04-10T18:12:44.753 回答
1

我不明白为什么 tox 不会在每个 virtualenv 中正确安装覆盖。你应该得到两份不同的覆盖率报告,一份用于 py27,一份用于 py35。更好的选择可能是生成一份合并报告。用于coverage run -p记录每次运行的单独数据,然后coverage combine在报告之前将它们组合起来。

于 2016-04-16T01:05:15.313 回答