unittest单元测试框架不仅可以适用于单元测试,还可以将其用于自动化测试用例的开发与执行,该测试框架可组织执行测试用例,并且提供了丰富的断言方法,判断测试用例是否通过,最终生成测试结果。
1.Unitest单元测试
对于单元测试,需要设置预先条件,对比预期结果和实际结果。
unittest库提供了testSuite、testCase、testRunner、Skip等,具体有以下作用:
1.1 testSuite 测试套件
testSuite = unittest.TestSuite() testSuite.addTest()
1.2 testCase 测试用例
测试用例是一个完整的测试流程,包括测试前准备环境的搭建(setUp),执行测试代码(run),测试后环境的还原(tearDown),以及判断测试得到的实际结果和预期结果是否相等决定的的assert*():
assertEqual(a,b,[msg='测试失败时打印的信息']):断言a和b是否相等,相等则测试用例通过。
assertNotEqual(a,b,[msg='测试失败时打印的信息']):断言a和b是否相等,不相等则测试用例通过。
assertTrue(x,[msg='测试失败时打印的信息']):断言x是否True,是True则测试用例通过。
assertFalse(x,[msg='测试失败时打印的信息']):断言x是否False,是False则测试用例通过。
assertIs(a,b,[msg='测试失败时打印的信息']):断言a是否是b,是则测试用例通过。
assertNotIs(a,b,[msg='测试失败时打印的信息']):断言a是否是b,不是则测试用例通过。
assertIsNone(x,[msg='测试失败时打印的信息']):断言x是否None,是None则测试用例通过。
assertIsNotNone(x,[msg='测试失败时打印的信息']):断言x是否None,不是None则测试用例通过。
assertIn(a,b,[msg='测试失败时打印的信息']):断言a是否在b中,在b中则测试用例通过。
assertNotIn(a,b,[msg='测试失败时打印的信息']):断言a是否在b中,不在b中则测试用例通过。
assertIsInstance(a,b,[msg='测试失败时打印的信息']):断言a是是b的一个实例,是则测试用例通过。
assertNotIsInstance(a,b,[msg='测试失败时打印的信息']):断言a是是b的一个实例,不是则测试用例通过。
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls):
print('测试开始啦...')
@classmethod
def tearDownClass(cls):
print('测试结束啦...')
def setUp(self):
print('setUp...')
def tearDown(self):
print('setDown...')
def test_testcase(self):
self.assertEqual(1, 0)
1.3 testRunner 执行测试并输出结果
unittest.main()
执行测试并在控制台输出测试结果:
unittest.TextTestRunner(verbosity=2).run(testSuite)
执行测试并生成HTML测试报告[HTMLTestReportCN.py:http://download.csdn.net/download/u013511989/9991831 ]:
fileName = 'Report/Milito_Test'+str(time.time()).replace('.','')+'.html'
f = open(fileName, 'wb')
runner = HTMLTestReportCN.HTMLTestRunner(stream=f, title='测试报告', description='测试报告')
runner.run(testSuite)
f.close()
1.4 Skip 装饰器
当运行用例时,有些用例如果不想执行,可用装饰器暂时屏蔽该条测试用例。一种常见的用法就是比如说想调试某一个测试用例,想先屏蔽其他用例就可以用装饰器屏蔽。
@unittest.skip(reason): skip(reason)装饰器:无条件跳过装饰的测试,并说明跳过测试的原因。
@unittest.skipIf(reason): skipIf(condition,reason)装饰器:条件为真时,跳过装饰的测试,并说明跳过测试的原因。
@unittest.skipUnless(reason): skipUnless(condition,reason)装饰器:条件为假时,跳过装饰的测试,并说明跳过测试的原因。
@unittest.expectedFailure(): expectedFailure()测试标记为失败。
2.将unitTest用于自动化测试
python可以编写Web页面和APP自动化测试脚本[之前的文章],对于编写的自动化测试脚本进行以下操作,即可将unitTest用于自动化测试。
2.1 将自动化测试脚本划分为合适的用例,放在testCase之中。
2.2 每一个自动化测试脚本的用例执行完之后,添加断言,判断测试是否成功。
2.3 每一个自动化测试脚本本身可能存在一些问题,用try: *** except Exception as e: *** 抛出异常,并在except中添加失败的断言。
2.4 如果自动化测试用例是否执行需要遵照某种规律,则设置变量进行标记,使用skip装饰器对变量进行判断,以跳过不执行的用例。
2.5 如果unitTest需要传参数,则调用UnittestWithParam,并对unitTest+自动化测试 脚本进行以下修改。
# -*- coding:utf-8 -*-
# UnittestWithParam.py
import unittest
class ParametrizedTestCase(unittest.TestCase):
""" TestCase classes that want to be parametrized should
inherit from this class.
"""
def __init__(self, methodName='runTest', param=None):
super(ParametrizedTestCase, self).__init__(methodName)
self.param = param
@staticmethod
def parametrize(testcase_klass, param=None):
""" Create a suite containing all tests taken from the given
subclass, passing them the parameter 'param'.
"""
testloader = unittest.TestLoader()
testnames = testloader.getTestCaseNames(testcase_klass)
suite = unittest.TestSuite()
for name in testnames:
suite.addTest(testcase_klass(name, param=param))
return suite
# -*- coding:utf-8 -*-
import unittest
import HTMLTestReportCN
##用法-testcase
class TestOne(ParametrizedTestCase):
def setUp(self):
self.num = 9
print("开始")
def tearDown(self):
print("完成")
def test_something(self):
self.assertEqual(self.param, self.num)
def test_something_else(self):
self.assertEqual(self.param, self.num)
##用法-测试
def main():
suite = unittest.TestSuite()
suite.addTest(ParametrizedTestCase.parametrize(TestOne, param=None))
suite.addTest(ParametrizedTestCase.parametrize(TestOne, param=13))
# 控制台输出结果
unittest.TextTestRunner(verbosity=2).run(suite)
# 生成测试报告
"""
fileName = 'unitTestParam.html'
f = open(fileName, 'wb')
runner = HTMLTestReportCN.HTMLTestRunner(stream=f, title='UT', description='测试报告')
runner.run(suite)
f.close()
"""
if __name__=="__main__":
main()
3.总结
使用python+unitTest进行自动化测试,是对自动化测试脚本进行更深度思考的机会,可以让测试脚本更接近高内聚低耦合的状态,提升测试人员的工作效率。