我有一个测试文件,其中包含花费大量时间的测试(他们将计算发送到集群并等待结果)。所有这些都在特定的TestCase类中。
由于它们需要时间而且不太可能破坏,我希望能够选择是否运行这个测试子集(最好的方法是使用命令行参数,即“ ./tests.py --offline
“或类似的东西”,所以我可以经常快速地运行大部分测试,并在我有时间的情况下偶尔运行整个测试。
目前,我只是使用unittest.main()
开始测试。
感谢。
答案 0 :(得分:80)
答案 1 :(得分:50)
默认的unittest.main()
使用默认的测试加载程序从运行main的模块中生成TestSuite。
您不必使用此默认行为。
例如,您可以制作三个unittest.TestSuite个实例。
“快速”子集。
fast = TestSuite()
fast.addTests( TestFastThis )
fast.addTests( TestFastThat )
“慢”子集。
slow = TestSuite()
slow.addTests( TestSlowAnother )
slow.addTests( TestSlowSomeMore )
“整体”集。
alltests = unittest.TestSuite([fast, slow])
请注意,我已调整TestCase名称以指示快速与慢速。你可以继承 unittest.TestLoader用于解析类的名称并创建多个加载器。
然后您的主程序可以使用optparse或argparse(自2.7或3.2以来可用)解析命令行参数,以选择要运行的套件,快速,慢速或全部。
或者,您可以相信sys.argv[1]
是三个值之一,并使用像这样简单的东西
if __name__ == "__main__":
suite = eval(sys.argv[1]) # Be careful with this line!
unittest.TextTestRunner().run(suite)
答案 2 :(得分:10)
实际上,可以将测试用例的名称作为sys.argv传递,并且只测试那些情况。
例如,假设你有
class TestAccount(unittest.TestCase):
...
class TestCustomer(unittest.TestCase):
...
class TestShipping(unittest.TestCase):
...
account = TestAccount
customer = TestCustomer
shipping = TestShipping
你可以打电话
python test.py account
只进行帐户测试,甚至是
$ python test.py account customer
测试两个案例
答案 3 :(得分:9)
我使用简单的skipIf
:
import os
SLOW_TESTS = int(os.getenv('SLOW_TESTS', '0'))
@unittest.skipIf(not SLOW_TESTS, "slow")
class CheckMyFeature(unittest.TestCase):
def runTest(self):
…
这样我只需用这一行来装饰已经存在的测试用例(不需要创建测试套件或类似的,只需要在我的单元测试文件的开头创建一个os.getenv()
调用行),并且默认情况下会跳过此测试。
如果我想尽快执行它,我只需要调用我的脚本:
SLOW_TESTS=1 python -m unittest …
答案 4 :(得分:8)
你基本上有两种方法可以做到:
我是他第二种方法的坚定支持者;单元测试应该只测试一个非常单元的代码,而不是复杂的系统(如数据库或集群)。但我明白并非总是可行;有时,创建模型太昂贵了,或者测试的目标确实在复杂的系统中。
返回选项(1),您可以这样做:
suite = unittest.TestSuite()
suite.addTest(MyUnitTestClass('quickRunningTest'))
suite.addTest(MyUnitTestClass('otherTest'))
然后将套件传递给测试运行器:
unittest.TextTestRunner().run(suite)
有关python文档的更多信息:http://docs.python.org/library/unittest.html#testsuite-objects
答案 5 :(得分:6)
由于您使用unittest.main()
,因此您只需运行python tests.py --help
即可获取文档:
Usage: tests.py [options] [test] [...]
Options:
-h, --help Show this message
-v, --verbose Verbose output
-q, --quiet Minimal output
-f, --failfast Stop on first failure
-c, --catch Catch control-C and display results
-b, --buffer Buffer stdout and stderr during test runs
Examples:
tests.py - run default set of tests
tests.py MyTestSuite - run suite 'MyTestSuite'
tests.py MyTestCase.testSomething - run MyTestCase.testSomething
tests.py MyTestCase - run all 'test*' test methods
in MyTestCase
也就是说,你可以简单地做到
python tests.py TestClass.test_method
答案 6 :(得分:2)
或者您可以使用unittest.SkipTest()
功能。例如,将skipOrRunTest
方法添加到测试类中,如下所示:
def skipOrRunTest(self,testType):
#testsToRun = 'ALL'
#testsToRun = 'testType1, testType2, testType3, testType4,...etc'
#testsToRun = 'testType1'
#testsToRun = 'testType2'
#testsToRun = 'testType3'
testsToRun = 'testType4'
if ((testsToRun == 'ALL') or (testType in testsToRun)):
return True
else:
print "SKIPPED TEST because:\n\t testSuite '" + testType + "' NOT IN testsToRun['" + testsToRun + "']"
self.skipTest("skipppy!!!")
然后在每个单元测试的最开头添加对此skipOrRunTest方法的调用,如下所示:
def testType4(self):
self.skipOrRunTest('testType4')
答案 7 :(得分:2)
我找到了另一种解决方案,基于unittest.skip
装饰器的工作原理。
通过设置__unittest_skip__
和__unittest_skip_why__
。
<强>基于标签的强>
我想应用标签系统,将某些测试标记为quick
,slow
,glacier
,memoryhog
,cpuhog
,{{1}等等。
然后运行core
或all 'quick' tests
您的基本白名单/黑名单设置
<强>实施强>
我分两部分实现了这个:
run everything except 'memoryhog' tests
类装饰器)@testlabel
以确定要跳过哪些测试,并在执行前修改测试列表内容。工作实施在这个要点: https://gist.github.com/fragmuffin/a245f59bdcd457936c3b51aa2ebb3f6c
(一个完整的例子太长了,无法放在这里)
结果是......
unittest.TestRunner
所有$ ./runtests.py --blacklist foo
test_foo (test_things.MyTest2) ... ok
test_bar (test_things.MyTest3) ... ok
test_one (test_things.MyTests1) ... skipped 'label exclusion'
test_two (test_things.MyTests1) ... skipped 'label exclusion'
----------------------------------------------------------------------
Ran 4 tests in 0.000s
OK (skipped=2)
类测试都会被跳过,因为它有MyTests1
标签。
foo
也有效
答案 8 :(得分:1)
使用专用的testrunner,比如py.test,nose或者甚至zope.testing。它们都有用于选择测试的命令行选项。
查看示例为Nose:https://pypi.python.org/pypi/nose/1.3.0
答案 9 :(得分:1)
我试过@slott的回答:
if __name__ == "__main__":
suite = eval(sys.argv[1]) # Be careful with this line!
unittest.TextTestRunner().run(suite)
但是这给了我以下错误:
Traceback (most recent call last):
File "functional_tests.py", line 178, in <module>
unittest.TextTestRunner().run(suite)
File "/usr/lib/python2.7/unittest/runner.py", line 151, in run
test(result)
File "/usr/lib/python2.7/unittest/case.py", line 188, in __init__
testMethod = getattr(self, methodName)
TypeError: getattr(): attribute name must be string
以下对我有用:
if __name__ == "__main__":
test_class = eval(sys.argv[1])
suite = unittest.TestLoader().loadTestsFromTestCase(test_class)
unittest.TextTestRunner().run(suite)
答案 10 :(得分:0)
我找到了另一种方法来选择我只想通过向它们添加属性来运行的test_ *方法。您基本上使用元类来装饰TestCase类中具有带有unittest.skip装饰器的StepDebug属性的可调用对象。有关
的更多信息Skipping all unit tests but one in Python by using decorators and metaclasses
我不知道它是否比上述更好的解决方案我只是提供它作为选项。
答案 11 :(得分:0)
之前没有找到一个很好的方法,所以在这里分享。
目标:将一组测试文件放在一起,以便它们可以作为一个单元运行, 但我们仍然可以选择其中任何一个单独运行。
问题:discover方法不允许轻松选择要运行的单个测试用例。
设计:见下文。这个展平命名空间,因此可以通过TestCase类名选择,并且不使用“tests1.test_core”前缀:
./run-tests TestCore.test_fmap
代码
test_module_names = [
'tests1.test_core',
'tests2.test_other',
'tests3.test_foo',
]
loader = unittest.defaultTestLoader
if args:
alltests = unittest.TestSuite()
for a in args:
for m in test_module_names:
try:
alltests.addTest( loader.loadTestsFromName( m+'.'+a ) )
except AttributeError as e:
continue
else:
alltests = loader.loadTestsFromNames( test_module_names )
runner = unittest.TextTestRunner( verbosity = opt.verbose )
runner.run( alltests )
答案 12 :(得分:0)
这是唯一对我有用的东西。
if __name__ == '__main__':
unittest.main( argv=sys.argv, testRunner = unittest.TextTestRunner(verbosity=2))
当我调用它时,我必须传入类的名称和测试名称。有点不方便,因为我没有记住课堂和考试名称的组合。
python ./tests.py class_Name.test_30311
删除类名和测试名会运行文件中的所有测试。我觉得这更容易处理内置方法因为我没有真正改变我在CLI上的命令。只需添加参数。
享受, 基思
答案 13 :(得分:0)
我创建了一个装饰器,该装饰器允许将测试标记为慢速测试,并使用环境变量将其跳过
from unittest import skip
import os
def slow_test(func):
return skipIf('SKIP_SLOW_TESTS' in os.environ, 'Skipping slow test')(func)
现在您可以像这样将测试标记为缓慢:
@slow_test
def test_my_funky_thing():
perform_test()
并通过设置SKIP_SLOW_TESTS
环境变量来跳过慢速测试:
SKIP_SLOW_TESTS=1 python -m unittest
答案 14 :(得分:0)
我发现这个答案试图弄清楚如何只运行特定的类测试;例如,
class TestCase1(unittest.TestCase):
def some_test(self):
self.assertEqual(True, True)
class TestCase2(unittest.TestCase):
def some_other_test(self):
self.assertEqual(False, False)
我想要一种快速注释掉 TestCase1
或 TestCase2
的方法,而不需要我扫选 100 多行代码,最终我找到了这个:
if __name__ == "__main__":
tests = []
tests.append("TestCase1")
# tests.append("TestCase2")
unittest.main(defaultTest=tests)
它只是使用 unittest.main()
的 defaultTest
参数来指定要运行的测试类。
答案 15 :(得分:0)
有时我会手动运行每个测试功能。假设我的测试类看起来像这样...
class TestStuff(unittest.TestCase):
def test1():
def test2():
然后我运行这个...
t = TestStuff()
t.test1()
t.test2()
(我使用 Spyder IDE 进行数据分析,这对于具有更灵活的测试工具的 IDE 来说可能不太理想)