1.TestSuite
TestSuite类用来对测试用例进行组合分类,通常称为测试套件。我们可以将不同位置的测试用例集合到一个测试套件内,并利用其内部实现的run方法来执行。
为了直观的理解TestSuite的用法,下面先定义了两个测试类。每个测试类里分别定义了几个方法。
import unittest class TestDemo01(unittest.TestCase): def test01(self): print('This is test01.') def test02(self): print('This is test02.') def test03(self): print('This is test03.') class TestDemo02(unittest.TestCase): def test04(self): print('This is test04.') def test05(self): print('This is test05.') |
在执行的代码段中,首先加入TestDemo01中的test02方法来构建出测试套件suite01,然后重新构建一个测试套件suite02,包含suite01与TestDemo02中的test04方法共同构成的一个元组。最后使用run方法将执行的结果保存到r变量中。这里需要特别说明,tests的参数类型必须是可迭代的,例如本例中的列表和元组。
if __name__ == '__main__': suite01 = unittest.TestSuite(tests=[TestDemo01('test02')]) suite02 = unittest.TestSuite(tests=(suite01,TestDemo02('test04'))) r = unittest.TestResult() suite02.run(result=r) print(r.__dict__) |
本例中调用的是suite02中的run方法,那么运行的是suite02套件内的测试用例,依次为test02和test04。
This is test02. This is test04. {'failfast': False, 'failures': [], 'errors': [], 'testsRun': 2, 'skipped': [], 'expectedFailures': [], 'unexpectedSuccesses': [], 'shouldStop': False, 'buffer': False, 'tb_locals': False, '_stdout_buffer': None, '_stderr_buffer': None, '_original_stdout': <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>, '_original_stderr': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, '_mirrorOutput': False, '_testRunEntered': False, '_moduleSetUpFailed': False, '_previousTestClass': <class '__main__.TestDemo02'>} |
TestSuite类中除了run()以外,还有一些重要的方法:addTest(test)和addTests(tests)。addTest(test)为添加测试用例,参数可以是TestCase或TestSuite的实例。addTests(tests)顾名思义,是对TestCase或TestSuite的实例的多个迭代进行添加,其内部实现原理依然是调用addTest(test)。简单点说,前者是添加单个测试用例,而后者是为了一次性添加多个测试用例。
依然沿用TestDemo01和TestDemo02的例子,执行代码做了一些调整,首先得到测试套件实例suite,分别调用addTest和addTests方法来添加测试用例,注意在addTests中只有一个参数,并且类型是元组,最后执行并输出测试结果的字典。这里也额外使用了另外一个TestSuite中的常用方法countTestCases(),作用是返回执行的测试方法的个数。
if __name__ == '__main__': suite = unittest.TestSuite() suite.addTest(TestDemo01('test02')) suite.addTests((TestDemo02('test04'),TestDemo02('test05'))) r = unittest.TestResult() suite.run(result=r) print(r.__dict__) print(suite.countTestCases()) |
执行结果不再赘述,仍然是依次执行添加的各个测试用例,然后输出总共执行的测试方法个数3。
This is test02. This is test04. This is test05. {'failfast': False, 'failures': [], 'errors': [], 'testsRun': 3, 'skipped': [], 'expectedFailures': [], 'unexpectedSuccesses': [], 'shouldStop': False, 'buffer': False, 'tb_locals': False, '_stdout_buffer': None, '_stderr_buffer': None, '_original_stdout': <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>, '_original_stderr': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, '_mirrorOutput': False, '_testRunEntered': False, '_moduleSetUpFailed': False, '_previousTestClass': <class '__main__.TestDemo02'>} 3 |
2.TestLoader
TestLoader是Unittest框架中的一个重要的类,可以从被测试的类和模块中创建测试套件,即TestSuite。通常我们不用对他进行实例化,使用匿名对象的方式来使用即可。TestLoader中提供了如下一些常用的方法。
(1)loadTestsFromTestCase(testCaseClass) :从某个类中加载所有的测试方法,参数为加载的类名,testCaseClass必须继承于TestCase。
(2)loadTestsFromModule(module, pattern=None) :从某个模块中加载所有的测试方法,参数为模块名,即文件名。当该模块中有多个类都继承于TestCase时,那么这些类里的测试方法均会被执行。
(3)loadTestsFromName(name, module=None) :加载某个单独的测试方法,参数name是一个string,格式为“module.class.method”。
(4)loadTestsFromNames(name, module=None) :names是一个list,用法与上面相同。
下面依然沿用前面计算器的例子来进行讲解。模块名为Test01.py,代码中被测试类为Calculator,TestDemo01与TestDemo02均为测试类,并继承于unittest.TestCase,每个测试类中各有一个测试方法。在执行的代码中,分别使用类名、模块名、方法的方式来加载要测试的方法,并添加到了测试集suite中,最后执行测试集。
import unittest # 导入当前的Test01模块,用于后续使用 from C03_Unittest.Ex03_TestLoader import Test01 class Calculator: def divide(self,x,y): return x / y class TestDemo01 (unittest.TestCase): def test01(self): print('This is test01.') cal = Calculator() result = cal.divide(10,2) self.assertEqual(result,5) class TestDemo02(unittest.TestCase): def test02(self): print('This is test02.') cal = Calculator() result = cal.divide(0,2) self.assertEqual(result,0) if __name__ == '__main__': suite = unittest.TestSuite() # 加载该类 testCase01 = unittest.TestLoader().loadTestsFromTestCase(TestDemo01) # 加载整个模块 testCase02 = unittest.TestLoader().loadTestsFromModule(Test01) # 加载TestDemo01类中的测试方法test01 testCase03 = unittest.TestLoader().loadTestsFromName('C03_Unittest.Ex03_TestLoader.Test01.TestDemo01.test01') suite.addTests(testCase01) suite.addTests(testCase02) suite.addTests(testCase03) r = unittest.TestResult() suite.run(result=r) print(r.__dict__) |
运行结果如下,未出现失败和错误。仔细分析可以看到,由于先执行suite.addTests(testCase01), TestDemo01类中的方法被运行了,输出了“This is test01.”。接下来执行suite.addTests(testCase02),整个模块即Test01.py里的所有测试方法被执行,所以分别输出了“This is test01.”和“This is test02.”。最后加载的是testCase03,而他仅仅只是TestDemo01中的方法test01,所以又输出了一次“This is test01.”。