"$ pytest" 和 "$ python -m pytest tests" 的区别是什么?

8

我想了解在IT技术中运行以下两种命令的区别:

$ pytest

and

$ python -m pytest tests

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

ModuleNotFoundError: No module named 'app'  

第二种解决方案可以正常工作。
为什么第二种解决方案可行而第一种不行? 我如何仅仅使用$ pytest就能使它起作用?
我的文件夹结构:
├── app.py   
├── requirements.txt  
├── templates  
├── tests  
│   ├── conftest.py  
│   ├── functional  
│   │   ├── __init__.py  
│   │   └── test_s.py   
│   └── unit   
│       ├── __init__.py   
│       └── test_app.py   
└── venv   

在 test_app.py 中,这行代码失败了:
from app import app
2个回答

7

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/


我认为对于调试问题的人来说,值得一提的是 pytest 可能并不等同于 python -m pytest。你应该验证 which pytest 指向的文件可以被你的 Python 安装访问到。例如,在相同的虚拟环境/相同的 Python 安装中。 - Leggy

1
区别在于Python模块搜索算法,以及Pytest发现测试的方式。 1. Python模块搜索 按照以下Python实现进行搜索:
  1. 搜索内置模块
  2. 搜索sys.path列表:
    • 首先将“当前目录”添加到sys.path中
    • 其次将PYTHONPATH内容添加到sys.path中
    • 最后将所有Python安装目录添加到sys.path中
这可能会相当复杂。我在此处看到了一个很好的“扩展模式”解释: Python的sys.path是从哪里初始化的? 2. Pytest发现机制 因此,Pytest发现测试的机制如下:
from app import app

当你像上面那样导入“app”时,它在两种情况下会以不同的方式进行搜索。换句话说,“sys.path”中的“当前目录”设置在两种情况下是不同的。您可以通过打印“sys.path”列表来检查这一点。
这不是问题,而是Python / pytest工作的方式。
3. 解决方法示例
您可以通过以下方式解决此问题(例如将其放入单独的pathmagic.py文件中,然后在test_xyz中导入pathmagic)
import pathmagic  # noqa Pep8 uncheck

pathmagic.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__))))))

1
不,不应该依赖那种神奇的路径操作。在使用操作系统工具运行程序之前,您应该正确地设置环境。 - juanpa.arrivillaga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接