- 单元测试框架教程
- 单元测试框架 - 首页
- 单元测试框架 - 概述
- 单元测试框架 - 框架
- 单元测试框架 - API
- 单元测试框架 - 断言
- 单元测试框架 - 测试发现
- 单元测试框架 - 跳过测试
- 单元测试框架 - 异常测试
- 单元测试框架 - 时间测试
- 单元测试框架 - Unittest2
- 单元测试框架 - 信号处理
- 单元测试框架 - Doctest
- 单元测试框架 - Doctest API
- 单元测试框架 - Py.test 模块
- Nose 测试 - 框架
- Nose 测试 - 工具
- 单元测试框架资源
- 单元测试框架 - 快速指南
- 单元测试框架 - 资源
- 单元测试框架 - 讨论
单元测试框架 - API
本章讨论 unittest 模块中定义的类和方法。此模块中有五个主要的类。
TestCase 类
此类的对象表示最小的可测试单元。它包含测试例程,并提供用于准备每个例程以及之后清理的钩子。
TestCase 类中定义了以下方法:
| 序号 | 方法及描述 |
|---|---|
| 1 | setUp() 用于准备测试夹具的方法。在调用测试方法之前立即调用。 |
| 2 | tearDown() 在测试方法被调用并记录结果后立即调用的方法。即使测试方法引发异常,也会调用此方法。 |
| 3 | setUpClass() 在单个类中的测试运行之前调用的类方法。 |
| 4 | tearDownClass() 在单个类中的测试运行之后调用的类方法。 |
| 5 | run(result = None) 运行测试,并将结果收集到作为 result 传递的测试结果对象中。 |
| 6 | skipTest(reason) 在测试方法或 setUp() 中调用此方法将跳过当前测试。 |
| 7 | debug() 运行测试但不收集结果。 |
| 8 | shortDescription() 返回测试的一行描述。 |
夹具
可以在 TestCase 类中编写许多测试。这些测试方法可能需要数据库连接、临时文件或其他需要初始化的资源。这些称为夹具。TestCase 包含一个特殊的钩子来配置和清理测试所需的任何夹具。要配置夹具,请覆盖 setUp()。要进行清理,请覆盖 tearDown()。
在以下示例中,在 TestCase 类中编写了两个测试。它们测试两个值的加法和减法的结果。setup() 方法根据每个测试的 shortDescription() 初始化参数。teardown() 方法将在每个测试结束时执行。
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()
TestSuite 类
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 | addTest() 在测试套件中添加测试方法。 |
| 2 | addTests() 从多个 TestCase 类中添加测试。 |
| 3 | run() 运行与此套件关联的测试,并将结果收集到测试结果对象中 |
| 4 | debug() 运行与此套件关联的测试,但不收集结果。 |
| 5 | countTestCases() 返回此测试对象表示的测试数量 |
以下示例显示了如何使用 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() 方法。
TestLoader 类
unittest 包具有 TestLoader 类,用于从类和模块创建测试套件。默认情况下,当调用 unittest.main(0 方法时,会自动创建 unittest.defaultTestLoader 实例。但是,显式实例允许自定义某些属性。
在以下代码中,使用 TestLoader 对象将来自两个类的测试收集到列表中。
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 | loadTestsFromTestCase() 返回 TestCase 类中包含的所有测试用例的套件 |
| 2 | loadTestsFromModule() 返回给定模块中包含的所有测试用例的套件。 |
| 3 | loadTestsFromName() 给定字符串说明符,返回所有测试用例的套件。 |
| 4 | discover() 通过从指定的起始目录递归进入子目录来查找所有测试模块,并返回 TestSuite 对象 |
TestResult 类
此类用于编译有关已成功测试和遇到失败的测试的信息。TestResult 对象存储一组测试的结果。TestRunner.run() 方法会返回 TestResult 实例。
TestResult 实例具有以下属性:
| 序号 | 属性及描述 |
|---|---|
| 1 | Errors 包含 TestCase 实例和保存格式化回溯的字符串的 2 元组的列表。每个元组表示引发意外异常的测试。 |
| 2 | Failures 包含 TestCase 实例和保存格式化回溯的字符串的 2 元组的列表。每个元组表示使用 TestCase.assert*() 方法明确发出失败信号的测试。 |
| 3 | Skipped 包含 TestCase 实例和保存跳过测试原因的字符串的 2 元组的列表。 |
| 4 | wasSuccessful() 如果迄今为止运行的所有测试都已通过,则返回 True,否则返回 False。 |
| 5 | stop() 可以调用此方法来发出正在运行的测试集应中止的信号。 |
| 6 | startTestRun() 在执行任何测试之前调用一次。 |
| 7 | stopTestRun() 在执行所有测试后调用一次。 |
| 8 | testsRun 迄今为止运行的测试总数。 |
| 9 | Buffer 如果设置为 true,则在调用 startTest() 和 stopTest() 之间,sys.stdout 和 sys.stderr 将被缓冲。 |
以下代码执行测试套件:
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