自动生成接口用例demo

注:为了节省自己的工作效率,让自己有更多的时间来摸鱼学习提升自己,因此用django写了一个自动生成接口测试用例的demo

自动生成接口测试用例demo

1.设计流程图

在这里插入图片描述

2.接口用例模板(冒烟,功能,压测)

(见最终生成效果)

3.原始数据,psotman导出的json包

在这里插入图片描述

4.涉及到的技术(边写边学习边记录)

Django(视图层、模型层、模板层,登录,注册)
Pytest测试框架(操作yaml、操作ini文件、数据驱动、测试报告生成等)
openpyxl(写入、保存、合并单元格、样式)
html+css(前端能力不强,因此用的比较low)
其它(上传、下载文件,相对绝对路径,django邮件发送,加密,文件操作,jsonpath使用、多层for循环等)

Get到的新的方法:
判断类型的方法:isinstances(obj,类型)
BASE_DIR方法:
Mac终端程序在后台运行方法:命令后 加上 &

获取目录下文件列表:
file = os.listdir(目录)

删除文件:os.remove(file)
删除目录:os.removedirs(空目录)

5.django目录

在这里插入图片描述

6. 代码

6.1生成表格的代码
import os
from pathlib import Path
from openpyxl import Workbook
from openpyxl.styles import Alignment, Font, colors, Border, Side, PatternFill
from openpyxl.utils import get_column_letter, column_index_from_string
from json_data import read_file

'''
postman 导出的文件命名格式:项目名_服务名
'''


