本文是对Python自带的unittest框架学习笔记的入门篇,简单介绍PyUnit框架的基础知识。
- #!/usr/bin/python
- #coding=utf-8
- class Widget:
- def __init__(self, size = (40,40)):
- self._size = size
- def getSize(self):
- return self._size
- def resize(self, width, height):
- if width < 0 or height < 0:
- raise ValueError, "illegal size"
- self._size = (width, height)
- def __del__(self):
- print "widget dispose now"
测试用例类
- #!/usr/bin/python
- #coding=utf-8
- from widget import Widget
- import unittest
- import sys
- reload(sys)
- sys.setdefaultencoding('utf8')
- class WidgetTestCase(unittest.TestCase):
- def setUp(self):
- print "setUp"
- self.widget = Widget()
- def tearDown(self):
- print "tearDown"
- self.widget = None
- def testSize(self):
- self.assertEqual(self.widget.getSize(), (40,40))
- def testResize(self):
- self.widget.resize(30,30)
- self.assertEqual(self.widget.getSize(), (30,30))
- if __name__ == "__main__":
- unittest.main()
1)用import语句引入unittest模块。
2)让所有执行测试的类都继承于TestCase类,这个类包含了对目标类进行测试的方法的集合。
3)在setUp()方法中进行测试前的初始化工作,并在tearDown()方法中执行测试后的清除工作,setUp()和tearDown()都是TestCase类中定义的方法。
4)在testSize()中调用assertEqual()方法,对Widget类中getSize()方法的返回值和预期值进行比较,确保两者是相等的,assertEqual()也是TestCase类中定义的方法。
5)提供名为suite()的全局方法,PyUnit在执行测试的过程调用suit()方法来确定有多少个测试用例需要被执行,可以将TestSuite看成是包含所有测试用例的一个容器。
6)在创建TestCase子类的实例时必须给出测试方法的名称,来为PyUnit测试框架指明运行该测试用例时究竟应该调用测试类中的哪个方法。
7)相关的测试用例称为一个测试用例集,在PyUnit中是用TestSuite类来表示的。PyUnit测试框架允许在单元测试代码中定义一个名为suite()的全局函数,并将其作为整个单元测试的入口,PyUnit通过调用它来完成整个测试过程。
8)PyUnit使用TestRunner类作为测试用例的基本执行环境,来驱动整个单元测试过程。我们一般不直接使用TestRunner类,而是使用其子类TextTestRunner来完成测试,并将测试结果以文本方式显示出来。
- runner = unittest.TextTestRunner()
- runner.run(suite())
默认情况下,TextTestRunner将结果输出到sys.stderr上,但如果在创建TextTestRunner类实例时将一个文件对象传递给了构造函数,则输出结果将被重定向到该文件中。
- logFile = open(test_log_path, "w")
- runner = unittest.TextTestRunner(logFile)
- runner.run(suite())
几个注意的地方:
1)对于每一个test**的测试方法,PyUnit都会为其单独执行一遍完整的测试流程,即从setUp到tearDown,两个test**方法之间实际上是独立的。
2)对于测试用例集,我们也可以直接定义一个TestSuite的子类,并在其初始化方法(__init__)中完成所有测试用例的添加,这样只需要在suite()方法中返回该类的一个实例就可以了。
- class WidgetTestSuite(unittest.TestSuite):
- def __init__(self):
- unittest.TestSuite.__init__(self, map(WidgetTestCase,
- ("testSize",
- "testResize")))
- def suite():
- return WidgetTestSuite()
如果用于测试类中所有测试方法都以test开头,我们甚至可以用PyUnit模块提供的makeSuite()方法来构造一个TestSuite:
- def suite():
- return unittest.makeSuite(WidgetTestCase, "test")
这样,相对应的可以用:
- if __name__ == "__main__":
- unittest.main(defaultTest = 'suite')
3) PyUnit模块中定义了一个名为main的全局方法,使用它可以很方便地将一个单元测试模块变成可以直接运行的测试脚本,main()方法使用TestLoader类来搜索所有包含在该模块中的测试方法,并自动执行它们。如果都是以test开头来命名所有的测试方法,那就只需要在测试模块的最后加入如下几行代码即可:
- if __name__ == "__main__":
- unittest.main()
4) 测试类WidgetTestCase中的所有测试方法都将被自动执行,但如果只想执行testSize()方法,可以使用如下命令:
- python test1.py WidgetTestCase.testSize