用例和数据的分离处理、数据驱动和生成报告,操作excel

数据驱动DDT  data driven testing 可以实现测试数据与测试脚本的分离,通过DDT将测试数据加载到脚本中;采用数据驱动设计模式使一组数据对应一个测试用例,用例自动加载生成。
    在执行测试用例时,有些用例只是参数不一致。比如登录操作。
    如果用例重复去写操作过程会增加代码量
    对应这种多组数据的测试用例,可以用数据驱动设计模式,一组数据对应一个测试用例,用例自动加载生成

数据驱动框架的意义
    代码复用率高。同一测试逻辑编写一次,可以被多条测试数据复用,提高测试代码的复用率,同时可以提高测试脚本的编写效率;
    异常排查效率高。测试框架依据测试数据,每条数据生成一条测试用例,用例执行过程相互隔离,在其中一条失败的情况下,不会影响其他的测试用例;
    代码的可维护性高。清晰的测试框架,提高可读性,提高代码的可维护性。

不用数据驱动:
- 1,非常容易理解,
- 2,自动化测试人员要求不高
- 3,方便调试。

用数据驱动:
- 1, 数据和测试的逻辑分离,
- 2, 方便维护
- 3, 节省很多的代码,测试函数可以复用的。

用数据驱动的劣势:
1, 当测试逻辑不太通用,测试步骤区别比较大,
2, 数据驱动调试的时候定位问题比较困难。

什么样的项目适合做自动化测试? 面试题
- 需求稳定,不会频繁变更。(项目初期不太适合)
- 研发和测试周期长,需要频繁执行回归测试 (搞活动。)
- 需要在多种平台上重复运行相同测试的场景
- 某些测试项目通过手工测试无法实现,或者手工成本太高
- 被测软件的开发较为规范,能够保证系统的可测试行 

- 编程语言的数据对象  转化成 通用的数据格式 ==> 序列化操作
- 通用的 转化成 编程语言数据对象  ==> 反序列化 操作


安装数据驱动测试DDT
安装命令pip install ddt

import unittest

import ddt    # 提前安装好ddt

li = list(range(100))


@ddt.ddt()    # ()可省略
class RegisterTestCase(unittest.TestCase):

    @ddt.data(*li)    # 拆包传参,把li列表的元素逐个遍历并赋值给case,@ddt.data(11,22,3,44)里面传几个数据就生成几条测试用例
    def test_register(self, case):
        print(f'{case}')


if __name__ == '__main__':
    unittest.main()
# 要测试的功能封装的类
li = ['py01','py02','py03']
class Register():
    def __init__(self, user, pwd1, pwd2):
        self.user = user
        self.pwd1 = pwd1
        self.pwd2 = pwd2
        # self.register_check()

    def register_check(self):
        if self.user not in li:
            if 6<=len(self.pwd1) and 6<=len(self.pwd2):
                if self.pwd1 == self.pwd2:
                    li.append(self.user)
                    return {'code':1,'msg':'注册成功'}
                else:
                    return {'code':0,'msg':'两次密码不一致'}
            elif len(self.pwd1) < 6 or len(self.pwd2)< 6:
                return {'code':0,'msg':'密码长度不符合要求'}
        else:
            return {'code':0,'msg':'已被注册'}
import unittest

import ddt    # 提前安装好ddt


from unittestcase.register import Register
# 测试用例
data_case = [{'data':('py05','123456','123456'),'exceped':{'code':1,'msg':'注册成功'}},
             {'data':('py01','123456','123456'),'exceped':{'code':0,'msg':'已被注册'}},
             {'data':('py08','123457','123456'),'exceped':{'code':0,'msg':'两次密码不一致'}},
             {'data':('py06','12345','123456'),'exceped':{'code':0,'msg':'密码长度不符合要求'}}]

@ddt.ddt()
class RegisterTest(unittest.TestCase):

    @ddt.data(*data_case)
    def test_register(self,case):
        data = case['data']
        exceped = case['exceped']
        res = Register(*data).register_check()
        self.assertEqual(res,exceped)

if __name__ == '__main__':
    unittest.main()


 python操作excel
