Pythonunit testing:如何只运行testing文件的一部分?

我有一个testing文件,其中包含testing需要相当多的时间(他们发送计算到一个集群,并等待结果)。 所有这些都在特定的TestCase类中。

由于他们需要时间,而且不会中断,所以我希望能够selecttesting的这个子集是否运行(最好的方法是使用命令行参数,即“ ./tests.py --offline “或者类似的东西),所以当我有时间的时候,我可以经常快速地运行大部分testing,而且偶尔也可以运行整个testing。

现在,我只使用unittest.main()来开始testing。

谢谢。

默认的unittest.main()使用默认的testing加载器来使一个TestSuite不在运行main的模块中。

您不必使用此默认行为。

例如,您可以创build三个unittest.TestSuite实例。

  1. “快”子集。

     fast = TestSuite() fast.addTests( TestFastThis ) fast.addTests( TestFastThat ) 
  2. “慢”子集。

     slow = TestSuite() slow.addTests( TestSlowAnother ) slow.addTests( TestSlowSomeMore ) 
  3. “整体”设置。

     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

你基本上有两种方法来做到这一点:

  1. 定义你自己的class级testing
  2. 创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命令。 只需添加参数。

享受,基思