7

使用鼻子测试和覆盖率模块,我想要代码的覆盖率报告以反映正在测试的版本。考虑这段代码:

import sys
if sys.version_info < (3,3):
    print('older version of python')

当我在 python 3.5 版中测试时,print()显示为未经测试。我想让覆盖忽略那条线,但只有当我使用 python 3.3+ 版本进行测试时

有没有办法只在不小于时做类似声明# pragma: no cover的事情?实际上,我想做这样的事情:print()sys.version_info(3,3)

import sys
if sys.version_info < (3,3):
    print('older version of python') # pragma: [py26,py27,py32] no cover
4

3 回答 3

8

另一种选择是为不同版本的 Python 使用不同的 .coveragerc 文件,并为不同版本设置exclude_lines不同的正则表达式。

例如,我看到有些人使用不同的注释字符串# no cover 3.xvs # no cover 2.x

但请记住,您根本不必使用注释编译指示。正则表达式应用于整行。例如,如果您对条件使用简短的符号,例如:

if PY2:
    blah_py2_stuff_blah()

那么 Python 3 的 .coveragerc 文件可能具有:

[report]
exclude_lines =
    # pragma: no cover
    if PY2:

然后,这些if PY2:行将被排除,无需您进行任何额外的评论或努力。

于 2016-02-21T21:27:14.177 回答
2

正如您在评论中解释的那样,您担心的是覆盖率报告只会显示行号,并且您希望避免一次又一次地重新检查这些。

另一方面,我不太赞成用注释使代码混乱以使一个或另一个工具满意:对我来说,这一切都会降低可读性。因此,我想提出另一种方法,它可以避免代码混乱,但仍然可以减轻您一直进行重新检查的负担。

这个想法是,创建覆盖情况的基线,您可以根据该基线比较未来的覆盖分析结果。例如,coverage.py 的覆盖率报告如下所示(引自http://coverage.readthedocs.org/en/coverage-4.0.3/index.html):

Name                      Stmts   Miss  Cover   Missing
-------------------------------------------------------
my_program.py                20      4    80%   33-35, 39
my_other_module.py           56      6    89%   17-23
-------------------------------------------------------
TOTAL                        76     10    87%

此输出可用作“基线”的基础:粗略的想法(改进见下文)是,您将此输出存储为“已接受”覆盖情况,并将其与未来的覆盖报告进行比较。不幸的是,每当行号发生变化时,您都会在区分报告时看到差异。为了避免这种情况,可以改进这个基本思想:

借助简单的脚本,您可以转换报告,以显示相应行的内容,而不是行号。例如,基于上述代码示例的假设报告可能如下所示:

Name                      Stmts   Miss  Cover   Missing
-------------------------------------------------------
my_program.py                20      1     5%   3

从此报告中,您可以为 python 版本 >= 3.3 创建以下“覆盖基线”,例如在文件中coverage-baseline-33andabove.txt

my_program.py:
-    print('older version of python')

即使您在文件顶部添加例如进一步的导入行,该基线也会看起来相同。将为您确定覆盖范围的其他 python 版本创建更多基线文件。

进一步可能的改进可能是分离行组,例如:

my_program.py:
*
-    print('older version of python')
*
-    cleanup()
-    assert False
my_program2.py:
*
-    print('older version of python')

您只会在未涵盖的代码更改(添加、删除、修改、移动)以及文件名更改时看到差异。然后,差异的出现将要求您存储新的“覆盖基线”,或者添加更多测试,直到再次达到原始基线内容。

于 2016-02-20T22:43:19.383 回答
0

coverage我为图书馆写了一个插件。它可用于根据不同的用户定义标准有条件地从覆盖范围中排除块和线。

它支持:

  • sys_version_info是相同的sys.version_info
  • os_environ是相同的os.environ
  • is_installed是我们的自定义函数,它尝试导入传递的字符串,返回 bool 值
  • package_version是我们的自定义函数,它尝试从 pkg_resources 获取包版本并返回其解析版本

这是一个例子:

try:  # pragma: has-django
    import django
except ImportError:  # pragma: has-no-django
    django = None

def run_if_django_is_installed():
    if django is not None:  # pragma: has-django
        ...

此示例将需要添加这些行:

[coverage:run]
# Here we specify plugins for coverage to be used:
plugins =
  coverage_conditional_plugin

[coverage:coverage_conditional_plugin]
rules =
  "is_installed('django')": has-django
  "not is_installed('django')": has-no-django

现在,标有的行在未安装# pragma: has-django时将被忽略django,但在安装时被覆盖。反过来也适用于has-no-django编译指示。

于 2020-09-11T19:11:16.957 回答