单元测试框架 - API
本章讨论unittest模块中定义的类和方法。该模块有五个主要类。
测试用例类
此类的对象代表最小的可测试单元。它保存测试例程并提供用于准备每个例程以及之后清理的挂钩。
TestCase 类中定义了以下方法 -
先生。 | 方法及说明 |
---|---|
1 | 设置() 调用方法来准备测试夹具。在调用测试方法之前立即调用此函数 |
2 | 拆除() 调用测试方法并记录结果后立即调用方法。即使测试方法引发异常,也会调用此方法, |
3 | 设置类() 在单个类中的测试运行之前调用的类方法。 |
4 | 拆解类() 在单个类中的测试运行后调用的类方法。 |
5 | 运行(结果=无) 运行测试,将结果收集到作为result传递的测试结果对象中。 |
6 | 跳过测试(原因) 在测试方法或 setUp() 期间调用此函数会跳过当前测试。 |
7 | 调试() 运行测试而不收集结果。 |
8 | 简短的介绍() 返回测试的一行描述。 |
固定装置
TestCase 类中可以编写大量测试。这些测试方法可能需要数据库连接、临时文件或其他资源进行初始化。这些被称为固定装置。TestCase 包含一个特殊的钩子来配置和清理测试所需的任何固定装置。要配置灯具,请重写 setUp()。要清理,请重写tearDown()。
在以下示例中,在 TestCase 类中编写了两个测试。他们测试两个值的加法和减法结果。setup() 方法根据每个测试的shortDescription() 初始化参数。Teadown() 方法将在每次测试结束时执行。
import unittest class simpleTest2(unittest.TestCase): def setUp(self): self.a = 10 self.b = 20 name = self.shortDescription() if name == "Add": self.a = 10 self.b = 20 print name, self.a, self.b if name == "sub": self.a = 50 self.b = 60 print name, self.a, self.b def tearDown(self): print '\nend of test',self.shortDescription() def testadd(self): """Add""" result = self.a+self.b self.assertTrue(result == 100) def testsub(self): """sub""" result = self.a-self.b self.assertTrue(result == -10) if __name__ == '__main__': unittest.main()
从命令行运行上述代码。它给出以下输出 -
C:\Python27>python test2.py Add 10 20 F end of test Add sub 50 60 end of test sub . ================================================================ FAIL: testadd (__main__.simpleTest2) Add ---------------------------------------------------------------------- Traceback (most recent call last): File "test2.py", line 21, in testadd self.assertTrue(result == 100) AssertionError: False is not true ---------------------------------------------------------------------- Ran 2 tests in 0.015s FAILED (failures = 1)
类夹具
TestCase 类有一个 setUpClass() 方法,可以在执行 TestCase 类内的各个测试之前重写该方法。类似地,tearDownClass() 方法将在类中的所有测试之后执行。这两个方法都是类方法。因此,它们必须用 @classmethod 指令修饰。
以下示例演示了这些类方法的用法 -
import unittest class TestFixtures(unittest.TestCase): @classmethod def setUpClass(cls): print 'called once before any tests in class' @classmethod def tearDownClass(cls): print '\ncalled once after all tests in class' def setUp(self): self.a = 10 self.b = 20 name = self.shortDescription() print '\n',name def tearDown(self): print '\nend of test',self.shortDescription() def test1(self): """One""" result = self.a+self.b self.assertTrue(True) def test2(self): """Two""" result = self.a-self.b self.assertTrue(False) if __name__ == '__main__': unittest.main()
测试套件类
Python 的测试框架提供了一种有用的机制,通过该机制可以根据测试用例实例所测试的功能将测试用例实例分组在一起。该机制由unittest模块中的TestSuite类提供。
创建和运行测试套件涉及以下步骤。
步骤 1 - 创建 TestSuite 类的实例。
suite = unittest.TestSuite()
步骤 2 - 在套件的 TestCase 类中添加测试。
suite.addTest(testcase class)
步骤 3 - 您还可以使用 makeSuite() 方法从类中添加测试
suite = unittest.makeSuite(test case class)
步骤 4 - 也可以在套件中添加单独的测试。
suite.addTest(testcaseclass(""testmethod")
步骤 5 - 创建 TestTestRunner 类的对象。
runner = unittest.TextTestRunner()
步骤 6 - 调用 run() 方法来运行套件中的所有测试
runner.run (suite)
TestSuite 类中定义了以下方法 -
先生。 | 方法及说明 |
---|---|
1 | 添加测试() 在测试套件中添加测试方法。 |
2 | 添加测试() 添加来自多个 TestCase 类的测试。 |
3 | 跑步() 运行与该套件关联的测试,将结果收集到测试结果对象中 |
4 | 调试() 运行与此套件关联的测试而不收集结果。 |
5 | 计数测试用例() 返回此测试对象代表的测试数量 |
以下示例显示如何使用 TestSuite 类 -
import unittest class suiteTest(unittest.TestCase): def setUp(self): self.a = 10 self.b = 20 def testadd(self): """Add""" result = self.a+self.b self.assertTrue(result == 100) def testsub(self): """sub""" result = self.a-self.b self.assertTrue(result == -10) def suite(): suite = unittest.TestSuite() ## suite.addTest (simpleTest3("testadd")) ## suite.addTest (simpleTest3("testsub")) suite.addTest(unittest.makeSuite(simpleTest3)) return suite if __name__ == '__main__': runner = unittest.TextTestRunner() test_suite = suite() runner.run (test_suite)
您可以通过取消注释具有 makeSuite() 方法的行和注释语句来试验 addTest() 方法。
测试加载器类
unittest 包具有 TestLoader 类,用于从类和模块创建测试套件。默认情况下,当调用unittest.main(0方法时,会自动创建unittest.defaultTestLoader实例。但是,显式实例可以自定义某些属性。
在以下代码中,使用 TestLoader 对象将两个类的测试收集到一个 List 中。
import unittest testList = [Test1, Test2] testLoad = unittest.TestLoader() TestList = [] for testCase in testList: testSuite = testLoad.loadTestsFromTestCase(testCase) TestList.append(testSuite) newSuite = unittest.TestSuite(TestList) runner = unittest.TextTestRunner() runner.run(newSuite)
下表显示了 TestLoader 类中的方法列表 -
先生编号 | 方法及说明 |
---|---|
1 | 从测试用例加载测试() 返回 TestCase 类中包含的所有测试用例的套件 |
2 | 从模块加载测试() 返回给定模块中包含的所有测试用例的套件。 |
3 | 从名称加载测试() 返回一组给定字符串说明符的所有测试用例。 |
4 | 发现() 通过从指定起始目录递归到子目录查找所有测试模块,并返回一个 TestSuite 对象 |
测试结果类
此类用于编译有关已成功的测试和已失败的测试的信息。TestResult 对象存储一组测试的结果。TestRunner.run() 方法返回 TestResult 实例。
TestResult 实例具有以下属性 -
先生。 | 属性及描述 |
---|---|
1 | 错误 包含 TestCase 实例的 2 元组和保存格式化回溯的字符串的列表。每个元组代表一个引发意外异常的测试。 |
2 | 失败 包含 TestCase 实例的 2 元组和保存格式化回溯的字符串的列表。每个元组代表一个测试,其中使用 TestCase.assert*() 方法显式发出失败信号。 |
3 | 跳过 包含 TestCase 实例的 2 元组和包含跳过测试原因的字符串的列表。 |
4 | 那是成功的() 如果到目前为止运行的所有测试都已通过,则返回 True,否则返回 False。 |
5 | 停止() 可以调用此方法来发出信号,表明正在运行的测试集应该中止。 |
6 | 开始测试运行() 在执行任何测试之前调用一次。 |
7 | 停止测试运行() 所有测试执行后调用一次。 |
8 | 测试运行 迄今为止运行的测试总数。 |
9 | 缓冲 如果设置为 true,sys.stdout和sys.stderr将在调用startTest()和stopTest()之间进行缓冲。 |
以下代码执行测试套件 -
if __name__ == '__main__': runner = unittest.TextTestRunner() test_suite = suite() result = runner.run (test_suite) print "---- START OF TEST RESULTS" print result print "result::errors" print result.errors print "result::failures" print result.failures print "result::skipped" print result.skipped print "result::successful" print result.wasSuccessful() print "result::test-run" print result.testsRun print "---- END OF TEST RESULTS"
执行时的代码显示以下输出 -
---- START OF TEST RESULTS <unittest.runner.TextTestResult run = 2 errors = 0 failures = 1> result::errors [] result::failures [(<__main__.suiteTest testMethod = testadd>, 'Traceback (most recent call last):\n File "test3.py", line 10, in testadd\n self.assertTrue(result == 100)\nAssert ionError: False is not true\n')] result::skipped [] result::successful False result::test-run 2 ---- END OF TEST RESULTS