$ pytest 和 $ python -m pytest 测试之间的区别

Mat*_*asM 10 python pytest

我想了解运行之间的区别:

\n
$ pytest\n
Run Code Online (Sandbox Code Playgroud)\n

\n
$ python -m pytest tests\n
Run Code Online (Sandbox Code Playgroud)\n

我正在 Mac 上的虚拟环境中工作。\n第一个解决方案给了我一个错误:

\n
ModuleNotFoundError: No module named 'app'  \n
Run Code Online (Sandbox Code Playgroud)\n

第二种解决方案效果很好。

\n

为什么第二个解决方案有效而第一个解决方案无效?\n我怎样才能让它只使用$ pytest

\n

我的文件夹结构:

\n
\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 app.py   \n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 requirements.txt  \n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 templates  \n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 tests  \n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 conftest.py  \n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 functional  \n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py  \n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 test_s.py   \n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 unit   \n\xe2\x94\x82       \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py   \n\xe2\x94\x82       \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 test_app.py   \n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 venv   \n
Run Code Online (Sandbox Code Playgroud)\n

在 test_app.py 中,此行失败:

\n
from app import app\n
Run Code Online (Sandbox Code Playgroud)\n

J.G*_*.G. 9

python -m pytest将当前目录添加到 sys.path,即允许您从那里导入模块。

这暗示有一些东西(我们称之为它)对于您的目录结构来说不是最佳的。

为什么这可能不是一件好事,您可以阅读这篇精彩的博客文章

https://blog.ganssle.io/articles/2019/08/test-as-installed.html

我还写了一篇关于这个主题的简短博客文章:

https://jugmac00.github.io/til/what-is-the-difference- Between-invoking-pytest-and-python-m-pytest/


小智 2

区别不仅在于 Python 搜索模块的算法,还在于 Pytest 发现测试的方式。

1.Python模块搜索

根据Python实现如下:

  1. 在内置模块中搜索
  2. 在 sys.path 列表中搜索:
    • 第一个“当前目录”被添加到 sys.path
    • 第二个 PYTHONPATH 内容被添加到 sys.path
    • 最后将所有Python安装目录添加到sys.path中

这可能相当复杂。我在这里看到“在扩展模式下”很好地解释了这一点: Where is Python's sys.pathinitialized from?

2. Pytest发现机制

所以

from app import app
Run Code Online (Sandbox Code Playgroud)

当您像上面一样导入“app”时,在两种情况下都会以不同的方式搜索它。换句话说,对于这两种情况,sys.path 中的“当前目录”设置不同。您可以通过打印 sys.path 列表来检查这一点。

这不是问题,而是 python/pytest 的工作方式。

3. 解决方法示例

您可以通过例如下面的内容来解决此问题(我将其放入单独的 pathmagic.py 文件并稍后在 test_xyz 中导入 pathmagic )

import pathmagic  # noqa Pep8 uncheck
Run Code Online (Sandbox Code Playgroud)

路径魔法.py

import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
sys.path.append(os.path.dirname((os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))
Run Code Online (Sandbox Code Playgroud)