Unittest Framework 简明教程

UnitTest Framework - API

本章讨论 unittest 模块中定义的类和方法。此模块中有五个主要类。

TestCase Class

此类的对象表示最小的可测试单元。它包含测试例程,并提供挂钩以便准备各个例程和清理之后的内容。

TestCase 类中定义了以下方法 −

Sr.No.

Method & Description

1

setUp() 用于准备测试装置的方法。这会在调用测试方法前立即调用

2

tearDown() 在调用测试方法并记录结果后立即调用的方法。即使测试方法引发异常,也会调用此方法,

3

setUpClass() 个人类运行中的测试前调用的类方法。

4

tearDownClass() 个人类运行中的测试后调用的类方法。

5

run(result = None) 运行测试,将结果收集到作为结果传递的测试结果对象中。

6

skipTest(reason) 在测试方法或 setUp() 期间调用此方法将跳过当前测试。

7

debug() 不收集结果地运行测试。

8

shortDescription() 返回测试的一行描述。

Fixtures

一个 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)

Class Fixture

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 Class

Python 的测试框架提供了一种很有用的机制,根据测试用例实例测试的功能对它们进行分组。此机制由 unittest 模块中的 TestSuite 类提供。

创建和运行测试套件包括以下步骤。

Step 1 − 创建 TestSuite 类的实例。

suite = unittest.TestSuite()

Step 2 − 在套件内添加 TestCase 类中的测试。

suite.addTest(testcase class)

Step 3 − 你还可以使用 makeSuite() 方法从一个类添加测试

suite = unittest.makeSuite(test case class)

Step 4 − 个体测试也可以添加到套件中。

suite.addTest(testcaseclass(""testmethod")

Step 5 − 创建 TestTestRunner 类的对象。

runner = unittest.TextTestRunner()

Step 6 − 调用 run() 方法运行套件中的所有测试,将结果收集到测试结果对象中

runner.run (suite)

TestSuite 类中定义了以下方法 −

Sr.No.

Method & Description

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)

可以使用 addTest() 方法,通过取消对包含 makeSuite() 方法的行和注释语句的注释来进行实验。

TestLoader Class

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 类中的方法列表:

Sr.No

Method & Description

1

loadTestsFromTestCase() 返回 TestCase 类中包含的所有测试用例的套件

2

loadTestsFromModule() 返回给定模块中包含的所有测试用例的套件。

3

loadTestsFromName() 根据字符串说明符返回所有测试用例的套件。

4

discover() 通过从指定的起始目录递归到子目录中来查找所有测试模块,并返回一个 TestSuite 对象

TestResult Class

此类用于编译有关已成功测试和已失败测试的信息。TestResult 对象存储一组测试的结果。TestResult 实例由 TestRunner.run() 方法返回。

TestResult 实例具有以下属性:

Sr.No.

Attribute & Description

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, sys.stdoutsys.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