class AutoCase:
    def __init__(self):
        self.BASE_DIR = Path(__file__).parent  # BSAE_DIR目录
        self.smoke_title = ['服务', '接口名称', '测试内容', '用例描述', '预期结果', '实际结果', '测试结果', '接口地址']  # 冒烟表表头
        self.function_title = ['服务名', '接口名', 'URL', '接口测试类型', '测试内容', '预期结果', '实际结果', '测试结果', '备注']  # 功能表表头
        self.stress_title = ['名称', '策略', '', '平均事务响应时间', 'TPS', '错误百分比', '测试URL', '描述', '是否新增', '结果']  # 压测表表头
        # self.test_cases = ["无该字段", "为null", '为\"\"', "为\'\'", "为#", '为**类型']  # 参数校验数据
        self.test_cases = ["无该字段","为null",'\"\"',"\'\'","#","为**类型"]	  # 参数校验数据
        self.test_cases_header = ["business1"]  # header校验数据
        self.business = ["business1"]  # 业务逻辑校验
        self.wb = Workbook()  # 创建文件
        self.ws = self.wb.active  # 激活sheet表
        self.file_path = os.path.join(self.BASE_DIR,
                                      'AI教师-魔拍v1.6(指令拍)_ok-student-middle.postman_collection.json')  # 文件路径
        print(self.file_path)
        self.read_file = eval(read_file(self.file_path))  # 读取文件
        self.item = self.read_file['item']  # item数据
        self.p_name_s_name = self.read_file['info']['name']  # 项目名-服务名
        self.p_name = self.p_name_s_name.split('_')[0]  # 项目名
        self.s_name = self.p_name_s_name.split('_')[1]  # 服务名
        self.interface_count = len(self.read_file['item'])  # 接口数
        self.font_style = Font(name=None, sz=None, b=None, i=None, charset=None,  # 字体样式
                               u=None, strike=None, color=None, scheme=None, family=None, size=12,
                               bold=None, italic=None, strikethrough=None, underline=None,
                               vertAlign=None, outline=None, shadow=None, condense=None,
                               extend=None)
        self.alignment_style = Alignment(wrapText=True)  # 默认样式
        self.alignment_center_style = Alignment(horizontal='center', vertical='center', wrapText=True)  # 居中样式
        self.border_style = Border(left=Side(style='medium', color=colors.BLACK),
                                   right=Side(style='medium', color=colors.BLACK),
                                   top=Side(style='medium', color=colors.BLACK),
                                   bottom=Side(style='medium'))  # 边框样式
        self.title_fill_style = PatternFill("solid", fgColor="0099ff")  # 表头的颜色-蓝色
        self.result_fill_style = PatternFill('solid', fgColor="00cc00")  # 测试结果列颜色-绿色
        self.test_type_fill_style = PatternFill("solid", fgColor="c0c0c0")  # 接口测试类型颜色-灰色

    # 接口名称列表
    def i_names(self):
        i_names = []
        for i in range(self.interface_count):
            i_name = self.read_file['item'][i]["name"]
            i_names.append(i_name)
        return i_names

    # URL列表
    def urls(self):
        urls = []
        for url in range(self.interface_count):
            urls.append(self.read_file['item'][url]['request']['url']['raw'])
        return urls

    # 创建冒烟表
    def create_smoke_sheet(self):
        ws_smoke = self.wb.create_sheet('冒烟', 0)
        ws_smoke.append(self.smoke_title)
        # 表头样式
        for row in ws_smoke.iter_rows(min_row=1, max_row=1, min_col=1, max_col=8):
            for cell in row:
                cell.font = self.font_style
                cell.alignment = self.alignment_center_style
                cell.border = self.border_style
                cell.fill = self.title_fill_style

        # 服务名(先填写再合并单元格)
        ws_smoke['A2'] = self.s_name
        ws_smoke['A2'].font = self.font_style
        ws_smoke.merge_cells('A2:A%s' % (self.interface_count + 1))
        ws_smoke['A2'].alignment = self.alignment_center_style

        # 接口名称列
        i_count = 0
        for col in ws_smoke.iter_cols(min_col=2, max_col=2, min_row=2, max_row=self.interface_count + 1):
            for cell in col:
                if i_count > len(self.i_names()) - 1:
                    print("i_count计数 不能大于 i_names索引长度")
                    break
                cell.value = self.i_names()[i_count].split('_')[0]  # 接口名 _ 分割后的第一个
                cell.font = self.font_style
                cell.alignment = self.alignment_style
                i_count += 1

        # 测试内容列
        for col in ws_smoke.iter_cols(min_col=3, max_col=3, min_row=2, max_row=self.interface_count + 1):
            for cell in col:
                cell.font = self.font_style
                cell.value = '正常情况'

        # 用例描述列
        for col in ws_smoke.iter_cols(min_col=4, max_col=4, min_row=2, max_row=self.interface_count + 1):
            for cell in col:
                cell.value = '冒烟'
                cell.font = self.font_style

        # 预期结果列
        for col in ws_smoke.iter_cols(min_col=5, max_col=5, min_row=2, max_row=self.interface_count + 1):
            for cell in col:
                cell.value = '"code":0'
                cell.font = self.font_style

        # 实际结果列
        for col in ws_smoke.iter_cols(min_col=6, max_col=6, min_row=2, max_row=self.interface_count + 1):
            for cell in col:
                cell.value = '"code":0'
                cell.font = self.font_style

        # 测试结果列
        for col in ws_smoke.iter_cols(min_col=7, max_col=7, min_row=2, max_row=self.interface_count + 1):
            for cell in col:
                cell.value = 'pass'
                cell.font = self.font_style
                cell.fill = self.result_fill_style

        u_count = 0
        for col in ws_smoke.iter_cols(min_col=8, max_col=8, min_row=2, max_row=self.interface_count + 1):
            for cell in col:
                if u_count > len(self.urls()) - 1:
                    print('u_count 必须小于 urls 的最大索引数')
                    break
                cell.value = self.urls()[u_count]
                cell.font = self.font_style
                cell.alignment = self.alignment_style
                u_count += 1

        # 设置行号、列宽
        print('冒烟表-最大行数:%s' % ws_smoke.max_row)
        print('冒烟表-最大列数:%s' % ws_smoke.max_column)
        # 行高
        for i in range(1, ws_smoke.max_row + 1):
            if i == 1:
                ws_smoke.row_dimensions[i].height = 30
            else:
                ws_smoke.row_dimensions[i].height = 15

        # 列宽
        for i in range(1, ws_smoke.max_column + 1):
            # 根据数字得到字母
            letter = get_column_letter(i)
            if letter == 'H':
                ws_smoke.column_dimensions[letter].width = 50
            else:
                ws_smoke.column_dimensions[letter].width = 20

        # 给整个表格添加边框
        for row in ws_smoke.iter_rows(min_row=ws_smoke.min_row, max_row=ws_smoke.max_row,
                                      min_col=ws_smoke.min_column, max_col=ws_smoke.max_column):
            for cell in row:
                cell.border = self.border_style

        return ws_smoke

    # 创建功能表
    def create_function_sheet(self):
        ws_function = self.wb.create_sheet('功能', 1)
        ws_function.append(self.function_title)

        # 表头样式
        for row in ws_function.iter_rows(min_row=1, max_row=1, min_col=1, max_col=9):
            for cell in row:
                cell.alignment = self.alignment_center_style
                cell.font = self.font_style
                cell.fill = self.title_fill_style

        # 测试内容(代码的位置不能变)
        keys_list = []  # 每个接口中所有的key

        for i in range(self.interface_count):
            if self.item[i]['request']['method'] == "GET":
                print("第%s个接口-%s 的请求方法是%s" % (
                    i + 1, self.read_file['item'][i]["name"], self.item[i]['request']['method']))
                query = self.item[i]['request']['url']['query']
                key_list = []
                for j in range(len(query)):
                    key = query[j]['key']
                    key_list.append(key)
                keys_list.append(key_list)  # 加入到keys_list中

            elif self.item[i]['request']['method'] == "POST":
                print(
                    "第%s个接口-%s的请求方法是%s" % (i + 1, self.read_file['item'][i]["name"], self.item[i]['request']['method']))
                raw = eval(self.item[i]['request']['body']['raw'])
                # print(raw)
                key_list = []
                for key, value in raw.items():
                    # 将参数中为列表的,
                    if isinstance(value, list):
                        # print(value)
                        key_list.append(key)
                        for value_dict in value:
                            # print("value_dict", value_dict)
                            if not isinstance(value_dict, dict):
                                print("参数%s列表中的元素,type不是字典,跳过" % value_dict)
                                continue
                            for value_dirt_k in value_dict:
                                # print(value_dirt_k)
                                key_list.append(value_dirt_k)
                    else:
                        key_list.append(key)

                keys_list.append(key_list)

            else:
                raise Exception("暂不支持该请求%s" % self.item[i]['request']['method'])
        print("功能表-test_cases:%s" % self.test_cases)
        print("功能表-keys_list:%s" % keys_list)

        # 正常情况+参数与参数校验数据组合+header校验+业务逻辑校验
        key_case_list = []
        for i in range(len(keys_list)):
            key_case_list.append("正常情况")
            for j in range(len(keys_list[i])):
                # print(keys_list[i][j])
                for c in range(len(self.test_cases)):
                    test_case_result = keys_list[i][j] + self.test_cases[c]
                    # print(test_case_result)
                    key_case_list.append(test_case_result)
            # 小列表循环结束加上header校验,业务校验
            for header in self.test_cases_header:
                key_case_list.append(header)

            for business in self.business:
                key_case_list.append(business)

        print("功能表-key_case_list:", key_case_list)

        # 合并单元格
        ps_list = []  # 参数开始行号
        pe_list = []  # 参数结束行号
        hs_list = []  # header开始行号
        he_list = []  # header结束行号
        bs_list = []  # 业务开始行号
        be_list = []  # 业务结束行号
        i = 2
        n = 0
        for key_l in keys_list:
            # 参数校验
            '''插入数据'''
            ws_function.merge_cells("D%s:D%s" % (i, i + len(key_l) * len(self.test_cases)))
            ws_function.cell(column=4, row=i).value = "参数校验"

            '''样式'''
            ws_function['D%s' % i].alignment = self.alignment_center_style
            ws_function['D%s' % i].fill = self.test_type_fill_style

            '''起始行号'''
            ps_list.append(i)
            pe_list.append(i + len(key_l) * len(self.test_cases))

            '''往下移位置'''
            i += len(key_l) * len(self.test_cases) + 1  # 新的行作为header校验的起始行

            # header校验
            '''插入数据'''
            if len(self.test_cases_header) > 0:  # 有header时,才添加header
                ws_function.merge_cells("D%s:D%s" % (i, i + len(self.test_cases_header) - 1))
                ws_function.cell(column=4, row=i).value = "header校验"

            '''样式'''
            ws_function['D%s' % i].alignment = self.alignment_center_style
            ws_function['D%s' % i].fill = self.test_type_fill_style

            '''起始行号'''
            hs_list.append(i)
            he_list.append(i+len(self.test_cases_header) - 1)

            '''向下移位置'''
            i += len(self.test_cases_header)  # 新的行作为业务校验的起始行

            # 接口业务逻辑校验
            '''插入数据'''
            if len(self.business) > 0:  # 有业务逻辑校验时,才添加业务校验数据
                ws_function.merge_cells("D{}:D{}".format(i, i + len(self.business)-1))
                ws_function.cell(column=4, row=i).value = "接口业务逻辑校验"

            '''样式'''
            ws_function['D%s' % i].alignment = self.alignment_center_style
            ws_function['D%s' % i].fill = self.test_type_fill_style

            '''起始行号'''
            bs_list.append(i)
            be_list.append(i+len(self.business) - 1)

            '''结束循环,没进入下一个接口单元'''
            i += len(self.business)  # i变为下一个参数校验起始行

            g = len(self.business) + len(self.test_cases_header) + \
                len(key_l)*len(self.test_cases)+1  # 每个单元格的cell行号长度
            # print(g)

            '''以下合并其他的单元格'''
            merge_srow_index = i - g  # 接口名、URL等的开始行号
            # print(merge_srow_index)

            # 接口名
            '''合并单元格'''
            ws_function.merge_cells("B{}:B{}".format(merge_srow_index, i-1))

            '''插入数据'''
            ws_function.cell(merge_srow_index, 2).value = self.i_names()[n].split('_')[0]

            '''样式'''
            ws_function["B%s" % merge_srow_index].alignment = self.alignment_center_style

            # URL
            '''合并单元格'''
            ws_function.merge_cells("C{}:C{}".format(merge_srow_index, i-1))

            '''插入数据'''
            ws_function.cell(merge_srow_index, 3).value = self.urls()[n]

            '''样式'''
            ws_function["C%s" % merge_srow_index].alignment = self.alignment_center_style

            n += 1

        # 服务名
        '''合并单元格'''
        ws_function.merge_cells("A{}:A{}".format(2, ws_function.max_row))

        '''插入数据'''
        ws_function.cell(row=2, column=1, value=self.s_name)

        '''样式'''
        ws_function["A2"].alignment = self.alignment_center_style

        print("功能表-参数校验开始行号%s" % ps_list)
        print("功能表-参数校验结束行号%s" % pe_list)
        print("功能表-header校验开始行号%s" % hs_list)
        print("功能表-header校验结束行号%s" % he_list)
        print("功能表-业务逻辑校验开始行号%s" % bs_list)
        print("功能表-业务逻辑校验结束行号%s" % be_list)

        # 插入测试内容数据
        tc_col_index = column_index_from_string('E')
        print("插入测试内容数据的列号是:", tc_col_index)
        n = 0
        for col in ws_function.iter_cols(min_col=tc_col_index, max_col=tc_col_index,
                                         min_row=2, max_row=len(key_case_list)+1):
            for cell in col:
                cell.value = key_case_list[n]
                n += 1

        # 预期结果

        # 实际结果

        # 测试结果
        for col in ws_function.iter_cols(min_row=2, max_row=ws_function.max_row,
                                         min_col=8, max_col=8):
            for cell in col:
                '''插入数据'''
                cell.value = 'pass'

                '''样式'''
                cell.alignment = self.alignment_center_style
                cell.fill = self.result_fill_style
        # 备注

        # 列宽
        print('功能表-最大行数:%s' % ws_function.max_row)
        print('功能表-最大列数:%s' % ws_function.max_column)
        for i in range(1, ws_function.max_column + 1):
            letter = get_column_letter(i)
            ws_function.column_dimensions[letter].width = 30

        # 行高
        for i in range(1, ws_function.max_row + 1):
            if i == 1:
                ws_function.row_dimensions[i].height = 30
            else:
                ws_function.row_dimensions[i].height = 15

        # 边框
        for row in ws_function.iter_rows(min_row=ws_function.min_row, max_row=ws_function.max_row,
                                         min_col=ws_function.min_column, max_col=ws_function.max_column):
            for cell in row:
                cell.border = self.border_style

        return ws_function

    # 压测表
    def create_stress_sheet(self):

        # 创建压测表
        ws_stress = self.wb.create_sheet('压测', 2)

        # 表头1-服务名
        '''合并'''
        ws_stress['A1'] = '服务名'
        ws_stress.merge_cells('A1:J1')
        '''样式'''
        ws_stress['A1'].alignment = Alignment(horizontal='center', vertical='center')
        ws_stress['A1'].fill = self.test_type_fill_style  # 灰色

        # 表头2
        ws_stress.append(self.stress_title)  # ''用于为占位使用
        ws_stress.merge_cells('B2:C2')
        ws_stress['B2'].alignment = Alignment(horizontal='center')

        # 表头样式
        for row in ws_stress.iter_rows(min_row=2, max_row=2, min_col=1, max_col=10):
            for cell in row:
                cell.alignment = self.alignment_center_style
                cell.font = self.font_style
                cell.fill = self.title_fill_style

        # 名称
        i = 3  # 每次循环移动位置计数
        n = 0  # 累加取URL
        r = 0  # 压测表填写的总行数
        qps_list = []
        for iname in self.i_names():
            if iname.split('_')[1] == '压':  # 压
                if iname.split('_')[2] == '新增':  # 新增
                    r += 3
                    if iname.split('_')[3] == '读':  # 新增-读
                        '''合并单元格'''
                        ws_stress.merge_cells("A{}:A{}".format(i, i + 2))  # 接口名称
                        ws_stress.merge_cells("G{}:G{}".format(i, i + 2))  # 测试URL
                        ws_stress.merge_cells("H{}:H{}".format(i, i + 2))  # 描述
                        ws_stress.merge_cells("I{}:I{}".format(i, i + 2))  # 是否新增

                        '''写入数据'''
                        ws_stress.cell(row=i, column=1).value = iname.split('_')[0] + "(读)"  # 接口名称
                        ws_stress.cell(row=i, column=9).value = "是"  # 是否新增
                        ws_stress.cell(row=i, column=7).value = self.urls()[n].split('?')[0]  # URL

                        '''样式'''
                        ws_stress["A{}".format(i)].alignment = self.alignment_center_style
                        ws_stress["G{}".format(i)].alignment = self.alignment_center_style
                        ws_stress["H{}".format(i)].alignment = self.alignment_center_style
                        ws_stress["I{}".format(i)].alignment = self.alignment_center_style

                        i += 3
                        n += 1
                        qps_list.append('200并发')
                        qps_list.append('250并发')
                        qps_list.append('300并发')
                        print("压-新增-读")
                    else:  # 新增-写
                        '''合并单元格'''
                        ws_stress.merge_cells("A{}:A{}".format(i, i + 2))  # 接口名称
                        ws_stress.merge_cells("G{}:G{}".format(i, i + 2))  # 测试URL
                        ws_stress.merge_cells("H{}:H{}".format(i, i + 2))  # 描述
                        ws_stress.merge_cells("I{}:I{}".format(i, i + 2))  # 是否新增

                        '''写入数据'''
                        ws_stress.cell(row=i, column=1).value = iname.split('_')[0] + "(写)"  # 接口名称
                        ws_stress.cell(row=i, column=9).value = "是"  # 是否新增
                        ws_stress.cell(row=i, column=7).value = self.urls()[n].split('?')[0]  # URL

                        i += 3
                        n += 1
                        qps_list.append('100并发')
                        qps_list.append('150并发')
                        qps_list.append('200并发')
                        print("压-新增-写")
                else:  # 不新增
                    r += 1
                    if iname.split('_')[3] == '读':  # 非新增-读
                        ws_stress.cell(row=i, column=1).value = iname.split('_')[0] + "(读)"  # 接口名称
                        ws_stress.cell(row=i, column=9).value = "否"  # 是否新增
                        ws_stress.cell(row=i, column=7).value = self.urls()[n].split('?')[0]  # URL

                        i += 1
                        n += 1
                        qps_list.append('200并发')
                        print("压-非新增-读")
                    else:  # 非新增-写
                        ws_stress.cell(row=i, column=1).value = iname.split('_')[0] + "(写)"  # 接口名称
                        ws_stress.cell(row=i, column=9).value = "否"  # 是否新增
                        ws_stress.cell(row=i, column=7).value = self.urls()[n].split('?')[0]  # URL

                        i += 1
                        n += 1
                        qps_list.append('100并发')
                        print("压-非新增-写")
            else:  # 不压
                print("压测表—接口%s,不需要压测" % iname)

        # print(qps_list)
        # print(r)

        # 策略-并发
        t = 0
        for col in ws_stress.iter_cols(min_col=2, max_col=2, min_row=3, max_row=len(qps_list)+2):
            for cell in col:
                cell.value = qps_list[t]
                cell.alignment = self.alignment_center_style
                t += 1

        # 测试结果
        for col in ws_stress.iter_cols(min_col=10, max_col=10, min_row=3, max_row=r+2):
            for cell in col:
                cell.value = "pass"
                cell.alignment = self.alignment_center_style
                cell.fill = self.result_fill_style

        # 策略--持续时长
        for col in ws_stress.iter_cols(min_row=3, max_row=3+r - 1,
                                       min_col=3, max_col=3):
            for cell in col:
                cell.value = "持续5min"
                cell.alignment = self.alignment_center_style

        # 平均事务响应时间

        # TPS

        # 错误百分比

        # 测试URL

        # 描述

        # 是否新增

        # 列宽
        print('压测表-最大行数:%s' % ws_stress.max_row)
        print('压测表-最大列数:%s' % ws_stress.max_column)
        for i in range(1, ws_stress.max_column + 1):
            letter = get_column_letter(i)
            if i == 7:
                ws_stress.column_dimensions[letter].width = 40
            else:
                ws_stress.column_dimensions[letter].width = 20

        # 行高
        for i in range(1, ws_stress.max_row + 1):
            if i == 1:
                ws_stress.row_dimensions[i].height = 40
            elif i == 2:
                ws_stress.row_dimensions[i].height = 35
            else:
                ws_stress.row_dimensions[i].height = 25

        # 全表基础样式 边框+对齐+字体大小+自动换行
        for row in ws_stress.iter_rows(min_row=ws_stress.min_row, max_row=ws_stress.max_row,
                                       min_col=ws_stress.min_column, max_col=ws_stress.max_column):
            for cell in row:
                cell.border = self.border_style
                cell.alignment = self.alignment_center_style  # 居中样式
                cell.font = self.font_style
        return ws_stress

    # 保存表
    def save_wb(self):
        return self.wb.save(self.p_name + '.xlsx')

    # 主函数
    def main(self):
        # self.wb.remove('Sheet')
        del self.wb['Sheet']  # 删除默认表
        print('接口名称列表:%s' % self.i_names())
        print('接口RUL列表:%s' % self.urls())

        print('-------------------------------------冒烟-------------------------------------')
        self.create_smoke_sheet()
        print('-------------------------------------功能-------------------------------------')
        self.create_function_sheet()
        print('-------------------------------------压测-------------------------------------')
        self.create_stress_sheet()
        print("sheet表名称:%s" % self.wb.sheetnames)
        self.save_wb()


