用典型的testing目录结构运行unittest
甚至一个简单的Python模块的通用目录结构似乎是将unit testing分离到他们自己的test
目录中:
new_project/ antigravity/ antigravity.py test/ test_antigravity.py setup.py etc.
例如看到这个Python项目howto 。
我的问题只是实际运行testing的常用方法是什么? 我怀疑这是除了我以外的每个人都很明显,但是你不能只从testing目录运行python test_antigravity.py
,因为import antigravity
python test_antigravity.py
将失败,因为模块不在path上。
我知道我可以修改PYTHONPATH和其他searchpath相关的技巧,但我不能相信这是最简单的方法 – 如果你是开发人员,这很好,但如果他们只是想检查testing是不现实的,通过。
另一种方法是将testing文件复制到另一个目录中,但似乎有点笨拙,并且错过了将它们放在一个单独的目录中的要点。
所以,如果你刚刚把源代码下载到我的新项目中,你将如何运行unit testing? 我更喜欢一个答案,让我对我的用户说:“运行unit testing做X.”
我认为最好的解决scheme是使用unittest
命令行界面 ,它将把目录添加到sys.path
所以你不必(在TestLoader
类中完成)。
例如对于像这样的目录结构:
new_project ├── antigravity.py └── test_antigravity.py
你可以运行:
$ cd new_project $ python -m unittest test_antigravity
对于像你这样的目录结构:
new_project ├── antigravity │ ├── __init__.py # make it a package │ └── antigravity.py └── test ├── __init__.py # also make test a package └── test_antigravity.py
在test
包内的testing模块中,您可以照常导入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
运行一个testing模块:
运行一个testing模块,在这种情况下是test_antigravity.py
:
$ cd new_project $ python -m unittest test.test_antigravity
只要引用testing模块,就像导入它的方法一样。
运行单个testing用例或testing方法
你也可以运行一个TestCase
或一个testing方法:
$ python -m unittest test.test_antigravity.GravityTestCase $ python -m unittest test.test_antigravity.GravityTestCase.test_method
运行所有testing:
您也可以使用testing发现来发现并运行所有testing,它们必须是名为test*.py
(可以用-p, --pattern
标志更改)的模块或包:
$ cd new_project $ python -m unittest discover
这将运行test
包内的所有test*.py
模块。
对于你的用户来说,最简单的解决scheme是提供一个可执行的脚本( runtests.py
或者其他一些)来引导必要的testing环境,包括,如果需要的话,暂时将你的根项目目录添加到sys.path中。 这不需要用户设置环境variables,像这样的东西在引导脚本中工作正常:
import sys, os sys.path.insert(0, os.path.dirname(__file__))
然后你的指示给你的用户可以像“python runtests.py”一样简单。
当然,如果你真正需要的path是os.path.dirname(__file__)
,那么你根本不需要把它添加到sys.path
; Python总是把当前正在运行的脚本的目录放在sys.path
的开头,所以根据你的目录结构,只要在正确的地方findruntests.py
就可以了。
此外, Python 2.7+中的unittest模块 (针对Python 2.6及更早版本以unittest2 反向移植)现在已经内置了testing发现function,因此如果您希望自动发现testing,鼻子不再是必需的:您的用户指令可以像“python -m unittest discover”。
从您链接到的文章:
创build一个test_modulename.py文件,并把你的unittesttesting。 由于testing模块与您的代码位于不同的目录中,因此您可能需要将模块的父目录添加到您的PYTHONPATH中才能运行它们:
$ cd /path/to/googlemaps $ export PYTHONPATH=$PYTHONPATH:/path/to/googlemaps/googlemaps $ python test/test_googlemaps.py
最后,还有一个比较stream行的Pythonunit testing框架(这非常重要!)。 鼻子有助于简化和扩展内置的unit testing框架(例如,它可以自动find你的testing代码并为你设置你的PYTHONPATH),但它不包含在标准的Python发行版中。
也许你应该看看鼻子,因为它表明?
我通常在加载我的“所有testing”套件的项目目录(源目录和test
共同的目录)中创build一个“运行testing”脚本。 这通常是样板代码,所以我可以在项目中重复使用它。
run_tests.py:
import unittest import test.all_tests testSuite = test.all_tests.create_test_suite() text_runner = unittest.TextTestRunner().run(testSuite)
test / all_tests.py(从我如何在目录中运行所有的Pythonunit testing? )
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
有了这个设置,你的确include antigravity
在你的testing模块中include antigravity
。 缺点是你需要更多的支持代码来执行特定的testing…我只是每次都运行它们。
如果你运行“python setup.py develop”,那么软件包将会在path中。 但是你可能不想这样做,因为你可能感染你的系统python安装,这就是为什么像virtualenv和buildout这样的工具存在。
使用setup.py develop
,使您的工作目录成为已安装的Python环境的一部分,然后运行testing。
我有一个单独的unit testing文件夹相同的问题。 从提到的build议我添加绝对源path到sys.path
。
以下解决scheme的好处是,可以运行文件test/test_yourmodule.py
而不必首先更改到test-directory:
import sys, os testdir = os.path.dirname(__file__) srcdir = '../src/projekt/dir' sys.path.insert(0, os.path.abspath(os.path.join(testdir, srcdir))) import yourmodule import unittest
可以使用运行选定或所有testing的包装器。
例如:
./run_tests antigravity/*.py
或者recursion地使用扩展的globbing( tests/**/*.py
)来运行所有的testing。
包装器基本上可以使用argparse
来parsing参数,如:
parser = argparse.ArgumentParser() parser.add_argument('files', nargs='*')
然后加载所有的testing:
for filename in args.files: exec(open(filename).read())
然后将它们添加到您的testing套件中(使用inspect
):
alltests = unittest.TestSuite() for name, obj in inspect.getmembers(sys.modules[__name__]): if inspect.isclass(obj) and name.startswith("FooTest"): alltests.addTest(unittest.makeSuite(obj))
并运行它们:
result = unittest.TextTestRunner(verbosity=2).run(alltests)
检查这个例子的更多细节。
另请参阅: 如何在目录中运行所有Pythonunit testing?
如果您使用VS Code,并且您的testing与您的项目位于同一级别,那么运行和debugging您的代码将无法正常工作。 你可以做的是改变你的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" ] } ] }
这里的关键是envFile
"envFile": "${workspaceRoot}/.env",
在项目的根目录中添加.env文件
.env文件的内部添加path到项目的根目录。 这将暂时添加
PYTHONPATH = C:\您的\ PYTHON \ PROJECT \ ROOT_DIRECTORY
你的项目的path,你将能够使用从VS代码debuggingunit testing
Pythonunit testing模块的解决scheme/示例
鉴于以下项目结构:
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
运行python test
,有效地运行ProjectName/test/__main__.py
,您需要执行以下操作:
1)通过添加一个__init__.py
文件,将您的test/models
目录变成一个包。 这使得子目录中的testing用例可以从父test
目录访问。
# ProjectName/test/models/__init__.py from .test_thing_1 import Thing1TestCase
2)在test/__main__.py
修改你的系统path以包含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)
现在,您可以在testing中成功从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)
以下是我的项目结构:
ProjectFolder: - project: - __init__.py - item.py - tests: - test_item.py
我发现最好在setUp()方法中导入:
import unittest import sys class ItemTest(unittest.TestCase): def setUp(self): sys.path.insert(0, "../project") from project import item # further setup using this import def test_item_props(self): # do my assertions if __name__ == "__main__": unittest.main()
实际运行testing的常用方法是什么?
我使用Python 3.6.2
cd new_project pytest test/test_antigravity.py
安装pytest : sudo pip install pytest
我没有设置任何pathvariables,我的导入不会失败,具有相同的“testing”项目结构。
我注释掉了这个东西: if __name__ == '__main__'
like this:
test_antigravity.py
import antigravity class TestAntigravity(unittest.TestCase): def test_something(self): # ... test stuff here # if __name__ == '__main__': # # if __package__ is None: # # import something # sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) # from .. import antigravity # # else: # # from .. import antigravity # # unittest.main()
我注意到,如果你从你的“src”目录运行unittest命令行界面,那么导入工作正确无需修改。
python -m unittest discover -s ../test
如果你想把它放在项目目录下的batch file中,你可以这样做:
setlocal & cd src & python -m unittest discover -s ../test
你应该真的使用点子工具。
使用pip install -e
以开发模式安装软件包。 这是一个非常好的做法。
在下面给出的Ref url中,给出了2个经典的项目(包括testing)布局,你可以按照其中的任何一个。
Ref :