提前安装第三方openpyxl,命令:pip install openpyxl

import openpyxl
'''
先在桌面或D盘创建xlsx格式的Excel的文件;只能xlsx格式,xls格式不行
把文件复制到pycharm
excel操作的三大对象:
工作簿:一个excel文件会被加载为一个工作簿对象Workbook
工作表:excel文件中每个sheet表会被加载成一个工作表对象sheet
单元格:工作表中的每个格子就是一个表格对象cell

'''
# 第一步,将excel文件加载到一个工作簿对象中
wb = openpyxl.load_workbook(r'D:\0423\pycharm\py40_0424\unittestcase\testopenpyxl.xlsx')    # 在同一目录下可以直接文件名,否则写完整的路径
# print(wb)    <openpyxl.workbook.workbook.Workbook object at 0x0000021BCB5C9D00>

# 第二步,选择文件中的表单
sheet = wb['login']
# print(sheet)    <Worksheet "login">

# 第三步,读取内容
# res = sheet.cell(row = 1,column = 1)    # 可以缩写(1,1)
# # print(res)    <Cell 'login'.A1>
# print(res.value)    # 111

# 写入操作有四步,前两步一样
# 第三步,写入内容,当前这一步为止只是写在工作簿中,还需要第四步保存才能写到excel表里
sheet.cell(row = 1,column = 1,value = '九八')    # 可以省略写(1,1,'九八')

# 第四步,保存,括号内为保存后文件的完整路径和文件名;如果只写文件名默认保存到当前目录
# 注意写入的时候文件不能处于打开状态,否则报错没有权限
# PermissionError: [Errno 13] Permission denied: 'D:\\0423\\pycharm\\py40_0424\\unittestcase\\testopenpyxl.xlsx'
wb.save(r'D:\0423\pycharm\py40_0424\unittestcase\testopenpyxl.xlsx')

一次性读取一个工作表内所有内容

import openpyxl

wb = openpyxl.load_workbook(r'D:\0423\pycharm\py40_0424\unittestcase\testopenpyxl.xlsx')

sheet = wb['register']

# res = sheet.rows

# print(res)    <generator object Worksheet._cells_by_row at 0x000001DE4DB64580>

res = list(sheet.rows)
# print(res)    [(<Cell 'register'.A1>, <Cell 'register'.B1>, <Cell 'register'.C1>, <Cell 'register'.D1>, <Cell 'register'.E1>),
# (<Cell 'register'.A2>, <Cell 'register'.B2>, <Cell 'register'.C2>, <Cell 'register'.D2>, <Cell 'register'.E2>),
# (<Cell 'register'.A3>, <Cell 'register'.B3>, <Cell 'register'.C3>,<Cell 'register'.D3>, <Cell 'register'.E3>),
# (<Cell 'register'.A4>, <Cell 'register'.B4>, <Cell 'register'.C4>, <Cell 'register'.D4>, <Cell 'register'.E4>)]
for i in res:
#     print(i)
# (<Cell 'register'.A1>, <Cell 'register'.B1>, <Cell 'register'.C1>, <Cell 'register'.D1>, <Cell 'register'.E1>)
# (<Cell 'register'.A2>, <Cell 'register'.B2>, <Cell 'register'.C2>, <Cell 'register'.D2>, <Cell 'register'.E2>)
# (<Cell 'register'.A3>, <Cell 'register'.B3>, <Cell 'register'.C3>, <Cell 'register'.D3>, <Cell 'register'.E3>)
# (<Cell 'register'.A4>, <Cell 'register'.B4>, <Cell 'register'.C4>, <Cell 'register'.D4>, <Cell 'register'.E4>)
    for j in i:
        print(j.value,end='  ')
    print()
# 11  12  13  14  15
# 21  22  23  24  25
# 31  32  33  34  35  
# 41  42  43  44  45


推荐使用方法 

import openpyxl


def handle_excel(file_name, sheet_name):
    wb = openpyxl.load_workbook(file_name)
    sh = wb[sheet_name]
    values = list(sh.values)
    wb.close()
    title, *data = values  # title= values[0],data = values[1:]
    new_value = [dict(zip(title, i)) for i in data]  # 列表推导式
    return new_value


