对于一个简单的Python模块来说,非常常见的目录结构似乎是将单元测试分离到它们自己的测试目录中:
new_project/
antigravity/
antigravity.py
test/
test_antigravity.py
setup.py
etc.
我的问题很简单,实际运行测试的通常方式是什么?我怀疑这对每个人来说都是显而易见的,除了我,但你不能只是从测试目录运行python test_antigravity.py,因为它的导入antigravity将失败,因为模块不在路径上。
我知道我可以修改PYTHONPATH和其他与搜索路径相关的技巧,但我不能相信这是最简单的方法——如果您是开发人员,这很好,但如果用户只是想检查测试是否通过,那么期望他们使用这种方法是不现实的。
另一种替代方法是将测试文件复制到另一个目录中,但这似乎有点愚蠢,并且没有注意到将它们放在一个单独的目录中。
那么,如果您刚刚下载源代码到我的新项目,您将如何运行单元测试?我更喜欢这样的答案:“要运行单元测试,请执行x。”
使用cwd作为根项目的目录(在你的例子中是new_project),你可以在任何目录中不使用__init__.py运行以下命令:
python -m unittest discover -s test
但是你需要在test_antigravity.py中导入如下:
from antigravity import antigravity.your_object
而不是:
import antigravity.your_object
如果你不喜欢反重力条款,你可能会喜欢艾伦L的答案。
Python unittest模块的解决方案/示例
鉴于以下项目结构:
ProjectName
├── project_name
| ├── models
| | └── thing_1.py
| └── __main__.py
└── test
├── models
| └── test_thing_1.py
└── __main__.py
你可以使用python project_name从根目录运行你的项目,它调用ProjectName/project_name/__main__.py。
要使用python test运行测试,有效地运行ProjectName/test/__main__.py,您需要执行以下操作:
1)通过添加__init__.py文件将您的test/models目录转换为一个包。这使得子目录中的测试用例可以从父测试目录中访问。
# ProjectName/test/models/__init__.py
from .test_thing_1 import Thing1TestCase
2)在test/__main__.py中修改系统路径以包含project_name目录。
# ProjectName/test/__main__.py
import sys
import unittest
sys.path.append('../project_name')
loader = unittest.TestLoader()
testSuite = loader.discover('test')
testRunner = unittest.TextTestRunner(verbosity=2)
testRunner.run(testSuite)
现在您可以在测试中成功地从project_name导入内容。
# ProjectName/test/models/test_thing_1.py
import unittest
from project_name.models import Thing1 # this doesn't work without 'sys.path.append' per step 2 above
class Thing1TestCase(unittest.TestCase):
def test_thing_1_init(self):
thing_id = 'ABC'
thing1 = Thing1(thing_id)
self.assertEqual(thing_id, thing.id)
我也遇到了同样的问题,使用了一个单独的单元测试文件夹。根据上述建议,我将绝对源路径添加到sys.path中。
以下解决方案的好处是,你可以运行test/test_yourmodule.py文件,而不需要一开始就切换到test目录:
import sys, os
testdir = os.path.dirname(__file__)
srcdir = '../antigravity'
sys.path.insert(0, os.path.abspath(os.path.join(testdir, srcdir)))
import antigravity
import unittest
如果你使用VS Code,并且你的测试与你的项目位于同一级别,那么运行和调试你的代码就不能开箱即用。你能做的就是改变启动方式。json文件:
{
"version": "0.2.0",
"configurations": [
{
"name": "Python",
"type": "python",
"request": "launch",
"stopOnEntry": false,
"pythonPath": "${config:python.pythonPath}",
"program": "${file}",
"cwd": "${workspaceRoot}",
"env": {},
"envFile": "${workspaceRoot}/.env",
"debugOptions": [
"WaitOnAbnormalExit",
"WaitOnNormalExit",
"RedirectOutput"
]
}
]
}
这里的关键行是envFile
"envFile": "${workspaceRoot}/.env",
在项目的根目录中添加.env文件
在.env文件中添加项目根目录的路径。这将临时添加
PYTHONPATH = C: \ \ PYTHON项目\ \ ROOT_DIRECTORY
路径到你的项目,你将能够使用调试单元测试从VS Code