我的项目中有以下文件夹结构:
my-project
src/
__init__.py
script.py
test/
__init__.py
test_script.py
理想情况下,我想要一个单独的文件夹来存放所有单元测试。我的
test_script.py
看起来像这样:
from src.script import my_object
class TestClass(unittest.TestCase):
def test_script_object(self):
# unit test here
pass
if __name__ == 'main':
unittest.main()
当我尝试运行脚本(使用
python test_script.py
)时,出现以下错误:
Traceback (most recent call last):
File "test_script.py", line 4, in <module>
from src.script import my_object
ModuleNotFoundError: No module named 'src'
我遵循了另一个线程的说明,我什至尝试将src
附加到系统路径(这迫使我改变在项目其余部分中导入的方式)。当我不尝试附加到 sys 路径时,我的两个
__init__.py
文件都是空的。我使用的是python 3.8。
有人有什么建议吗?我是 python 单元测试的新手,所以也许有更好的结构或其他我不知道的约定。预先感谢您的帮助!
sys.path
以运行测试的指令都会将您引向错误的方向。您的测试工具应该能够发现您的测试和应用程序代码,而无需进行此类黑客攻击。我喜欢使用
pytest 来运行我的测试。我会这样构造你的例子:
my-project/
├── src
│ ├── conftest.py
│ └── myproject
│ ├── __init__.py
│ └── script.py
└── tests
├── __init__.py
└── test_script.py
假设 src/myproject/script.py
看起来像这样:
def double(x: int):
return x*2
并且tests/test_script.py
看起来像这样:
import myproject.script
def test_double():
res = myproject.script.double(2)
assert res == 4
我可以通过简单地运行 my-project
:来从
pytest
目录运行测试
$ pytest
========================================== test session starts ==========================================
platform linux -- Python 3.11.1, pytest-7.2.0, pluggy-1.0.0
rootdir: /home/lars/tmp/python/my-project
collected 1 item
tests/test_script.py . [100%]
=========================================== 1 passed in 0.00s ===========================================
在此设置中,文件 src/conftest.py
允许 pytest 自动发现应用程序代码的位置。或者,您可以在
pyproject.toml
文件中指定,如下所示:
[tool.pytest.ini_options]
pythonpath = [
"src"
]
如果您编写问题中所示的
unittest
风格的测试,
pytest 也可以工作;如果
tests/test_script.py
看起来像这样,上面的行为将是相同的:
import unittest
import myproject.script
class TestScript(unittest.TestCase):
def test_double(self):
res = myproject.script.double(2)
self.assertEqual(res, 4)
if __name__ == '__main__':
unittest.main()
(但我更喜欢 pytest 更简单的语法。)可能有用的阅读:
unittest
,您可以使用相同的目录布局,但您需要更新
sys.path
才能正确运行。最简单的方法是:
PYTHONPATH=$PWD/src python -m unittest
这将自动发现您的所有测试并运行它们。您可以像这样运行单个测试:
PYTHONPATH=$PWD/src python -m tests.test_script
如果您使用更简单的目录布局,则可以避免需要修改sys.path
:
my-project/
├── myproject
│ ├── __init__.py
│ └── script.py
└── tests
├── __init__.py
└── test_script.py
从 pytest
目录运行时,
python -m unittest
和
my-project
都将正确发现并运行您的测试,而无需任何路径修改。