Maj*_*jor 641 python unit-testing
即使是简单的Python模块,非常常见的目录结构似乎是将单元测试分成它们自己的test目录:
new_project/
antigravity/
antigravity.py
test/
test_antigravity.py
setup.py
etc.
Run Code Online (Sandbox Code Playgroud)
例如,看看这个Python项目如何.
我的问题是,实际运行测试的常用方法是什么?我怀疑这对除了我以外的所有人都是显而易见的,但你不能只是python test_antigravity.py从测试目录运行,因为import antigravity它将失败,因为模块不在路径上.
我知道我可以修改PYTHONPATH和其他搜索路径相关的技巧,但我不能相信这是最简单的方法 - 如果你是开发人员,那就没关系,但是如果他们只是想检查测试,那么期望用户使用是不现实的通过.
另一种选择只是将测试文件复制到另一个目录中,但它看起来有点愚蠢,并且忽略了将它们放在一个单独的目录中的重点.
那么,如果您刚刚将源代码下载到我的新项目中,您将如何运行单元测试?我更喜欢一个能让我对用户说的答案:"运行单元测试做X."
Pie*_*rre 608
在我看来,最好的解决方案是使用unittest 命令行界面,它将目录添加到sys.path你不需要的(在TestLoader类中完成).
例如,对于像这样的目录结构:
new_project
??? antigravity.py
??? test_antigravity.py
Run Code Online (Sandbox Code Playgroud)
你可以运行:
$ cd new_project
$ python -m unittest test_antigravity
Run Code Online (Sandbox Code Playgroud)
对于像您这样的目录结构:
new_project
??? antigravity
? ??? __init__.py # make it a package
? ??? antigravity.py
??? test
??? __init__.py # also make test a package
??? test_antigravity.py
Run Code Online (Sandbox Code Playgroud)
在test包内的测试模块中,您可以antigravity像往常一样导入包及其模块:
# import the package
import antigravity
# import the antigravity module
from antigravity import antigravity
# or an object inside the antigravity module
from antigravity.antigravity import my_object
Run Code Online (Sandbox Code Playgroud)
运行单个测试模块:
要运行单个测试模块,在这种情况下test_antigravity.py:
$ cd new_project
$ python -m unittest test.test_antigravity
Run Code Online (Sandbox Code Playgroud)
只需像导入它一样引用测试模块.
运行单个测试用例或测试方法:
您还可以运行单个TestCase或单个测试方法:
$ python -m unittest test.test_antigravity.GravityTestCase
$ python -m unittest test.test_antigravity.GravityTestCase.test_method
Run Code Online (Sandbox Code Playgroud)
运行所有测试:
您还可以使用将发现并运行所有测试的测试发现,它们必须是命名的模块或包test*.py(可以使用-p, --pattern标志更改):
$ cd new_project
$ python -m unittest discover
Run Code Online (Sandbox Code Playgroud)
这将运行包中的所有test*.py模块test.
Car*_*yer 47
对您的用户来说,最简单的解决方案是提供一个可执行脚本(runtests.py或其他类似的脚本)来引导必要的测试环境,包括,如果需要,可以暂时将根项目目录添加到sys.path.这不需要用户设置环境变量,这样的东西在引导脚本中工作正常:
import sys, os
sys.path.insert(0, os.path.dirname(__file__))
Run Code Online (Sandbox Code Playgroud)
然后,您对用户的指示可以像"python runtests.py"一样简单.
当然,如果您真正需要的路径是sys.path,那么您根本不需要添加它python runtests.py; Python始终将当前运行脚本的目录放在开头os.path.dirname(__file__),因此根据您的目录结构,只需找到您sys.path需要的所有内容即可.
此外,Python 2.7+中的unittest模块(后向移植为Python 2.6及更早版本的unittest2)现在内置了测试发现,因此如果您想要自动化测试发现,则不再需要鼻子:您的用户指令可以像"python -m unittest discover".
stw*_*dev 22
我通常在项目目录中创建一个"运行测试"脚本(源目录和源目录共同的脚本test),它加载我的"所有测试"套件.这通常是样板代码,因此我可以在项目之间重复使用它.
run_tests.py:
import unittest
import test.all_tests
testSuite = test.all_tests.create_test_suite()
text_runner = unittest.TextTestRunner().run(testSuite)
Run Code Online (Sandbox Code Playgroud)
test/all_tests.py(来自如何在目录中运行所有Python单元测试?)
import glob
import unittest
def create_test_suite():
test_file_strings = glob.glob('test/test_*.py')
module_strings = ['test.'+str[5:len(str)-3] for str in test_file_strings]
suites = [unittest.defaultTestLoader.loadTestsFromName(name) \
for name in module_strings]
testSuite = unittest.TestSuite(suites)
return testSuite
Run Code Online (Sandbox Code Playgroud)
通过这种设置,您确实可以只include antigravity在您的测试模块中.缺点是你需要更多的支持代码来执行特定的测试...我只是每次都运行它们.
Mar*_*ers 18
从您链接到的文章:
创建一个test_modulename.py文件并将您的unittest测试放入其中.由于测试模块与代码位于不同的目录中,因此您可能需要将模块的父目录添加到PYTHONPATH中以运行它们:
Run Code Online (Sandbox Code Playgroud)$ cd /path/to/googlemaps $ export PYTHONPATH=$PYTHONPATH:/path/to/googlemaps/googlemaps $ python test/test_googlemaps.py最后,还有一个更受欢迎的Python单元测试框架(它非常重要!),鼻子.nose有助于简化和扩展内置单元测试框架(例如,它可以自动找到您的测试代码并为您设置PYTHONPATH),但它不包含在标准Python发行版中.
也许你应该看看它暗示的鼻子?
Pat*_*lva 15
我有同样的问题很长时间了。我最近选择的是以下目录结构:
project_path
??? Makefile
??? src
? ??? script_1.py
? ??? script_2.py
? ??? script_3.py
??? tests
??? __init__.py
??? test_script_1.py
??? test_script_2.py
??? test_script_3.py
Run Code Online (Sandbox Code Playgroud)
在__init__.pytest 文件夹的脚本中,我写了以下内容:
import os
import sys
PROJECT_PATH = os.getcwd()
SOURCE_PATH = os.path.join(
PROJECT_PATH,"src"
)
sys.path.append(SOURCE_PATH)
Run Code Online (Sandbox Code Playgroud)
共享项目的超级重要的是 Makefile,因为它强制正确运行脚本。这是我放在 Makefile 中的命令:
run_tests:
python -m unittest discover .
Run Code Online (Sandbox Code Playgroud)
Makefile 很重要,不仅因为它运行的命令,还因为它从哪里运行它。如果您将 cd in tests 和 do python -m unittest discover .,它将不起作用,因为unit_tests 中的init脚本调用 os.getcwd(),然后它将指向不正确的绝对路径(将附加到 sys.path 并且您将丢失您的源文件夹)。由于发现发现所有测试,脚本将运行,但它们无法正常运行。所以 Makefile 是为了避免记住这个问题。
我真的很喜欢这种方法,因为我不必接触我的 src 文件夹、我的单元测试或我的环境变量,一切都运行顺利。
让我知道你们是否喜欢它。
希望有所帮助,
如果你运行"python setup.py develop",那么包将在路径中.但是你可能不想那样做,因为你可以感染你的系统python安装,这就是为什么存在像virtualenv和buildout这样的工具.
我有同样的问题,有一个单独的单元测试文件夹.从提到的建议,我添加了绝对的源路径来sys.path.
以下解决方案的好处是,可以在test/test_yourmodule.py不首先更改为test-directory的情况下运行该文件:
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
Run Code Online (Sandbox Code Playgroud)
添加到@Pierre
\n\n使用unittest这样的目录结构:
new_project\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 antigravity\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py # make it a package\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 antigravity.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 test\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py # also make test a package\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 test_antigravity.py\nRun Code Online (Sandbox Code Playgroud)\n\n运行测试模块test_antigravity.py:
$ cd new_project\n$ python -m unittest test.test_antigravity\nRun Code Online (Sandbox Code Playgroud)\n\n或者单个TestCase
$ python -m unittest test.test_antigravity.GravityTestCase\nRun Code Online (Sandbox Code Playgroud)\n\n强制不要忘记__init__.py即使为空,否则将不起作用。
如果没有一些巫毒,你无法从父目录导入。这是至少适用于 Python 3.6 的另一种方法。
首先,有一个包含以下内容的文件 test/context.py:
import sys
import os
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
Run Code Online (Sandbox Code Playgroud)
然后在文件 test/test_antigravity.py 中导入以下内容:
import unittest
try:
import context
except ModuleNotFoundError:
import test.context
import antigravity
Run Code Online (Sandbox Code Playgroud)
请注意,这个 try- except 子句的原因是
通过这种诡计,他们都起作用了。
现在您可以使用以下命令运行测试目录中的所有测试文件:
$ pwd
/projects/new_project
$ python -m unittest
Run Code Online (Sandbox Code Playgroud)
或使用以下命令运行单独的测试文件:
$ cd test
$ python test_antigravity
Run Code Online (Sandbox Code Playgroud)
好吧,这并不比 test_antigravity.py 中包含 context.py 的内容漂亮多少,但也许有一点。欢迎提出建议。
使用setup.py develop让您的工作目录是安装Python环境的一部分,然后运行测试.
如果您使用VS Code并且您的测试与项目位于同一级别,那么运行和调试代码将无法开箱即用.你可以做的是改变你的launch.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"
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
这里的关键是envFile
"envFile": "${workspaceRoot}/.env",
Run Code Online (Sandbox Code Playgroud)
在项目的根目录中添加.env文件
在.env文件中添加项目根目录的路径.这将暂时添加
PYTHONPATH = C:\您的\ PYTHON\PROJECT\ROOT_DIRECTORY
项目的路径,您将能够使用VS Code中的调试单元测试
Python unittest模块的解决方案/示例
鉴于以下项目结构:
ProjectName
??? project_name
| ??? models
| | ??? thing_1.py
| ??? __main__.py
??? test
??? models
| ??? test_thing_1.py
??? __main__.py
Run Code Online (Sandbox Code Playgroud)
您可以从根目录运行您的项目python project_name,调用ProjectName/project_name/__main__.py.
要运行测试python test,有效运行ProjectName/test/__main__.py,您需要执行以下操作:
1)test/models通过添加__init__.py文件将目录转换为包.这使得可以从父test目录访问子目录中的测试用例.
# ProjectName/test/models/__init__.py
from .test_thing_1 import Thing1TestCase
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
现在,您可以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)
Run Code Online (Sandbox Code Playgroud)
我注意到,如果您从“ src”目录运行unittest命令行界面,则导入无需修改即可正常工作。
python -m unittest discover -s ../test
Run Code Online (Sandbox Code Playgroud)
如果要将其放入项目目录中的批处理文件中,可以执行以下操作:
setlocal & cd src & python -m unittest discover -s ../test
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
184480 次 |
| 最近记录: |