如果 py.test 从另一个目录执行它,coverage.py 不会覆盖脚本

Posted

技术标签:

【中文标题】如果 py.test 从另一个目录执行它,coverage.py 不会覆盖脚本【英文标题】:coverage.py does not cover script if py.test executes it from another directory 【发布时间】:2013-09-05 13:57:52 【问题描述】:

我有一个 python 脚本,它接受命令行参数,处理一些文件。 我正在使用py.test 编写成功的测试,让这个脚本通过它的步伐,用subprocess.call 执行它。

现在我想用coverage.py 分析代码覆盖率。 覆盖率,当通过 pytest-cov 插件(内置子进程处理)使用时,在从使用 py.test 创建的临时测试目录调用时,看不到/覆盖我的脚本 s tmpdir 夹具。 Coverage确实看到我的脚本在它所在的目录中被调用(并且文件名参数指向远程路径)。

在这两种情况下,我的测试都通过了!覆盖 3.6、pytest-2.3.5、pytest-cov 1.6,均来自 PyPi。

问题:即使脚本在另一个目录中执行,我如何才能获得覆盖以识别我的脚本?这是覆盖范围的错误,还是无法做到的事情?如果后者毕竟tmpdir 是 py.test 的股票机制会感到惊讶......

简单示例:

我得到了一个脚本my_script.py,它只是回显了通过命令行参数提供的文件arg_file.txt 的内容。在两个不同的测试中,这一次在 tmpdir 中调用,一次在脚本位置调用。两个测试都通过了,但是在 tmpdir 测试中,我没有得到覆盖信息!

试运行:

~/pytest_experiment$ py.test -s
=================================== test session starts ====================================
platform linux2 -- Python 2.7.4 -- pytest-2.3.5
plugins: cov
collected 2 items 

tests/test_in_scriptdir.py 
set_up: In directory /tmp/pytest-52/test_10
Running in directory /home/cbuchner/pytest_experiment
Command: ./my_script.py /tmp/pytest-52/test_10/arg_file.txt
--Contents of arg_file.txt--

.
tests/test_in_tmpdir.py 
set_up: In directory /tmp/pytest-52/test_11
Running in directory /tmp/pytest-52/test_11
Command: /home/cbuchner/pytest_experiment/my_script.py arg_file.txt
--Contents of arg_file.txt--

.

================================= 2 passed in 0.06 seconds =================================

覆盖范围:

~/pytest_experiment$ py.test --cov=my_script.py tests/test_in_scriptdir.py=================================== test session starts ====================================
platform linux2 -- Python 2.7.4 -- pytest-2.3.5
plugins: cov
collected 1 items 

tests/test_in_scriptdir.py .
--------------------- coverage: platform linux2, python 2.7.4-final-0 ----------------------
Name        Stmts   Miss  Cover
-------------------------------
my_script       3      0   100%

================================= 1 passed in 0.09 seconds =================================
~/pytest_experiment$ py.test --cov=my_script.py tests/test_in_tmpdir.py=================================== test session starts ====================================
platform linux2 -- Python 2.7.4 -- pytest-2.3.5
plugins: cov
collected 1 items 

tests/test_in_tmpdir.py .Coverage.py warning: No data was collected.

--------------------- coverage: platform linux2, python 2.7.4-final-0 ----------------------
Name    Stmts   Miss  Cover
---------------------------

================================= 1 passed in 0.09 seconds =================================

文件在这里:https://gist.github.com/bilderbuchi/6412754

编辑:有趣的是,当使用 -s 运行覆盖测试时,也会有更多奇怪的输出 - 覆盖警告 No data was collected,显然它被收集了,在 tmpdir测试警告Module my_script.py was never imported.??

~/pytest_experiment$ py.test -s --cov=my_script.py tests/test_in_scriptdir.py
=================================== test session starts ====================================
platform linux2 -- Python 2.7.4 -- pytest-2.3.5
plugins: cov
collected 1 items 

tests/test_in_scriptdir.py 
set_up: In directory /tmp/pytest-63/test_10
Running in directory /home/cbuchner/pytest_experiment
Command: ./my_script.py /tmp/pytest-63/test_10/arg_file.txt
--Contents of arg_file.txt--

Coverage.py warning: No data was collected.
.
--------------------- coverage: platform linux2, python 2.7.4-final-0 ----------------------
Name        Stmts   Miss  Cover
-------------------------------
my_script       3      0   100%

================================= 1 passed in 0.09 seconds =================================
~/pytest_experiment$ py.test -s --cov=my_script.py tests/test_in_tmpdir.py=================================== test session starts ====================================
platform linux2 -- Python 2.7.4 -- pytest-2.3.5
plugins: cov
collected 1 items 

