用典型的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议我添加绝对源pathsys.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 

安装pytestsudo 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