我有一个在相当大的django项目上使用Pytest的工作测试套件 . 问题是我无法使用覆盖率获得正确的结果,我想知道是否可能是因为项目目录结构 .

请考虑以下目录树示例:

.
├── apps
│   ├── api
│   │   ├── __init__.py
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   └── views
│   │   │       ├── __init__.py
│   │   │       └── test_tickets.py
│   │   └── views
│   │       ├── __init__.py
│   │       ├── tickets.py
│   ├── support
│   │   ├── __init__.py
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   └── utils
│   │   │       ├── __init__.py
│   │   │       ├── test_management_commands.py
│   │   ├── utils
│   │   │   ├── __init__.py
│   │   │   ├── management_commands.py

以及覆盖率报告的示例输出:

coverage run --source apps/ -m py.test apps/
coverage report

Name                                        Stmts   Miss  Cover
---------------------------------------------------------------
apps/api/views/tickets.py                      42     18    57%
apps/support/utils/management_commands.py     135    100    26%

查看html报告,我可以看到测试执行的许多语句都不被视为涵盖,即使它们应该被覆盖 . 我认为这个覆盖率数据不完整,似乎只考虑了所涵盖的进口,定义和文档字符串 .

无法确定覆盖率出现错误的原因,我尝试运行单个测试模块,结果为正:

coverage run --source apps/support/utils/management_commands.py -m py.test apps/support/tests/utils/test_management_commands.py
coverage report

Name                                        Stmts   Miss  Cover
---------------------------------------------------------------
apps/support/utils/management_commands.py     135     68    50%

这是更准确的,HTML报告显示我测试的语句在这次显示为覆盖 . 无法弄清楚为什么运行单个测试模块会产生准确的结果,我通过在单个父文件夹下移动测试来修改目录结构 .

.
├── apps
│   ├── api
│   │   ├── __init__.py
│   │   └── views
│   │       ├── __init__.py
│   │       ├── tickets.py
│   ├── support
│   │   ├── __init__.py
│   │   ├── utils
│   │   │   ├── __init__.py
│   │   │   ├── management_commands.py
├── tests
│   │   ├── __init__.py
│   ├── api
│   │   ├── __init__.py
│   │   └── views
│   │       ├── __init__.py
│   │       └── test_tickets.py
│   ├── support
│   │   ├── __init__.py
│   │   ├── utils
│   │   │   ├── __init__.py
│   │   │   ├── test_management_commands.py

使用此目录结构重新运行coverage会产生更准确的结果:

coverage run --source apps/ -m py.test tests/
coverage report

Name                                        Stmts   Miss  Cover
---------------------------------------------------------------
apps/api/views/tickets.py                      42      0   100%
apps/support/utils/management_commands.py     135     68    50%

任何人都可以解释为什么运行py.test覆盖范围在原始目录结构下完全覆盖?目录结构实际上是问题还是我错过了其他的东西?

附加信息:

# pytest.ini
[pytest]
addopts = --nomigrations
markers =
    slowtest: mark a test as being slow
    integration: mark a test as being an integration test

INSTALLED_APPS += ('django_coverage', )
TEST_DISCOVER_PATTERN = 'test_*'
COVERAGE_MODULE_EXCLUDES = [
    'settings',
    'urls$',
    'locale$',
    'tests$',
    'django',
    'migrations',
    'compressor',
    'templates?$',
    'fixtures$',
    'static$',
]
ROOT_PATH = os.path.abspath('%s/' % os.path.dirname(__file__))

.coveragerc

[run]
source = apps
omit =
     apps/*/templates?/*
     apps/*/migrations/*
     apps/*/factories/*
     apps/*/tests/*
[html]
directory = coverage

模块版本(有些可能不相关):

pytest==2.9.0
pytest-cov==2.2.1
pytest-django==2.9.1
django-coverage==1.2.4
coverage==4.0.3