一、单元测试简介 1.什么是单元测试 针对程序模块来进行正确性检验的测试工作。程序模块的最小单元是单个程序、函数、方法等,包括基类(超类)、抽象类,或者派生类。
2.为什么要做单元测试 (1)确保代码质量 (2)改善代码设计,难以测试的代码一般是设计不够简洁的代码 (3)保障重构不会引入新问题,以函数为单位进行重构的时候,只需要重新跑测试就基本可以保证重构没有引入新问题。
二、单元测试实战 1.登录函数详细设计
……
【登录函数】
参数:
用户名、密码,用户名和密码不能为空
返回值:
用户名:不能为空,如果为空,返回{“code”: 0, “msg”: “所有的参数不能为空”};
密码:不能为空,如果为空,返回{“code”: 0, “msg”: “所有的参数不能为空”};
用户名错误:{“code”: 0, “msg”: “账号或密码不正确”}
密码错误:{“code”: 0, “msg”: “账号或密码不正确”}
登录成功:{“code”: 1, “msg”: “登录成功”}
……
2.设计测试用例
3.使用普通方法测试代码 login.py
def login_check(username=None,password=None): """ 登录校验 :param username: 账号 :param password: 密码 :return: 字典类型的提示信息 """ # 如果用户名或密码错误,提示:{"code": 0, "msg": "账号或密码不正确"} if username != 'lemon' or password != '123456': return {"code": 0, "msg": "账号或密码不正确!"} if not username or not password: return {"code": 0, "msg": "所有的参数不能为空!"} if username == 'lemon' and password == '123456': return {"code": 1, "msg": "登录成功!"} return {"code": 1, "msg": "未知错误,请联系管理员"} if __name__ == '__main__': try: # 断定 login_check('lemon','123456') 的返回值是{'code': 1, 'msg': '登录成功'} assert login_check('lemon','123456') == {'code': 1, 'msg': '登录成功'} assert login_check('lemon','123456789') == {'code': 0, 'msg': '账号或密码不正确'} assert login_check('leomasasdf','123456') == {'code': 0, 'msg': '账号或密码不正确'} assert login_check('','123456') == {'code': 0, 'msg': '所有的参数不能为空'} assert login_check('lemon','') == {'code': 0, 'msg': '所有的参数不能为空'} assert login_check('asdfasdf','123456454676') == {'code': 0, 'msg': '账号或密码不正确'} except: print('测试不通过') raise ValueError('测试失败') else: print('恭喜你,全部测试通过')4.使用单元测试方法测试代码 单元测试框架: unittest——python内置的单元测试框架 test_login.py
import unittest from user.login import login_check class LoginTestCase(unittest.TestCase): def setUp(self) -> None: """这里可以放前置条件,初始化""" print('前置条件在每个test_开头的方法运行前都会运行') def test_login_success(self): """正确的用户名,正确的密码,返回值是{"code": 1, "msg": "登录成功"}""" expected = {"code": 1, "msg": "登录成功"} act = login_check(username='lemon',password='123456') self.assertEqual(expected,act,msg='预期结果和实际结果不相等,测试失败。') def test_login_user_error(self): """验证错误的用户名,是否返回{"code": 0, "msg": "账号或密码不正确"}""" self.assertEqual({"code": 0, "msg": "账号或密码不正确"},login_check(username='lemon222',password='123456')) def test_login_pwd_error(self): pass def test_login_username_is_none(self): pass def test_login_pwd_is_none(self): pass def tearDown(self) -> None: """这里可以放后置条件,清理工作""" print('在每个test_开头的方法运行后都会运行') if __name__ == '__main__': unittest.main()三、单元测试总结 1.单元测试框架unittest的架构 TestCase:一个testcase的实例就是一个测试用例 TestSuite:多个测试用例集合在一起 TestLoader:用来加载TestCase到TestSuite中 TextTestRunner:用来执行测试用例 fixture:包括setUp和tearDown两个方法,分别用于创建测试环境和销毁测试环境
2.使用unittest做单元测试的步骤 导入unittest模块,为了使用unittest框架(pytest框架) 导入被测对象 login_check 创建一个测试类,并继承unittest.TestCase 重写setUp和tearDown方法(如果有初始化条件和结束条件)(可选) 以方法的形式写测试项:方法名以test_开头 使用unittest.main()运行测试用例(运行所有以test_开头的方法,运行顺序按字母顺序执行)
3.常用断言函数说明
四、测试用例的管理 1.常用函数说明
2.用例管理的步骤
五、如何生成测试报告 1.纯文本测试报告
2.html类型报告 使用BeautifulReport模块生成
完整代码如下:
3.生成报告的三种方法
# 套件 import unittest from BeautifulReport import BeautifulReport from py32_wuji_02day.last_homework import test_register from py32_wuji_02day.last_homework.test_register import RegisterTestCase suite = unittest.TestSuite() # 加载器 loader = unittest.TestLoader() # 用套件 把用例 添加到套件中。 # 方法1. 从类中加载所有case # suite.addTest(loader.loadTestsFromTestCase(RegisterTestCase)) # 方法2. 从模块中加载所有case # suite.addTest(loader.loadTestsFromModule(test_register)) # 方法3. 从文件夹追踪加载所有case suite.addTest(loader.discover(r'C:\Users\10795\PycharmProjects\autotesting\py32_wuji_02day\last_homework')) br = BeautifulReport(suite) br.report('注册测试报告', 'br.html', report_dir='.')