print(handle_excel(r'D:\0423\pycharm\py40_0424\py0528\cases.xlsx', 'login'))
# [{'case_id': 1, 'username': 'yuz', 'password': 123, 'expect': '{"code": "200", "msg": "登录成功"}'},
# {'case_id': 2, 'username': 'yuz', 'password': 1234, 'expect': '{"code": "300", "msg": "用户名或密码错误"}'}, 
# {'case_id': 3, 'username': 'wyuz', 'password': 123, 'expect': '{"code": "300", "msg": "用户名或密码错误"}'}, 
# {'case_id': 4, 'username': 'yuz', 'password': None, 'expect': '{"code": "400", "msg": "用户名或密码为空"}'}, 
# {'case_id': 5, 'username': None, 'password': 123, 'expect': '{"code": "400", "msg": "用户名或密码为空"}'}]

import openpyxl
wb = openpyxl.load_workbook(r'D:\0423\pycharm\py40_0424\unittestcase\testopenpyxl.xlsx')
sheet = wb['login']
res = list(sheet.rows)
res1= res[0]
res1_list = []
test_cases = []
for i in res1:    # 遍历第一行内容
    res1_list.append(i.value)
for j in res[1:]:    # 遍历第二行之后的内容
    res2_list = []
    for v in j:
        res2_list.append(v.value)    # 用个列表接收遍历出来的每行的数据
        res_zip = dict(zip(res1_list,res2_list))    # 每遍历出来一行就和第一行做聚合打包,转换字典格式,作为一条测试用例
    test_cases.append(res_zip)    # 聚合打包的每个字典就是一条测试用例,作为元素加入一个列表内
print(test_cases)    # 注意此时data和exceped的值都是字符串类型,需要使用eval()方法
# [{'case_id': 1, 'title': '注册成功', 'data': "('py05','123456','123456')", 'exceped': "{'code':1,'msg':'注册成功'}"}, 
# {'case_id': 2, 'title': '已被注册', 'data': "('py01','123456','123456')", 'exceped': "{'code':0,'msg':'已被注册'}"}, 
# {'case_id': 3, 'title': '两次密码不一致', 'data': "('py08','123457','123456')", 'exceped': "{'code':0,'msg':'两次密码不一致'}"}, 
# {'case_id': 4, 'title': '密码长度不符合要求', 'data': "('py06','12345','123456')", 'exceped': "{'code':0,'msg':'密码长度不符合要求'}"}]

从excel读取用例数据(封装成类),并测试功能函数
1、定义测试用例类和测试方法(模块名字和测试用例方法以test开头)
    导入unittest、ddt、要读取的excel、被测的功能函数
2、去excel中读取数据(事先定义好类和方法去读取数据)
3、通过DDT实现数据驱动
4、实现测试用例类内部逻辑
    unittest是通过执行测试用例是否出现断言异常来评判通过与否;如果使用try...except进行AssertionError断言异常的捕获,需raise抛出异常,否则检测不到该异常均认为通过
5、新建run.py模块,导入unittest和要生成报告的第三方模块,加载套件,执行测试用例

