问题:通过命令行从unittest.TestCase运行单个测试
在我们的团队中,我们定义了大多数测试用例,如下所示:
一门“框架”课ourtcfw.py
:
import unittest
class OurTcFw(unittest.TestCase):
def setUp:
# something
# other stuff that we want to use everywhere
还有很多测试用例,例如testMyCase.py:
import localweather
class MyCase(OurTcFw):
def testItIsSunny(self):
self.assertTrue(localweather.sunny)
def testItIsHot(self):
self.assertTrue(localweather.temperature > 20)
if __name__ == "__main__":
unittest.main()
当我编写新的测试代码并希望经常运行它并节省时间时,我要做的是在所有其他测试之前放置“ __”。但这很麻烦,使我从正在编写的代码中分散了注意力,并且由此产生的提交噪音实在令人讨厌。
因此,例如,当对进行更改时testItIsHot()
,我希望能够做到这一点:
$ python testMyCase.py testItIsHot
并unittest
运行只 testItIsHot()
我该如何实现?
我尝试重写该if __name__ == "__main__":
部分,但是由于我是Python的新手,所以我迷失了方向,不停地尝试除方法之外的所有事情。
回答 0
这可以按照您的建议进行工作-您只需指定类名即可:
python testMyCase.py MyCase.testItIsHot
回答 1
如果您组织测试用例,即遵循与实际代码相同的组织,并且对同一包中的模块使用相对导入
您还可以使用以下命令格式:
python -m unittest mypkg.tests.test_module.TestClass.test_method
# In your case, this would be:
python -m unittest testMyCase.MyCase.testItIsHot
与此相关的Python3文档:https ://docs.python.org/3/library/unittest.html#command-line-interface
回答 2
您可以猜到它可以很好地工作
python testMyCase.py MyCase.testItIsHot
还有另一种方法可以测试testItIsHot
:
suite = unittest.TestSuite()
suite.addTest(MyCase("testItIsHot"))
runner = unittest.TextTestRunner()
runner.run(suite)
回答 3
如果您查看unittest模块的帮助,它将告诉您几种组合,这些组合允许您从模块运行测试用例类,并从测试用例类运行测试方法。
python3 -m unittest -h
[...]
Examples:
python3 -m unittest test_module - run tests from test_module
python3 -m unittest module.TestClass - run tests from module.TestClass
python3 -m unittest module.Class.test_method - run specified test method
它不需要您将a定义unittest.main()
为模块的默认行为。
回答 4
也许对某人会有帮助。如果您只想运行特定类的测试:
if __name__ == "__main__":
unittest.main(MyCase())
它在python 3.6中对我有用
回答 5
受@yarkee的启发,我将其与已经获得的一些代码结合在一起。您也可以从另一个脚本中调用此方法,run_unit_tests()
而无需调用命令行即可直接调用该函数,也可以仅通过命令行从中调用它python3 my_test_file.py
。
import my_test_file
my_test_file.run_unit_tests()
可悲的是,这仅适用于Python 3.3
或优于:
import unittest
class LineBalancingUnitTests(unittest.TestCase):
@classmethod
def setUp(self):
self.maxDiff = None
def test_it_is_sunny(self):
self.assertTrue("a" == "a")
def test_it_is_hot(self):
self.assertTrue("a" != "b")
跑步者代码:
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import unittest
from .somewhere import LineBalancingUnitTests
def create_suite(classes, unit_tests_to_run):
suite = unittest.TestSuite()
unit_tests_to_run_count = len( unit_tests_to_run )
for _class in classes:
_object = _class()
for function_name in dir( _object ):
if function_name.lower().startswith( "test" ):
if unit_tests_to_run_count > 0 \
and function_name not in unit_tests_to_run:
continue
suite.addTest( _class( function_name ) )
return suite
def run_unit_tests():
runner = unittest.TextTestRunner()
classes = [
LineBalancingUnitTests,
]
# Comment all the tests names on this list, to run all Unit Tests
unit_tests_to_run = [
"test_it_is_sunny",
# "test_it_is_hot",
]
runner.run( create_suite( classes, unit_tests_to_run ) )
if __name__ == "__main__":
print( "\n\n" )
run_unit_tests()
稍微编辑一下代码,您可以传递一个包含您要调用的所有单元测试的数组:
...
def run_unit_tests(unit_tests_to_run):
runner = unittest.TextTestRunner()
classes = \
[
LineBalancingUnitTests,
]
runner.run( suite( classes, unit_tests_to_run ) )
...
和另一个文件:
import my_test_file
# Comment all the tests names on this list, to run all Unit Tests
unit_tests_to_run = \
[
"test_it_is_sunny",
# "test_it_is_hot",
]
my_test_file.run_unit_tests( unit_tests_to_run )
或者,您可以使用https://docs.python.org/3/library/unittest.html#load-tests-protocol并在测试模块/文件上定义以下方法:
def load_tests(loader, standard_tests, pattern):
suite = unittest.TestSuite()
# To add a single test from this file
suite.addTest( LineBalancingUnitTests( 'test_it_is_sunny' ) )
# To add a single test class from this file
suite.addTests( unittest.TestLoader().loadTestsFromTestCase( LineBalancingUnitTests ) )
return suite
如果要将执行限制为单个测试文件,则只需将测试发现模式设置为定义load_tests()
函数的唯一文件。
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
import unittest
test_pattern = 'mytest/module/name.py'
PACKAGE_ROOT_DIRECTORY = os.path.dirname( os.path.realpath( __file__ ) )
loader = unittest.TestLoader()
start_dir = os.path.join( PACKAGE_ROOT_DIRECTORY, 'testing' )
suite = loader.discover( start_dir, test_pattern )
runner = unittest.TextTestRunner( verbosity=2 )
results = runner.run( suite )
print( "results: %s" % results )
print( "results.wasSuccessful: %s" % results.wasSuccessful() )
sys.exit( not results.wasSuccessful() )
参考文献:
除了最后一个主程序示例,在阅读unittest.main()
方法实现后,我想到了以下变体:
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
import unittest
PACKAGE_ROOT_DIRECTORY = os.path.dirname( os.path.realpath( __file__ ) )
start_dir = os.path.join( PACKAGE_ROOT_DIRECTORY, 'testing' )
from testing_package import main_unit_tests_module
testNames = ["TestCaseClassName.test_nameHelloWorld"]
loader = unittest.TestLoader()
suite = loader.loadTestsFromNames( testNames, main_unit_tests_module )
runner = unittest.TextTestRunner(verbosity=2)
results = runner.run( suite )
print( "results: %s" % results )
print( "results.wasSuccessful: %s" % results.wasSuccessful() )
sys.exit( not results.wasSuccessful() )
回答 6
TL; DR:这很可能会起作用:
python mypkg/tests/test_module.py MyCase.testItIsHot
说明:
便捷的方式
python mypkg/tests/test_module.py MyCase.testItIsHot
可以正常工作,但它的潜台词是,您已经在测试文件中(通常在末尾)包含了此常规代码段。
if __name__ == "__main__": unittest.main()
不便的方式
python -m unittest mypkg.tests.test_module.TestClass.test_method
将始终有效,而无需
if __name__ == "__main__": unittest.main()
在测试源文件中包含该代码段。
那么为什么第二种方法不方便?因为手动键入该长的,用点分隔的路径会很麻烦(_ 在此处插入您的身体部位之一)。在第一种方法中,mypkg/tests/test_module.py
可以使用现代外壳或编辑器自动完成零件。
PS:如果您认为身体部位在腰部以下,那么您就是一个真实的人。:-)我的意思是说“手指关节”。打字过多对您的关节不利。;-)