Pythonunit testing:如何只运行testing文件的一部分?
我有一个testing文件,其中包含testing需要相当多的时间(他们发送计算到一个集群,并等待结果)。 所有这些都在特定的TestCase类中。
由于他们需要时间,而且不会中断,所以我希望能够selecttesting的这个子集是否运行(最好的方法是使用命令行参数,即“ ./tests.py --offline
“或者类似的东西),所以当我有时间的时候,我可以经常快速地运行大部分testing,而且偶尔也可以运行整个testing。
现在,我只使用unittest.main()
来开始testing。
谢谢。
默认的unittest.main()
使用默认的testing加载器来使一个TestSuite不在运行main的模块中。
您不必使用此默认行为。
例如,您可以创build三个unittest.TestSuite实例。
-
“快”子集。
fast = TestSuite() fast.addTests( TestFastThis ) fast.addTests( TestFastThat )
-
“慢”子集。
slow = TestSuite() slow.addTests( TestSlowAnother ) slow.addTests( TestSlowSomeMore )
-
“整体”设置。
alltests = unittest.TestSuite([fast, slow])
请注意,我已经调整了TestCase名称来指示快速与慢速。 您可以inheritanceunittest.TestLoader来分析类的名称并创build多个加载器。
然后你的主程序就可以用optparse或者argparse (2.7或者3.2以后的版本)parsing命令行参数来select你想运行哪个套件,快,慢或者全部。
或者,你可以相信, sys.argv[1]
是三个值之一,并使用这样简单的东西
if __name__ == "__main__": suite = eval(sys.argv[1]) # Be careful with this line! unittest.TextTestRunner().run(suite)
要只运行一个特定的testing,您可以使用:
$ python -m unittest test_module.TestClass.test_method
更多信息在这里
实际上,可以将testing用例的名称作为sys.argv来传递,只有这些用例才会被testing。
例如,假设你有
class TestAccount(unittest.TestCase): ... class TestCustomer(unittest.TestCase): ... class TestShipping(unittest.TestCase): ... account = TestAccount customer = TestCustomer shipping = TestShipping
你可以打电话
python test.py account
只有帐户testing,甚至
$ python test.py account customer
有两个案件testing
你基本上有两种方法来做到这一点:
- 定义你自己的class级testing
- 创build将返回实际数据的群集连接的模拟类。
我强烈支持他的第二种方法。 一个unit testing应该只testing一个代码单元,而不是复杂的系统(如数据库或集群)。 但是我明白,这并不总是可能的。 有时候,创build模拟器太贵了,或者testing的目标确实在复杂的系统中。
回到选项(1),你可以这样进行:
suite = unittest.TestSuite() suite.addTest(MyUnitTestClass('quickRunningTest')) suite.addTest(MyUnitTestClass('otherTest'))
然后将套件传给testing运行者:
unittest.TextTestRunner().run(suite)
有关python文档的更多信息: http : //docs.python.org/library/unittest.html#testsuite-objects
既然你使用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
我正在使用一个简单的skipIf
做这个:
import os SLOW_TESTS = int(os.getenv('SLOW_TESTS', '0')) @unittest.skipIf(not SLOW_TESTS, "slow") class CheckMyFeature(unittest.TestCase): def runTest(self): …
这样我只需要用这一行装饰一个已经存在的testing用例(不需要创buildtesting套件或者类似的东西,只需要在我的unit testing文件的开头就有一个os.getenv()
调用行),并且默认情况下testing会被跳过。
如果我想执行它,尽pipe速度很慢,我只需要像这样调用脚本:
SLOW_TESTS=1 python -m unittest …
或者你可以使用unittest.SkipTest()
函数。 例如,像下面这样添加一个skipOrRunTest
方法到你的testing类:
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方法到每个unit testing的开始,像这样:
def testType4(self): self.skipOrRunTest('testType4')
看看使用一个专门的testrunner,像py.test,鼻子甚至可能甚至zope.testing。 他们都有selecttesting的命令行选项。
以鼻子为例: https : //pypi.python.org/pypi/nose/1.3.0
我试过@ 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)
我find了另一种方法来selecttest_ *方法,我只想通过给它们添加一个属性来运行。 你基本上使用一个元类来装饰TestCase类中具有StepDebug属性和unittest.skip装饰器的可调用元素。 更多信息
通过使用装饰器和元类跳过所有的unit testing,但在Python中是一个unit testing
我不知道这是比上述更好的解决scheme,我只是提供一个选项。
还没有find一个好的方法来做到这一点,所以在这里分享。
目标:获取一组testing文件,以便它们可以作为一个单元运行,但我们仍然可以select其中的任何一个单独运行。
问题:发现方法不允许简单地select一个testing用例来运行。
devise:见下文。 这使命名空间变平 ,所以可以通过TestCase类名来select,而不要使用“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 )
这是我唯一的工作。
if __name__ == '__main__': unittest.main( argv=sys.argv, testRunner = unittest.TextTestRunner(verbosity=2))
当我打电话给我的时候,我不得不通过class级名称和考试名称。 有点不方便,因为我没有上课和考试名字的组合。
python ./tests.py class_Name.test_30311
删除类名称和testing名称将运行文件中的所有testing。 我发现这样做更容易处理内置的方法,因为我没有真正改变我的CLI命令。 只需添加参数。
享受,基思