import openpyxl
class OperationCases:
    def __init__(self,file_name,sheet_name):    # 初始化,文件完整路径和表单名
        self.file_name = file_name
        self.sheet_name = sheet_name

    def write_cases_exceped(self,row,column,value):    # 写入内容,需传参行列和值
        wb = openpyxl.load_workbook(self.file_name)
        sheet = wb[self.sheet_name]
        sheet.cell(row,column,value)
        wb.save(self.file_name)

    def read_cases(self):    # 读取所有内容
        wb = openpyxl.load_workbook(self.file_name)
        sheet = wb[self.sheet_name]
        res = list(sheet.rows)
        res1= res[0]
        # res1_list = []
        test_cases = []
        # for i in res1:    # 遍历第一行内容
        #     res1_list.append(i.value)
        res1_list = [i.value for i in res1]    # 列表推导式代替for循环及定义的res1_list = []
        for j in res[1:]:    # 遍历第二行之后的内容
            res2_list = []
            for v in j:     # 可用列表推导式 res2_list = [v.value for v in j]
                res2_list.append(v.value)    # 用个列表接收遍历出来的每行的数据
                res_zip = dict(zip(res1_list,res2_list))    # 每遍历出来一行就和第一行做聚合打包,转换字典格式,作为一条测试用例
            test_cases.append(res_zip)    # 聚合打包的每个字典就是一条测试用例,作为元素加入一个列表内
        return test_cases

    @staticmethod
    def f_case(tese_case,data,exceped):    # 使用eval()方法识别字符串中的字典,元组等;也可定义成对象方法,首先去调用read_cases(self)方法
        for a in range(len(tese_case)):
            tese_case[a][data] = eval(tese_case[a][data])
            tese_case[a][exceped] = eval(tese_case[a][exceped])
        return tese_case
        # [{'case_id': 1, 'title': '注册成功', 'data': "('py05','123456','123456')", 'exceped': "{'code':1,'msg':'注册成功'}"},
        # {'case_id': 2, 'title': '已被注册', 'data': "('py01','123456','123456')", 'exceped': "{'code':0,'msg':'已被注册'}"},
        # {'case_id': 3, 'title': '两次密码不一致', 'data': "('py08','123457','123456')", 'exceped': "{'code':0,'msg':'两次密码不一致'}"},
        # {'case_id': 4, 'title': '密码长度不符合要求', 'data': "('py06','12345','123456')", 'exceped': "{'code':0,'msg':'密码长度不符合要求'}"}]

import unittest
import ddt
from unittestcase.register import Register
@ddt.ddt()
class RegisterTest(unittest.TestCase):
    tc0524 = OperationCases(r'D:\0423\pycharm\py40_0424\unittestcase\testopenpyxl.xlsx', 'login')  # 创建对象,放在测试用例类里方便管理
    res = tc0524.read_cases()
    print(tc0524.f_case(res, 'data', 'exceped'))  # 调用f_case()方法把字符串格式转换去掉引号
    @ddt.data(*res)    # 解包
    def test_register(self,case):
        data = case['data']    # 推荐在此处使用eval()方法
        exceped = case['exceped']    # 推荐在此处使用eval()方法
        res1 = Register(*data).register_check()
        self.assertEqual(res1,exceped)    # 断言

if __name__ == '__main__':
    unittest.main()

实际项目代码如下:
测试用例

import unittest
from unittestcase import myddt
from py0524.test_py0524 import OperationCases
from unittestcase.register import Register


@myddt.ddt()
class RegisterTest(unittest.TestCase):
    excel = OperationCases(r'D:\0423\pycharm\py40_0424\unittestcase\testopenpyxl.xlsx', 'login')
    res = excel.read_cases()
    excel.f_case(res, 'data', 'exceped')

    @myddt.data(*res)
    def test_register(self, case):
        data = case['data']
        exp = case['exceped']
        title = case['title']
        id = case['case_id'] + 1
        res1 = Register(*data).register_check()
        print(f'实际结果{res1}')    # print输出的内容会体现在报告里
        print(f'预期结果{exp}')
        try:
            self.assertEqual(res1, exp)
        except AssertionError as a:
            self.excel.write_cases_exceped(id, 5, '失败')
            self.excel.write_cases_exceped(id,6,str(res1))    # res1是字典格式,往excel里只能写字符串格式,所以需要转换下格式
            print(f'"{title}":测试用例执行失败,信息如下:{a}')
            raise
        else:
            self.excel.write_cases_exceped(id, 5, '通过')
            print(f'"{title}":测试用例执行通过')

run文件  项目启动文件

import unittest
from unittestreport import TestRunner

suite1 = unittest.defaultTestLoader.discover(r'D:\0423\pycharm\py40_0424\py0525')
runner = TestRunner(suite1)
runner.run()

生成报告
unittestreport  兼容beautifulreport主题格式
beautifulreport
HTMLTestRunner  很少用
unittest内置TextTestRunner报告  基本不用
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值