如何让 pytest 在已安装的模块中发现和 运行 doctests?

How to let pytest discover and run doctests in installed modules?

我正在添加单元测试和一种 "legacy" Python 包。一些模块包含嵌入在文档字符串中的自己的文档测试。我的目标是 运行 这些文档测试和新的专用单元测试。

跟随 this Q&A ("How to make py.test run doctests as well as normal tests directory?") I'm using the --doctest-modules 选项到 pytest。当 运行ning 从源存储库中时,pytest 确实从 src 目录下的 Python 模块中发现了嵌入式文档测试。

但是,我的目标是测试源代码分发是否完全构建和安装,然后针对 installed 包测试所有内容。为此,我使用 tox 来自动构建 sdist(源代码分发)tarball,将其安装在虚拟环境中,然后 运行 对安装的版本进行测试.为确保测试导入的是已安装的版本,而不是源存储库中的版本,我遵循建议 in this article,存储库现在如下所示:

repo/
  src/
    my_package/
      __init__.py
      module_a.py
      module_b.py
      ...
  tests/
    test_this.py
    test_that.py
  requirements.txt
  setup.py
  tox.ini

(tests下的测试脚本像import my_package一样导入包,这会命中安装的版本,因为存储库布局确保src/my_package目录不在模块搜索路径。)

并且在 tox 配置文件中,相关部分看起来像

[tox]
envlist = py27,py36,coverage-report

[testenv]
deps =
  -rrequirements.txt
commands =
  coverage run -p -m pytest --

[pytest]                                                                        
addopts = --doctest-modules 

到目前为止,测试 运行 很好,并且从 src/my_package 下的模块中提取了 doctests,而不是从安装在 tox 虚拟环境中的包中提取。

我与此设置相关的问题如下:

pytest 当前目录 收集测试(除非您指示它以其他方式传递显式目录)。在tox.ini中使用tox substitutions添加安装目录。即,要么传递目录:

[testenv]
deps =
  -rrequirements.txt
commands =
  coverage run -p -m pytest {envsitepackagesdir}/my_package

或更改目录:

[testenv]
changedir = {envsitepackagesdir}/my_package
deps =
  -rrequirements.txt
commands =
  coverage run -p -m pytest --

我找到了我自己问题的答案。

引用pytest issue #2042:

currently doctest-modules is fundamentally incompatible with testing against a installed package due to module search in checkout vs module usage from site-packages

所以到目前为止,解决方案不存在。

这就是我解决导入不匹配的方法:

$ pytest tests/ --doctest-modules --pyargs myrootpkg <other args>

这里的问题是,一旦开始明确指定源路径(在本例中为 --pyargs),您还必须指定所有其他源路径(本例中为 tests/pytest 将停止扫描根目录。不过,这在使用 src 布局时应该不是问题,因为测试通常不会分散在存储库周围。