python unittest与(子)进程的覆盖率报告

问题描述 投票:5回答:3

我正在使用nose进行我的“unittest”测试,并让nose-cov包含报道报告。这些都可以正常工作,但我的部分测试需要运行一些代码作为multiprocessing.Processnose-cov文档说它可以做multiprocessing,但我不知道如何让它工作。

我只是通过运行nosetests并使用以下.coveragerc来运行测试:

[run]
branch = True
parallel = True

[report]
# Regexes for lines to exclude from consideration
exclude_lines =
    # Have to re-enable the standard pragma
    pragma: no cover

    # Don't complain about missing debug-only code:
    def __repr__
    #if self\.debug

    # Don't complain if tests don't hit defensive assertion code:
    raise AssertionError
    raise NotImplementedError

    # Don't complain if non-runnable code isn't run:
    if 0:
    if __name__ == .__main__.:
    def __main__\(\):

omit =
    mainserver/tests/*

编辑:

我在我的“.coveragerc”文件中修复了parallel开关。我也试过在我的site-packages目录中添加这样的sitecustomize.py

import os
import coverage
os.environ['COVERAGE_PROCESS_START']='/sites/metrics_dev/.coveragerc'
coverage.process_startup()

我很确定它仍然无法正常工作,因为“丢失”报告仍显示我知道正在运行的行(它们输出到控制台)。我还尝试在运行测试用例之前在我的测试用例文件中添加环境变量,也在shell中添加环境变量。我还尝试在multiprocessing.Process调用的函数中显式调用相同的东西来启动新进程。

python python-3.x nose nosetests coverage.py
3个回答
1
投票

首先,您需要的配置设置是parallel,而不是parallel-mode。其次,您可能需要按照coverage.py文档的Measuring Subprocesses部分中的说明进行操作。


1
投票

另一件需要考虑的事情是,如果在运行coverage时看到多个coverage文件。也许只是后来将它们结合起来的问题。


1
投票

tl; dr - 使用coverage + nosetests + nose的--processes选项,将覆盖率的--concurrency选项设置为multiprocessing,最好是在.coveragercsetup.cfg而不是命令行(另请参阅:command line usageconfiguration files)。


长版......

我也跟着Configuring Python for sub-process coverage上的文件跟着写了一段时间。最后,在更仔细地重新检查coverage run --help的输出后,我偶然发现了--concurrency=multiprocessing选项,这是我以前从未使用过的,这似乎是缺失的环节。 (事后看来,这是有道理的:鼻子的--processing选项使用引擎盖下的multiprocessing库。)

这是一个按预期工作的最小配置:


unit.py

def is_even(x):
    if x % 2 == 0:
        return True
    else:
        return False

test.py

import time
from unittest import TestCase

import unit


class TestIsEvenTrue(TestCase):
    def test_is_even_true(self):
        time.sleep(1)  # verify multiprocessing is being used
        self.assertTrue(unit.is_even(2))


# use a separate class to encourage nose to use a separate process for this
class TestIsEvenFalse(TestCase):
    def test_is_even_false(self):
        time.sleep(1)
        self.assertFalse(unit.is_even(1))

setup.cfg

[nosetests]
processes = 2
verbosity = 2

[coverage:run]
branch = True
concurrency = multiprocessing
parallel = True
source = unit

sitecustomize.py(注:位于site-packages

import os
try:
    import coverage
    os.environ['COVERAGE_PROCESS_START'] = 'setup.cfg'
    coverage.process_startup()
except ImportError:
    pass

$ coverage run $(command -v nosetests)
test_is_even_false (test.TestIsEvenFalse) ... ok
test_is_even_true (test.TestIsEvenTrue) ... ok

----------------------------------------------------------------------
Ran 2 tests in 1.085s

OK

$ coverage combine && coverage report
Name      Stmts   Miss Branch BrPart  Cover
-------------------------------------------
unit.py       4      0      2      0   100%
© www.soinside.com 2019 - 2024. All rights reserved.