关于python的测试框架,目前比较流行的有unittest、pytest、nosetest。
unittest提供了test cases、test suites、test fixtures、test runner相关的类,让测试更加明确、方便、可控。使用unittest编写用例,必须遵守以下规则:
1.测试文件必须先import unittest
2.测试类必须继承unittest.TestCase
3.测试方法必须以“test_”开头
4.测试类必须要有unittest.main()方法
下面以unittest单元测试框架介绍
unittest
在Python中进行单元测试需要用到自动单元测试框架PyUnit,Python2.1及其以后的版本都将PyUnit作为一个标准模块(即python的unittest模块)。测试最基本的原理是比较预期结果是否与实际执行结果相同,如果相同则测试成功,否则测试失败。
软件测试中最基本的组成单元式测试用例(test case),PyUnit使用TestCase类来表示测试用例,并要求所有用于执行测试的类都必须从该类继承。TestCase子类实现的测试代码应该是自包含的(self contained),即测试用例既可以单独运行,也可以和其它测试用例构成集合共同运行。
>>>import unittest
>>>dir(unittest)
['FunctionTestCase','TestCase', 'TestLoader', 'TestProgram', 'TestResult', 'TestSuite','TextTestRunner', '_TextTestResult', '_WritelnDecorator', '__all__','__author__', '__builtins__', '__doc__', '__email__', '__file__', '__metaclass__','__name__', '__unittest', '__version__', '_makeLoader', '_strclass','defaultTestLoader', 'findTestCases', 'getTestCaseNames', 'main', 'makeSuite','os', 'sys', 'time', 'traceback', 'types']
pyunit是借由以下概念支持单元测试的:
测试固件(test fixture),测试固件是指运行测试前的准备工作和运行测试后的清理工作。例如,创建临时或代理数据库、目录,或者启动服务进程。
测试用例(test case),测试用例是最小的测试单元,检查特定的输入会产生预期的结果。PyUnit提供一个测试用例几类TestCase,继承基类可以创建新的测试用例。
TestCase类在PyUnit测试框架中被视为测试单元的运行实体,Python程序员可以通过它派生自定义的测试过程与方法(测试单元),利用Command和Composite设计模式,多个TestCase还可以组合成测试用例集合。当自定义一个测试类时(此类继承unittest模块中的TestCase基类,通过这种继承方式,此类成为unittest自动化测试框架中的一个单元测试实例),PyUnit测试框架在运行一个测试用例时,TestCase子类定义的setUp()、run()和tearDown()方法被依次执行,最简单的测试用例只需要覆盖run()方法来执行特定的测试代码就可以了。
>>> dir(unittest.TestCase)
['_TestCase__exc_info', '__call__', '__class__', '__delattr__','__dict__', '__doc__', '__getattribute__', '__hash__', '__init__','__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__','__setattr__', '__str__', '__weakref__', 'assertAlmostEqual','assertAlmostEquals', 'assertEqual', 'assertEquals', 'assertFalse','assertNotAlmostEqual', 'assertNotAlmostEquals', 'assertNotEqual','assertNotEquals', 'assertRaises', 'assertTrue', 'assert_', 'countTestCases','debug', 'defaultTestResult', 'fail', 'failIf', 'failIfAlmostEqual','failIfEqual', 'failUnless', 'failUnlessAlmostEqual', 'failUnlessEqual','failUnlessRaises', 'failureException', 'id', 'run', 'setUp','shortDescription', 'tearDown']
>>>
TestCase类中常用的函数或方法有:
setUp:进行测试前的初始化工作。
tearDown:执行测试后的清除工作。
self.assertEqual(value1,
value2, failedinfo):断言value1 == value2
self.assertTrue(, failedinfo)
self.assertFalse(, failedinfo):断言value为真。
self.assertRaises(ValueError, self.widget.resize, -1, -1):断言肯定发生异常,如果没发生异常,则为测试失败。参数1为异常,参数2为抛出异常的调用对象,其余参数为传递给可调用对象的参数。
一个完整的单元测试框架如下
import unittest
class TestDemo(unittest.TestCase):
def setUp(self):
print('set up')
def tearDown(self):
print('tear down')
def test_case_B(self):
print('run B')
def test_case_A(self):
print('run A')
def test_case_C(self):
print('run C')
if __name__ == '__main__':
unittest.main()
这是一种是通过unittest.main()来启动所需测试的测试模块。
完整的单元测试很少只执行一个测试用例,开发人员通常需要编写多个测试用例才能对某一软件功能进行比较完成的测试,这些相关的测试用例称为一个测试用例集,在PyUnit中是用TestSuite类来表示的。
测试集(test suit),测试集是测试用例的集合,同时也可以是其他测试集的结合,或者是测试用例和测试集的混合集合,用于批量执行测试用例。
if __name__ == '__main__':
#添加Suite
defSuite():
#定义一个单元测试容器
suiteTest = unittest.TestSuite()
suiteTest.addTest(TestDemo("test_case_A"))
suiteTest.addTest(TestDemo("test_case_B"))
suiteTest.addTest(TestDemo("test_case_C"))
return suiteTest
#运行测试用例
runner.run(Suite())
PyUinit测试框架允许Python程序员在单元测试代码中定义一个名为suite的全局对象,并将其作为整个单元测试的入口,PyUnit通过调用它来完成整个测试过程。
TestSuite类实现测试套件功能,可以整合单独的测试用例或者其他测试套件。执行测试套件,测试套件中所有的测试用例和子测试套件都会被执行。
>>>dir(unittest.TestSuite)
['__call__','__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__','__hash__', '__init__', '__iter__', '__module__', '__new__', '__reduce__','__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__','addTest', 'addTests', 'countTestCases', 'debug', 'run']
>>>
执行器(test runner),执行器用来执行测试用例,并且把测试结果呈现给用户。执行器可以使用图形界面,文本界面,甚至特殊值来显示测试结果。最常用的运行器是TextTestRunner,它是TestRunner的子类,以文字方式运行测试报告并报告结果。执行器提供一个方法run(),该方法接受TestCase或者TestSuite对象作为参数,并且返回TestResult结果对象。PyUnit提供一个使用TextTestRunner执行器的例子,该例子汇报默认的标准错误流测试结果。
>>>dir(unittest.TextTestRunner)
['__class__','__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__','__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__','__setattr__', '__str__', '__weakref__', '_makeResult', 'run']
>>>
在一组测试用例中,包含共同需要处理的代码,被称为测试固件。这些代码可能是在测试之前需要进行的初始化工作,或测试结束之后需要做的代码清理工作等,这是由setUp和tearDown函数来实现的,在测试执行的时候,setUp将首先被执行,当方法通过后,不管后面的测试是否通过,都会执行tearDown函数,一个测试方法执行时,这两个函数都会被执行(即一个Case有多个测试用例时,函数会被执行多次)。可使用下列方法对setUp和tearDown函数进行替换,如下
@classmethod
def setUpClass(cls):
print('set up')
@classmethod
def tearDownClass(cls):
print('tear down')
这样,上述两个函数都只会运行一次。
可用同时包含setUpClass和setUp函数,测试用例运行时先运行前者。