tests/test_in_tmpdir.py 
set_up: In directory /tmp/pytest-64/test_10
Running in directory /tmp/pytest-64/test_10
Command: /home/cbuchner/pytest_experiment/my_script.py arg_file.txt
--Contents of arg_file.txt--

Coverage.py warning: Module my_script.py was never imported.
Coverage.py warning: No data was collected.
Coverage.py warning: Module my_script.py was never imported.
Coverage.py warning: No data was collected.
.Coverage.py warning: No data was collected.

--------------------- coverage: platform linux2, python 2.7.4-final-0 ----------------------
Name    Stmts   Miss  Cover
---------------------------

================================= 1 passed in 0.09 seconds =================================

【问题讨论】:

抱歉没有回答。但在我看来,您必须查看 py.test 内部才能看到 tmpdir 固定装置的特殊性。如果它在某种上下文管理器中,覆盖范围会在它退出(或类似的东西)后被调用。 谢谢。我已经与覆盖开发人员联系,一旦我们了解了这一点,我会发布一个摘要。 @Christoph 如果你仍然有兴趣让它与 pytest-cov 一起工作,请随时在github.com/schlamar/pytest-cov 上打开一个问题。我是 pytest-cov 的新维护者,也许可以提供帮助。 @schlamar 谢谢,但我已经在我身边解决了这个问题(请参阅下面的答案)。虽然我通常会(正确地)打开一个关于这个的错误报告,但我目前没有时间关心这个并再次测试它并发布一个重现过程,抱歉。 @schlamar 我刚刚检查过,我仍然可以使用上面的过程进行复制,但我什至不确定在使用覆盖覆盖 @987654340 调用的内容时这是否实际上是一个轻微的用户错误@ 【参考方案1】:

根据此博客: https://thomas-cokelaer.info/blog/2017/01/pytest-cov-collects-no-data-on-travis/

您应该将所有__init__.py 文件添加到tests 文件夹中!这个解决方案对我有用。

【讨论】:

【参考方案2】:

tox 的另一个选项是在tox.ini 中设置PYTHONPATH

[testenv] setenv = PYTHONPATH = toxinidir commands = pytest --cov=<your package> - codecov

【讨论】:

【参考方案3】:

我在从 tox 调用“py.test --cov ...”时遇到了同样的问题。我在这个页面上找到了一个提示:http://blog.ionelmc.ro/2014/05/25/python-packaging/,尽管它没有明确提到这一点。对 tox 使用“--develop”将确保从与覆盖分析相同的目录中调用覆盖数据收集。 tox.ini 中的这一部分让我有一个覆盖测试环境:

[tox]
envlist = ...,py34,cov

[testenv:cov]
# necessary to make cov find the .coverage file
# see http://blog.ionelmc.ro/2014/05/25/python-packaging/
usedevelop = true
commands = py.test --cov=<MODULE_NAME>
deps = pytest pytest-cov

【讨论】:

这是迄今为止最好的答案,它帮助我节省了一个小时。为你竖起大拇指。 这使得测试不太彻底,因为您没有针对 setup.py 生成的 dist 进行测试。 这是因为您的库名称与模块名称不匹配。【参考方案4】:

当测量的脚本从另一个目录运行时,这原来是一个相对路径混淆覆盖率的问题。覆盖结果文件最终位于该目录中,而不是项目的根目录中。

为了解决这个问题,我停止使用pytest-cov,转而使用纯coverage。我在相关的地方使用完整路径而不是相对路径。

所以,例如 通过export COVERAGE_PROCESS_START=/full/path/to/.coveragerc 定义启用子进程覆盖所需的环境变量。 在.coveragerc中,覆盖结果文件通过

指定
     [run]
     data_file = /full/path/to/.coverage

任何--source--include 选项也应该使用完整路径。 这样就可以得到正确的覆盖率测量。

【讨论】:

恐怕这不是一个普遍接受的答案,因为如果您有持续集成,这将无法工作,我们需要一个适当的解决方案。 CI 会怎样阻止您使用完整路径? @Christoph:您通常无法控制(也不应该控制)构建/提取源的确切位置(无论构建步骤是否相关)。因此需要依赖相对路径。 点了。虽然,您可以通过使用包含您动态生成的完整路径的环境变量,通过os.path.abspath() 至少部分解决这个问题。无论如何,我不知道这是否仍然是一个问题,我使用的旧代码在.covragerc 中没有完整路径。

以上是关于如果 py.test 从另一个目录执行它,coverage.py 不会覆盖脚本的主要内容,如果未能解决你的问题,请参考以下文章

长时间运行的 py.test 在第一次失败时停止

如何告诉 py.test 跳过某些目录?

测试代码是不是从 py.test 会话中执行

pytest的执行方式及搜索原则

从另一个目录运行的 JAR 文件?

从另一个 exe 运行一个 Exe