我有一个包含我的Python单元测试的目录 . 每个单元测试模块的形式为 test_*.py . 我正在尝试创建一个名为 all_test.py 的文件,您猜对了,运行上述测试表单中的所有文件并返回结果 . 到目前为止,我尝试了两种方法;都失败了 . 我将展示这两种方法,我希望那里的人知道如何正确地做到这一点 .
对于我的第一次勇敢尝试,我想“如果我只是在文件中导入我的所有测试模块,然后调用这个 unittest.main()
doodad,它会起作用,对吧?”好吧,事实证明我错了 .
import glob
import unittest
testSuite = unittest.TestSuite()
test_file_strings = glob.glob('test_*.py')
module_strings = [str[0:len(str)-3] for str in test_file_strings]
if __name__ == "__main__":
unittest.main()
这不起作用,我得到的结果是:
$ python all_test.py
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
对于我的第二次尝试,我可以,好吧,也许我会尝试以更“手动”的方式完成整个测试 . 所以我试着在下面这样做:
import glob
import unittest
testSuite = unittest.TestSuite()
test_file_strings = glob.glob('test_*.py')
module_strings = [str[0:len(str)-3] for str in test_file_strings]
[__import__(str) for str in module_strings]
suites = [unittest.TestLoader().loadTestsFromName(str) for str in module_strings]
[testSuite.addTest(suite) for suite in suites]
print testSuite
result = unittest.TestResult()
testSuite.run(result)
print result
#Ok, at this point I have a result
#How do I display it as the normal unit test command line output?
if __name__ == "__main__":
unittest.main()
这也没用,但似乎太近了!
$ python all_test.py
<unittest.TestSuite tests=[<unittest.TestSuite tests=[<unittest.TestSuite tests=[<test_main.TestMain testMethod=test_respondes_to_get>]>]>]>
<unittest.TestResult run=1 errors=0 failures=0>
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
我似乎有一些类型的套件,我可以执行结果 . 我有点担心它说我只有 run=1
,看起来应该是 run=2
,但这是进步 . 但是如何将结果传递给main?或者我如何基本上使它工作,所以我可以运行这个文件,并在这样做,运行此目录中的所有单元测试?
14 回答
通过研究上面的代码(特别是使用
TextTestRunner
和defaultTestLoader
),我能够非常接近 . 最后我通过将所有测试套件传递给单个套件构造函数来修复我的代码,而不是添加它们"manually",这修复了我的其他问题 . 所以这是我的解决方案 .是的,使用鼻子可能比做这个更容易,但这是重点 .
因为测试发现似乎是一个完整的主题,所以有一些专门的框架来测试发现:
nose
Py.Test
更多阅读:https://wiki.python.org/moin/PythonTestingToolsTaxonomy
您可以使用可以为您执行此操作的测试运行器 . nose非常好 . 例如 . 运行时,它将在当前树中找到测试并运行它们 .
更新:
这是我前鼻子时代的一些代码 . 您可能不希望显式的模块名称列表,但其余部分可能对您有用 .
基于Stephen Cagle的答案,我添加了对嵌套测试模块的支持 .
代码在
.
的所有子目录中搜索*Tests.py
文件,然后加载这些文件 . 它希望每个*Tests.py
包含一个类*Tests(unittest.TestCase)
,它依次加载并一个接一个地执行 .这适用于目录/模块的任意深度嵌套,但其间的每个目录至少需要包含一个空的
__init__.py
文件 . 这允许测试通过用点替换斜杠(或反斜杠)来加载嵌套模块(参见replace_slash_by_dot
) .使用Python 2.7及更高版本,您不必编写新代码或使用第三方工具来执行此操作;通过命令行执行递归测试是内置的 .
您可以在python 2.7或python 3.x unittest文档中阅读更多内容 .
无论您在哪个工作目录中,此BASH脚本都将从文件系统中的ANYWHERE执行python unittest测试目录:其工作目录始终位于
test
目录所在的位置 .ALL TESTS, independent $PWD
unittest Python模块对您当前的目录很敏感,除非您告诉它在哪里(使用
discover -s
选项) .这在停留在
./src
或./example
工作目录中时非常有用,您需要进行快速的整体单元测试:SELECTED TESTS, independent $PWD
我将此实用程序文件命名为:
runone.py
并像这样使用它:生产环境 过程中不需要
test/__init__.py
文件来增加包/内存开销 .现在可以直接从unittest:unittest.TestLoader.discover .
如果是打包的库或应用程序,您不希望这样做 .
setuptools
will do it for you .只需告诉它根测试包的位置,例如:
并运行
python setup.py test
.基于文件的发现在Python 3中可能存在问题,除非您避免在测试套件中进行相对导入,因为discover使用文件导入 . 即使它支持可选的
top_level_dir
,但我有一些无限的递归错误 . 因此,对于非打包代码的简单解决方案是将以下内容放在测试包的__init__.py
中(请参阅load_tests Protocol) .在python 3中,如果您正在使用
unittest.TestCase
并且测试目录中有一个空(或其他)__init__.py
文件,那么您可以运行所有测试完成!小于100行的解决方案 . 希望另一个python初学者通过找到它来节省时间 .
我尝试了各种方法,但都看起来有缺陷,或者我不得不化妆一些代码,这很烦人 . 但是有一个方便的在linux下,只需通过某种模式查找每个测试,然后逐个调用它们 .
最重要的是,它绝对有效 .
这是我的方法,创建a wrapper从命令行运行测试:
为简单起见,请原谅我的非PEP8编码标准 .
然后,您可以为所有测试创建公共组件的BaseTest类,因此您的每个测试都将如下所示:
要运行,只需将测试指定为命令行参数的一部分,例如:
我使用PyDev / LiClipse并没有真正弄清楚如何从GUI一次运行所有测试 . (编辑:右键单击根测试文件夹并选择
Run as -> Python unit-test
这是我目前的解决方法:
我将此代码放在我的测试目录中名为
all
的模块中 . 如果我从LiClipse运行此模块作为单元测试,则运行所有测试 . 如果我要求只重复特定或失败的测试,那么只运行那些测试 . 它没有被忽视 .您可能需要根据项目设置将参数更改为
discover
.如果您想从各种测试用例类中运行所有测试,并且您很乐意明确指定它们,那么您可以这样做:
其中
uclid
是我的项目,TestSymbols
和TestPatterns
是TestCase
的子类 .我已经使用了
discover
方法和load_tests
的重载来实现这个结果(我认为最小的)数字代码行:执行就像五个人一样