单元测试
unittest
- 测试用例
- TestCase:使用用例类
- 测试用例中test开头的方法就是一个测试用例
- 测试套件
- TestSuite:创建测试套件
- 添加用例到套件的方法:单条 类 模块 目录
- 测试运行程序
- HTMLTestRunnerNew 创建运行程序,可以生成测试报告
- 测试环境的初始化和恢复
- setUP:每条用例执行前执行
- TearDown:每条用例执行之后执行
openpyxl
- load_workbook:打开一个工作薄(传入1个excle文件)
- wb[表单名]:选择表单
- 表单对象.cell(row,column)
ddt
-
ddt
- 装测试用例类上@ddt
-
data
-测试用例的方法上@data(*cases)
logging
- 创建日志收集器对象
- 设置收集筹等级
- 创建日志输出渠道(设置等级)
- 输出到文件(设置等级)
- 创建日志输出格式
-把输出格式添加到输出渠道上
- 将输出渠道添加到收集器上
1.根据功能函数在Excle表格里设计测试用例
2.创建测试用例类test_cases.py
(1)定义测试用例类
(2)定义测试方法
(3)通过ddt生成测试用例数据
3.创建测试套件runtest.py
(1)创建测试套件
(2)加载测试套件
(3)创建测试程序运行测试套件
4.生成测试报告zy_report
单元测试和接口测试最重要的就是测试用例的设计和编写
# ==========================
# @time:2019/11/3 17:04
# @Author:coco
# @File:mylogger.py
# @software:PyCharm
# ============================
import logging
class MyLogger(object):
@classmethod
def create_logger(cls):
"""创建日志收集器"""
# 创建一个日志收集器
my_log = logging.getLogger("my_log999")
# 设置日志收集器的收集等级
my_log.setLevel("DEBUG")
# 设置日志输出的格式
formater = logging.Formatter('%(asctime)s - [%(filename)s-->line:%(lineno)d] - %(levelname)s: %(message)s')
# 创建一个输出导控制台的日志输出渠道
sh = logging.StreamHandler()
sh.setLevel("DEBUG")
# 设置输出导控制台的格式
sh.setFormatter(formater)
# 将输出渠道添加到日志收集器中
my_log.addHandler(sh)
# 创建一个输出导文件的渠道
fh = logging.FileHandler(filename="test.log", encoding='utf8')
fh.setLevel('DEBUG')
# 设置输出导文件的日志格式
fh.setFormatter(formater)
# 将输出渠道添加到日志收集器中
my_log.addHandler(fh)
return my_log
log = MyLogger.create_logger()
if __name__ == '__main__':
log = MyLogger.create_logger()
log.info("hello")
# ==========================
# @time:2019/10/30 21:27
# @Author:coco
# @File:read_excle02.py
# @software:PyCharm
# ============================
import openpyxl
class CaseData:
"""测试用例数据类,专门用来存放数据的"""
pass
class ReadExcle(object):
def __init__(self, filename, sheetname):
self.filename = filename
self.sheetname = sheetname
def open(self):
"""打开工作表和表单"""
self.wb = openpyxl.load_workbook(self.filename)
self.sh = self.wb[self.sheetname]
def read_data(self):
"""读取数据的方法"""
# 打开工作薄和表单
self.open()
# 将表单中的内容,按行获取所有的格子
rows = list(self.sh.rows)
# 创建一个空列表,用例存放所有的用例数据
cases = []
# 获取表头,放到一个列表中
title = [c.value for c in rows[0]]
# 获取除表头以外的其他行中的数据
for r in rows[1:]:
# 每遍历一行,创建一个列表,用例存放该行的数据
data = [c.value for c in r]
# 将表头和该行的数据进行聚合打包,转换字典
case_data = dict(zip(title, data))
# 将该行的用例数据加入到cases这个列表中
cases.append(case_data)
# 关闭工作薄
self.wb.close()
# 将读取好的数据返回出去
return cases
def read_data_obj(self):
"""读取数据的方法,数据返回的是列表嵌套对象的形式"""
# 打开工作薄和表单
self.open()
# 将表单中的内容,按行获取所有的格子
rows = list(self.sh.rows)
# 创建一个空列表,用例存放所有的用例数据
cases = []
# 通过列表推导式获取表头,放到一个列表中
title = [c.value for c in rows[0]]
# 获取除表头以外的其他行中的数据
for r in rows[1:]:
# 通过列表推导式,获取该行的数据,放到一个列表中,该行的数据
data = [c.value for c in r]
# 创建一个用例数据对象
case = CaseData()
# 将表头和该行的数据进行聚合打包,然后进行遍历
for i in zip(title, data):
# 通过反射机制将表头设为对象属性,对应值设为对象的属性值
setattr(case, i[0], i[1])
# 将该行的用例数据加入到cases这个列表中
cases.append(case)
# 关闭工作薄
self.wb.close()
# 将读取好的数据返回出去
return cases
def write_data(self, row, column, value):
"""写入数据"""
# 打开工作薄和表单
self.open()
# 写入内容
self.sh.cell(row=row, column=column, value=value)
# 保存文件
self.wb.save(self.filename)
# 关闭工作薄
self.wb.close()
if __name__ == '__main__':
read = ReadExcle('cases.xlsx', 'register')
# 读取
# data = read.read_data_obj()
# print(data)
# read.write_data(2, 4, '通过')
# read.write_data(3, 4, '未通过')
# ==========================
# @time:2019/10/28 20:10
# @Author:coco
# @File:register.py
# @software:PyCharm
# ============================
users = [{'user': 'python23', 'password': '1123456'}]
def register(username, password1, passwrod2):
# 注册功能
for user in users: # 遍历出所有的账号,判断账号是否存在
if username == user['user']:
# 账号存在
return {"code": 0, "msg": "该账号已存在"}
else:
if password1 != passwrod2:
# 两次密码不一致
return {"code": 0, "msg": "两次密码不一致"}
else:
# 账号不存在,密码重复,判断账号密码长度是否在6-18位之间
if 6 <= len(username) >= 6 and 6 <= len(password1) <= 18:
# 注册账号
users.append({'user': username, 'password': passwrod2})
return {"code": 1, "msg": "注册成功"}
else:
# 账号密码长度不对,注册失败
return {"code": 0, "msg": "账号和密码必须在6-18位之间"}
# ==========================
# @time:2019/11/3 11:14
# @Author:coco
# @File:run_test.py
# @software:PyCharm
# ============================
import unittest
import test_cases
from HTMLTestRunnerNew import HTMLTestRunner
from mylogger import log, MyLogger
# 不要重复创建日志收集器,创建多个收集器,日志会重复收集
# log2 = MyLogger.create_logger()
# log3 = MyLogger.create_logger()
# 创建测试套件
suite = unittest.TestSuite()
log.info('测试套件创建成功')
# 加载用例到套件
loader = unittest.TestLoader()
suite.addTest(loader.loadTestsFromModule(test_cases))
log.info('测试套件加载完毕')
with open('zy_report.html', 'wb') as fb:
# 创建测试运行程序
runner = HTMLTestRunner(stream=fb,
title='我的测试报告',
description='案例运用',
tester='coco')
# 执行测试用例
runner.run(suite)
log.info('所有的用例执行完毕')
# ==========================
# @time:2019/10/29 20:01
# @Author:coco
# @File:test_cases.py
# @software:PyCharm
# ============================
import time
import unittest
from mylogger import log
from register import register
from read_excle02 import ReadExcle
from py23_15day.test_project.ddt import ddt, data
"""
ddt:能够实现数据驱动,通过用例用例数据,自动生成测试用例
自动遍历数据,自动生成测试用例
每遍历一条用例数据,会录成一个参数,传到生成的用例中去
"""
@ddt # ddt去装饰测试用例类,自动去遍历用例数据
class RegisterTestCase(unittest.TestCase):
excle = ReadExcle("cases.xlsx", 'register')
cases = excle.read_data_obj()
# data去装饰测试用例类,自动去遍历用例数据,加*对列表拆包,有多少条数据,就会生成多少条测试用例,每生成一条测试用例,就会当做参数传递到测试用例的方法里
@data(*cases)
def test_register(self, case):
# 第一步 准备用例数据
# 获取用例的行号
row = case.case_id + 1
# 获取预期结果
excepted = eval(case.excepted)
# 获取用例入参
data = eval(case.data)
# 第二步 调用功能函数
res = register(*data)
# 第三步 比对预期结果和实际结果
try:
self.assertEqual(excepted, res)
except AssertionError as e:
log.info("用例:{},执行未通过".format(case.title))
self.excle.write_data(row=row, column=5, value='未通过')
log.error(e)
raise e
else:
log.info("用例:{},执行通过".format(case.title))
self.excle.write_data(row=row, column=5, value='通过')