Ste*_*gle 268 python testing unit-testing python-unittest
我有一个包含我的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()
Run Code Online (Sandbox Code Playgroud)
这不起作用,我得到的结果是:
$ python all_test.py
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
Run Code Online (Sandbox Code Playgroud)
对于我的第二次尝试,我可以,也许我会尝试以更"手动"的方式完成整个测试.所以我试着在下面这样做:
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()
Run Code Online (Sandbox Code Playgroud)
这也行不通,但似乎太近了!
$ 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 Code Online (Sandbox Code Playgroud)
我似乎有一些类型的套件,我可以执行结果.我有点担心它说我只有run=1,似乎应该是run=2,但这是进步.但是如何将结果传递给main?或者我如何基本上使它工作,所以我可以运行此文件,并在这样做,运行此目录中的所有单元测试?
Tra*_*ear 423
使用Python 2.7及更高版本,您无需编写新代码或使用第三方工具来执行此操作; 通过命令行执行递归测试是内置的.
python -m unittest discover <test_directory>
# or
python -m unittest discover -s <directory> -p '*_test.py'
Run Code Online (Sandbox Code Playgroud)
您可以在python 2.7 或python 3.x unittest文档中阅读更多内容.
Ned*_*der 103
您可以使用可以为您执行此操作的测试运行器. 鼻子非常好,例如.运行时,它将在当前树中找到测试并运行它们.
更新:
这是我前鼻子时代的一些代码.您可能不希望显式的模块名称列表,但其余部分可能对您有用.
testmodules = [
'cogapp.test_makefiles',
'cogapp.test_whiteutils',
'cogapp.test_cogapp',
]
suite = unittest.TestSuite()
for t in testmodules:
try:
# If the module defines a suite() function, call it to get the suite.
mod = __import__(t, globals(), locals(), ['suite'])
suitefn = getattr(mod, 'suite')
suite.addTest(suitefn())
except (ImportError, AttributeError):
# else, just load all the test cases from the module.
suite.addTest(unittest.defaultTestLoader.loadTestsFromName(t))
unittest.TextTestRunner().run(suite)
Run Code Online (Sandbox Code Playgroud)
tmc*_*ode 68
在python 3中,如果您正在使用unittest.TestCase:
__init__.py文件test(必须命名test/)test/与模式匹配test_*.py.它们可以位于下面的子目录中test/,并且这些子目录可以命名为任何内容.然后,您可以运行所有测试:
python -m unittest
Run Code Online (Sandbox Code Playgroud)
完成!解决方案少于100行.希望另一个python初学者通过找到它来节省时间.
sla*_*r98 59
现在可以直接从unittest:unittest.TestLoader.discover.
import unittest
loader = unittest.TestLoader()
start_dir = 'path/to/your/test/files'
suite = loader.discover(start_dir)
runner = unittest.TextTestRunner()
runner.run(suite)
Run Code Online (Sandbox Code Playgroud)
Ste*_*gle 30
通过研究上面的代码(特别是使用TextTestRunner和defaultTestLoader),我能够非常接近.最后我通过将所有测试套件传递给单个套件构造函数来修复我的代码,而不是"手动"添加它们,这解决了我的其他问题.所以这是我的解决方案.
import glob
import unittest
test_files = glob.glob('test_*.py')
module_strings = [test_file[0:len(test_file)-3] for test_file in test_files]
suites = [unittest.defaultTestLoader.loadTestsFromName(test_file) for test_file in module_strings]
test_suite = unittest.TestSuite(suites)
test_runner = unittest.TextTestRunner().run(test_suite)
Run Code Online (Sandbox Code Playgroud)
是的,使用鼻子可能比做这个更容易,但这是重点.
dem*_*hog 24
如果您想从各种测试用例类中运行所有测试,并且您很乐意明确指定它们,那么您可以这样做:
from unittest import TestLoader, TextTestRunner, TestSuite
from uclid.test.test_symbols import TestSymbols
from uclid.test.test_patterns import TestPatterns
if __name__ == "__main__":
loader = TestLoader()
tests = [
loader.loadTestsFromTestCase(test)
for test in (TestSymbols, TestPatterns)
]
suite = TestSuite(tests)
runner = TextTestRunner(verbosity=2)
runner.run(suite)
Run Code Online (Sandbox Code Playgroud)
uclid我的项目在哪里TestSymbols,TestPatterns是的子类TestCase.
rds*_*rds 13
我已经使用了discover方法和重载load_tests来实现这个结果(我认为最少)数字代码行:
def load_tests(loader, tests, pattern):
''' Discover and load all unit tests in all files named ``*_test.py`` in ``./src/``
'''
suite = TestSuite()
for all_test_suite in unittest.defaultTestLoader.discover('src', pattern='*_tests.py'):
for test_suite in all_test_suite:
suite.addTests(test_suite)
return suite
if __name__ == '__main__':
unittest.main()
Run Code Online (Sandbox Code Playgroud)
像五个人一样执行
Ran 27 tests in 0.187s
OK
Run Code Online (Sandbox Code Playgroud)
我尝试了各种各样的方法,但都看起来有缺陷,或者我必须编写一些代码,这很烦人.但是在linux下有一种方便的方法,就是通过某种模式找到每个测试,然后逐个调用它们.
find . -name 'Test*py' -exec python '{}' \;
Run Code Online (Sandbox Code Playgroud)
最重要的是,它绝对有效.
对于打包的库或应用程序,您不希望这样做.setuptools 会为你做的.
要使用此命令,必须
unittest通过函数,TestCase类或方法或包含TestCase类的模块或包将项目的测试包装在测试套件中.如果命名套件是一个模块,并且模块有一个additional_tests()函数,则调用它并将结果(必须是aunittest.TestSuite)添加到要运行的测试中.如果命名套件是一个包,则任何子模块和子包都以递归方式添加到整个测试套件中.
只需告诉它根测试包的位置,例如:
setup(
# ...
test_suite = 'somepkg.test'
)
Run Code Online (Sandbox Code Playgroud)
并运行python setup.py test.
基于文件的发现在Python 3中可能存在问题,除非您在测试套件中避免相对导入,因为discover使用文件导入.即使它支持可选top_level_dir,但我有一些无限的递归错误.因此,对于非打包代码的简单解决方案是将以下内容放入__init__.py测试包中(请参阅load_tests协议).
import unittest
from . import foo, bar
def load_tests(loader, tests, pattern):
suite = unittest.TestSuite()
suite.addTests(loader.loadTestsFromModule(foo))
suite.addTests(loader.loadTestsFromModule(bar))
return suite
Run Code Online (Sandbox Code Playgroud)
这是一个老问题,但现在(2019 年)对我有用的是:
python -m unittest *_test.py
Run Code Online (Sandbox Code Playgroud)
我的所有测试文件都与源文件位于同一文件夹中,并且以_test.