【问题标题】:Using py.test with coverage doesn't include imports使用 py.test 覆盖不包括导入
【发布时间】:2013-04-30 13:27:39
【问题描述】:

对于Jedi,我们想要生成我们的test coverage。 stackoverflow 中有一个related question,但没有帮助。

我们使用 py.test 作为测试运行器。但是,我们无法将导入和其他“导入”的内容添加到报告中。例如__init__.py 总是被报告为未被发现:

Name                           Stmts   Miss  Cover
--------------------------------------------------
jedi/__init__                      5      5     0%
[..]

很明显,此文件正在导入,因此应报告为已测试。

我们开始这样的测试 [*]:

py.test --cov jedi

如您所见,我们使用的是pytest-coverage

那么如何正确计算__init__.py 等文件的覆盖率?

[*] 我们还尝试在没有--doctest-modules(从pytest.ini 中删除)的情况下开始测试,并在之前通过py.test -p pytest_cov --cov jedi 激活覆盖模块。它们都不起作用。

我提供了赏金。请尝试在 Jedi 中修复它。它是公开的。

【问题讨论】:

  • 你有没有偶然导入“jedi”的conftest.py文件?我猜在 pytest 初始化之后(包括在 CWD 读取 conftest.py 文件和 test*/ 如果它存在)你的绝地已经被导入了。
  • 是的。我们有一个conftest.py。它间接导入jedi。但是,将这些间接导入移动到函数中也没有帮助(或者这也是一个问题???)。文件在这里:github.com/davidhalter/jedi/blob/master/test/conftest.py
  • 什么是 __init__.py?例如,导入函数与运行函数不同。

标签: python pytest coverage.py


【解决方案1】:

如果您使用的是烧瓶,那么这将帮助您解决问题-

pytest --cov=src --cov-report=html