if __name__ == '__main__':
    AutoCase().main()
6.2发送邮件的代码
"""
    这里定义公共的方法
"""
import os
from email.header import make_header
from django.core.mail import EmailMultiAlternatives
from autocase import settings

# 发送邮件方法
def send_email(file_path, recipients, subject, body):

    # 指定django的配置文件,同manage.py
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'autocase.settings')

    # 调多种邮件方式方法,并赋予变量
    msg = EmailMultiAlternatives(subject=subject, body=body, from_email=settings.DEFAULT_FROM_EMAIL, to=recipients)

    # 内容设为html格式类型
    msg.attach_alternative(body, 'text/html')

    # 发送附件
    file = open(file_path, 'rb').read()
    file_name = os.path.basename(file_path)
    print(file_name)
    b_name = make_header(decoded_seq=[(file_name, 'utf-8')]).encode('utf-8')  # 这里传了一个解码序列
    msg.attach(filename=b_name, content=file)

    # 发送邮件
    msg.send()

    # 判断发送是否成功
    if msg.send():
        print("邮件发送成功")
    else:
        raise Exception("邮件发送失败")



7.效果

7.1页面效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.2用例表格效果

冒烟表
在这里插入图片描述
功能表
在这里插入图片描述
压测表
在这里插入图片描述

8.结合pytest,来进行自动运行用例

8.1 pytest目录

在这里插入图片描述
目录简要说明:

  • data:存放测试数据相关
  • reoprt:存放allure生成的测试报告
  • temp:存放生成allure测试报告的基础json文件
  • tests:存放运行用例脚本
  • utuils:存放自己封装的各种工具类或方法

9.设计思路:

请添加图片描述

10.效果图

页面效果

在这里插入图片描述

运行结果效果

表格:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

11.踩坑

1.定义空列表时,用 l = list(),不用l = [],这样能避免一些不必要的错误

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值