【讨论】:

    【解决方案2】:

    我通过this patch 将测试覆盖率固定为 94%,这简化了导入依赖项,并通过以下命令:

    py.test --cov jedi test                    # or
    py.test --cov jedi test --cov-report=html  # + a listing with red uncovered lines
    

    未覆盖的行仅在条件命令或一些较少使用的函数中,但所有标题都被完全覆盖。

    问题是测试配置test/conftest.py 确实被项目中几乎所有文件的依赖项提前导入。 conftest 文件还定义了应在运行测试之前设置的其他命令行选项和设置。因此,我认为如果 pytest_cov 插件忽略与此文件一起导入的所有内容,则它可以正常工作,尽管这很痛苦。我还从报告中排除了__init__.pysettings.py,因为它们很简单并且覆盖范围很广,但它们也会在 conftest 的依赖中过早导入。

    【讨论】:

    【解决方案3】:

    在我的例子中,所有测试都运行了,但覆盖率为 0%。

    解决方法是:

    $ export PYTHONPATH="."
    

    结果正确后。

    在过去的几个问题中,py.test 命令在导入某些内容时遇到问题,而设置 PYTHONPATH 环境变量是解决方案。这次也对我有用。

    awslogs 的真实例子

    首先取消设置PYTHONPATH

    $ py.test --cov=awslogs  tests/
    ========================================= test session starts =========================================
    platform linux2 -- Python 2.7.9, pytest-2.8.5, py-1.4.31, pluggy-0.3.1
    rootdir: /home/javl/sandbox/awslogs/github/awslogs, inifile:
    plugins: cov-2.2.0
    collected 11 items
    
    tests/test_it.py ...........Coverage.py warning: No data was collected.
    
    --------------------------- coverage: platform linux2, python 2.7.9-final-0 ---------------------------
    Name                    Stmts   Miss  Cover
    -------------------------------------------
    awslogs/__init__.py         2      2     0%
    awslogs/bin.py             85     85     0%
    awslogs/core.py           143    143     0%
    awslogs/exceptions.py      12     12     0%
    -------------------------------------------
    TOTAL                     242    242     0%
    
    ====================================== 11 passed in 0.38 seconds ======================================
    

    最终覆盖率为 0%。

    然后我设置PYTHONPATH:

    $ export PYTHONPATH="."
    

    然后重新运行测试:

    $ py.test --cov=awslogs  tests/
    ========================================= test session starts =========================================
    platform linux2 -- Python 2.7.9, pytest-2.8.5, py-1.4.31, pluggy-0.3.1
    rootdir: /home/javl/sandbox/awslogs/github/awslogs, inifile:
    plugins: cov-2.2.0
    collected 11 items
    
    tests/test_it.py ...........
    --------------------------- coverage: platform linux2, python 2.7.9-final-0 ---------------------------
    Name                    Stmts   Miss  Cover
    -------------------------------------------
    awslogs/__init__.py         2      0   100%
    awslogs/bin.py             85      9    89%
    awslogs/core.py           143     12    92%
    awslogs/exceptions.py      12      2    83%
    -------------------------------------------
    TOTAL                     242     23    90%
    
    ====================================== 11 passed in 0.44 seconds ======================================
    

    现在是覆盖率 90%。

    警告:操纵PYTHONPATH 可能会产生奇怪的副作用。目前我遇到了问题,基于pbr的包在构建可分发时创建了egg目录,如果PYTHONPATH设置为“.”,它会自动认为与egg相关的包已安装。出于这个原因,我停止使用pytest-cov 并按照建议改用coverage 工具。

    【讨论】:

    • 你知道pip install -e .吗?这允许您安装软件的开发版本,这可能是您在此处遇到的问题(未包含在 sys.path 中)。
    • @DaveHalter 谢谢,好主意。当然我知道pip install -e . 但是当通过pip install . 安装时(没有-e 选项),普通的coverage 命令可以正确处理覆盖,但py.test --cov==awslogs -m py.test -sv tests 不能。
    • @JanVlcinsky(或阅读此主题的人)。 Coverage 不处理将当前工作目录添加到 sys.path 的默认 python 行为,因此coverage run --source mypackage -m pytest tests 将导入本地mypackage 目录而不是pip install . 安装的目录(除非您使用的是src文件夹,请参阅 blog.ionelmc.ro/2014/05/25/python-packaging/#the-structure 了解为什么这是一个好主意)。 pytest-cov 通过从 sys.path 中删除 cwd 来明确避免这种情况,因此不会发生这种情况。
    • 我的文件夹结构是src/<stuff> src/tests。将PYTHONPATH 设置为$(pwd)/src 为我解决了测试覆盖率问题。
    【解决方案4】:

    @hynekcer 给了我正确的想法。但基本上最简单的解决方案在其他地方:

    摆脱pytest-cov

    使用

    coverage run --source jedi -m py.test
    coverage report
    

    相反!!!这样,您只需在当前的 py.test 配置上运行覆盖,它工作得非常好!从哲学上讲,这也是正确的方法:让每个程序做好一件事 - py.test 运行测试,coverage 检查代码覆盖率。

    现在这听起来像是在咆哮,但确实如此。 pytest-cov 已经有一段时间没有正常工作了。有些测试失败了,只是因为我们使用了它。


    截至 2014,pytest-cov 似乎已易手。 py.test --cov jedi test 似乎又是一个有用的命令(查看 cmets)。但是,您不需要使用它。但结合xdist 可以加快您的报道报告速度。

    【讨论】:

    【解决方案5】:

    我在 py.test、覆盖率和 django 插件方面遇到了这个问题。 显然,模型文件是在开始覆盖之前导入的。 甚至没有用于早期加载覆盖插件的“-p覆盖”。

    我通过从 sys.modules 中删除模型模块并将其重新导入到测试模型的测试文件中来修复它(丑陋?):

    import sys
    del sys.modules['project.my_app.models']
    from project.my_app import models
    
    def test_my_model():
      ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-08
      • 2018-09-09
      • 2015-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多