zoukankan      html  css  js  c++  java
  • swagger 自动生成接口测试用例


    ---整体更新一波---
      1.实际工作中,因为要动手输入的地方比较多,自动生成的异常接口用例感觉用处不大,就先去掉了,只保留了正常的;
      2.接口有改动的,如果开发人员没有及时告知或没有详细告知,会增加一些不必要的麻烦,所以增加了文件对比功能;

    目录:
      
    case_generate.py
    import sys
    
    sys.path.append('D:Interface_framework_Beauty')
    
    import requests
    import os
    from common.operation_excel import Write_excel  # 写入excel模块
    from common.logger import Log  # 打印日志模块
    from common.processing_json import write_data  # 写入json文件模块
    from common.difference import diff_excel, diff_json
    from common import read_config
    
    title_list = []
    
    old_excel_path = os.path.abspath(
        os.path.dirname(os.path.dirname(__file__))) + '\case_generate' + '\data_old' + '\demo_api.xlsx'
    excel_path = os.path.abspath(
        os.path.dirname(
            os.path.dirname(__file__))) + '\case_generate' + '\data_new' + '\demo_api.xlsx'  # case path
    old_json_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + '\case_generate' + '\data_old'
    json_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + '\case_generate' + '\data_new'
    
    
    class AnalysisJson:
        """swagger自动生成测试用例"""
    
        def __init__(self, url_json):
            self.url_json = url_json
            r = requests.get(self.url_json + '/v2/api-docs?group=sign-api').json()
            self.title = r['info']['description']
            write_data(r, '{}.json'.format(self.title))
            self.interface_params = {}
            self.log = Log()
            self.row = 2  # 写入excel起始行数
            self.num = 1  # case id
            global title_list, json_path
            if self.check_data(r):
                self.json_path = os.path.abspath(
                    os.path.dirname(
                        os.path.dirname(__file__))) + '\case_generate' + '\data_new' + '\{}_data.json'.format(
                    self.title)  # json file path,执行多个url的情况,区分生成的json文件
            self.data = r['paths']  # paths中的数据是有用的
    
            title_list.append(self.title)
    
        def check_data(self, r):
            """检查返回的数据是否是dict"""
            if not isinstance(r, dict):
                self.log.info('swagger return json error.')
                return False
            else:
                return True
    
        def retrieve_data(self):
            """主函数"""
            global body_name, method
            for k, v in self.data.items():
                method_list = []
                for _k, _v in v.items():
                    interface = {}
                    if not _v['deprecated']:  # 接口是否被弃用
                        method_list.append(_k)
                        api = k  # api地址
                        if len(method_list) > 1:  # api地址下的请求方式不止一个的情况
                            for i in range(len(method_list)):
                                body_name = api.replace('/', '_') + '_' * i  # json文件对应参数名称,excel中body名称
                                method = method_list[-1]  # 请求方式 同一个api地址,不同请求方式
                        else:
                            body_name = api.replace('/', '_')
                            method = _k
                        self.interface_params = self.retrieve_excel(_v, interface, api)
                    else:
                        self.log.info('interface path: {}, case name: {}, is deprecated.'.format(k, _v['description']))
                        break
            if self.interface_params:
                write_data(self.interface_params, self.json_path)  # 参数写入json文件
    
        def retrieve_excel(self, _v, interface, api):
            """解析参数,拼接为dict--准备完成写入excel的数据"""
            parameters = _v.get('parameters')  # 未解析的参数字典
            if not parameters:  # 确保参数字典存在
                parameters = {}
            case_name = _v['summary']  # 接口名称
            tags = _v['tags'][0]  # 标签名称
            params_dict = self.retrieve_params(parameters)  # 处理接口参数,拼成dict形式
            if params_dict and parameters != {}:  # 单个或多个参数
                interface['row_num'] = self.row  # 写入excel时的所在行
                interface['id'] = 'test_' + str(self.num)  # case id
                interface['tags'] = tags  # 标签名称
                interface['name'] = case_name
                _type = 'json'  # 参数获取方式
                interface['method'] = method  # 请求方式
                interface['url'] = self.url_json + api  # 拼接完成接口url
                interface['headers'] = 'yes'  # 是否传header
                interface['body'] = body_name
                interface['type'] = _type
                self.num += 1
                self.row += 1
                self.interface_params[body_name] = params_dict
                self.write_excel(interface, excel_path)  # 参数写入excel
            else:  # 没有参数
                _type = 'data_old'
                interface['name'] = case_name
                interface['row_num'] = self.row
                interface['id'] = 'test_' + str(self.num)
                interface['tags'] = tags
                interface['method'] = method
                interface['url'] = self.url_json + api
                interface['headers'] = 'yes'
                interface['body'] = ''
                interface['type'] = _type
                self.num += 1
                self.row += 1
                self.interface_params[body_name] = params_dict
                self.write_excel(interface, excel_path)
            return self.interface_params
    
        def retrieve_params(self, parameters):
            """处理参数,转为dict"""
            params = ''
            _in = ''
            for each in parameters:
                _in += each.get('in') + '
    '  # 参数传递位置
                params += each.get('name') + '
    '  # 参数
            _in = _in.strip('
    ')
            _in_list = _in.split('
    ')
            params = params.strip('
    ')
            params_list = params.split('
    ')
            del_list = params_list.copy()
            for i in range(len(_in_list)):
                if _in_list[i] == 'header':
                    params_list.remove(del_list[i])  # 只保存在body传的参数
            test_list = params_list.copy()
            params_dict = dict(zip(params_list, test_list))  # 把list转为dict
            return params_dict
    
        def write_excel(self, interface, filename):
            """把dict中的值写入对应的excel行中"""
            wt = Write_excel(filename, self.title)
            try:
                wt.write(interface['row_num'], 1, interface['id'])
                wt.write(interface['row_num'], 2, interface['tags'])
                wt.write(interface['row_num'], 3, interface['name'])
                wt.write(interface['row_num'], 4, interface['method'])
                wt.write(interface['row_num'], 5, interface['url'])
                wt.write(interface['row_num'], 7, interface['headers'])
                wt.write(interface['row_num'], 8, interface['body'])
                wt.write(interface['row_num'], 10, interface['type'])
                self.log.info('Interface case id {},write to excel file successfully!'.format(interface['id']))
            except Exception as e:
                self.log.info('Failure of interface use case to write to excel file! error:{}
    '.format(e))
                return
    
    
    def diff_file():
        """对比文件"""
        global title_list
        for title in title_list:
            diff_excel(old_excel_path, excel_path, title)
            diff_json(os.path.join(old_json_path, '{}_data.json'.format(title)),
                      os.path.join(json_path, '{}_data.json'.format(title)), title)
    
    
    if __name__ == '__main__':
        url = read_config.generate_url.split(',')
        for i in url:
            # url_json = i + '/v2/api-docs?group=sign-api'  # json swagger url地址
            AnalysisJson(i).retrieve_data()
        diff_file()

    difference.py
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Time    : 2019/3/17 21:35
    # @Author  : lixiaofeng
    # @File    : difference.py
    # @Software: PyCharm
    # @desc    : 对比接口excel, json更新
    
    import xlrd, time, difflib, sys, os
    from common.logger import Log, report_path
    
    log = Log()
    
    
    def diff_excel(ori_path, tar_path, sub_name):
        """比较excel文件"""
        success = 0  # 匹配一致数量
        fail = 0  # 匹配不一致数量
        origin_xls = {}  # 存储源xls文件
        target_xls = {}  # 比对的xls文件
        wb_ori = xlrd.open_workbook(ori_path)  # 打开原始文件
        wb_tar = xlrd.open_workbook(tar_path)  # 打开目标文件
        log.info(':【开始比对】...' + '
    ')  # 写入开始时间
    
        try:
            sheet_ori = wb_ori.sheet_by_name(sub_name)
            sheet_tar = wb_tar.sheet_by_name(sub_name)
            if sheet_ori.name == sheet_tar.name:
                # sheet表名
                if sheet_ori.name == sub_name:
                    # 先将数存入dictionary中dictionary(rows:list)
                    # 第一行存储表头
                    # 源表取一行数据与目标表全表进行比对如果表中存在主键可以用主键进行索引
                    # 数据从excel第3行开始
                    for rows in range(1, sheet_ori.nrows):
                        orign_list = sheet_ori.row_values(rows)  # 源表i行数据
                        target_list = sheet_tar.row_values(rows)  # 目标表i行数据
                        origin_xls[rows] = orign_list  # 源表写入字典
                        target_xls[rows] = target_list  # 目标表写入字典
                    if origin_xls[1] == target_xls[1]:
                        log.info('>>>>>>>>>>>>>>>>>>> 表头一致')
                    for ori_num in origin_xls:
                        flag = 'false'  # 判断是否一致标志
                        for tar_num in target_xls:
                            if origin_xls[ori_num] == target_xls[tar_num]:
                                flag = 'true'
                                break  # 如果匹配到结果退出循环
                        if flag == 'true':  # 匹配上结果输出后台日志
                            success += 1
                        else:  # 匹配不上将源表中行记录写入log
                            fail += 1
                            data = origin_xls[ori_num]
                            logstr = '【不一致】row<' + str(ori_num) + '>:' + str(data)
                            log.info(logstr)
                    logstr = '【比对完成】总记录数:{:d}条,一致:{:d}条,不一致:{:d}条'.format(ori_num, success, fail)
                    log.info(logstr)
            else:
                errmsg = '' + sub_name + '】子表名不一致'
                log.info(errmsg)
        except Exception as err:
            log.info(str(err))  # 输出异常
    
    
    # 创建打开文件函数,并按换行符分割内容
    def read_json(filename):
        try:
            with open(filename, 'r') as fileHandle:
                text = fileHandle.read().splitlines()
            return text
        except IOError as e:
            log.error("Read file Error:" + e)
            sys.exit()
    
    
    # 比较两个文件并输出到html文件中
    def diff_json(filename1, filename2, name):
        text1_lines = read_json(filename1)
        text2_lines = read_json(filename2)
        d = difflib.HtmlDiff()
        # context=True时只显示差异的上下文,默认显示5行,由numlines参数控制,context=False显示全文,差异部分颜色高亮,默认为显示全文
        result = d.make_file(text1_lines, text2_lines, filename1, filename2, context=True)
        # 内容保存到result.html文件中
        log.info('json数据比对结果写入html中.')
        with open(os.path.join(report_path, '{}_diff.html'.format(name)), 'w') as result_file:
            result_file.write(result)
    
    
    if __name__ == '__main__':
        for i in ['前台api', '后台api']:
            diff_excel(r'G:Interface_framework_Beautycase_generatedata_olddemo_api.xlsx',
                       'G:Interface_framework_Beautycase_generatedata_newdemo_api.xlsx', '{}'.format(i))
        diff_json('G:Interface_framework_Beautycase_generatedata_old前台api_data.json',
                  'G:Interface_framework_Beautycase_generatedata_new前台api_data.json', '')
    
    

    执行成功后自动生成的 case,因为我使用的是ddt+requests+unittest框架,所以要把case集成到excel中。断言什么的需要手动输入...

    data.json文件。使用的参数值需要手动输入...

    生成的日志文件。从日志文件可以看出,case条数和对应的json参数数量是一致的.

     可以根据生成的对比结果来修改接口数据

    excel文件生成的log对比结果:

     json文件生成的html对比结果:

    各位大大有其他好的方法,欢迎留言一起讨论。

    --------------------假装这里是分割线---------------------

    writeExcel.py 文件
    # coding:utf-8
    from openpyxl import load_workbook
    import openpyxl
    from openpyxl.styles import Font, colors
    
    
    class Write_excel(object):
        """修改excel数据"""
    
        def __init__(self, filename):
            self.filename = filename
            self.wb = load_workbook(self.filename)
            self.ws = self.wb.active  # 激活sheet
    
        def write(self, row_n, col_n, value):
            """写入数据,如(2,3,"hello"),第二行第三列写入数据"hello""""
            ft = Font(color=colors.RED, size=12, bold=True)
            # 判断值为错误时添加字体样式
            if value in ['fail', 'error'] or col_n == 12:
                self.ws.cell(row_n, col_n).font = ft
            if value == 'pass':
                ft = Font(color=colors.GREEN)
                self.ws.cell(row_n, col_n).font = ft
            self.ws.cell(row_n, col_n).value = value
            self.wb.save(self.filename)
    
    
    if __name__ == "__main__":
        # copy_excel("demo_api.xlsx", "test111.xlsx")
        wt = Write_excel("test111.xlsx")
        wt.write(4, 5, "HELLEOP")
        wt.write(4, 6, "HELLEOP")
    processingJson.py 文件
    import json
    from common.logger import Log
    from jsonpath_rw import jsonpath, parse
    
    
    def write_data(res, json_path):
        """把处理后的参数写入json文件"""
        if isinstance(res, dict):
            with open(json_path, 'w', encoding='utf-8') as f:
                json.dump(res, f, indent=4)
                Log().info('Interface Params Total:{} ,write to json file successfully!
    '.format(len(res)))
        else:
            Log().info('{} Params is not dict.
    '.format(write_data.__name__))

     

    logger.py 参考另一篇即可:python logging模块 输出日志和过期清理


    此功能已集成到 EasyTest测试平台 中,欢迎大家体验~~~
  • 相关阅读:
    购物菜单
    数据库
    增删改查
    页面交互
    计算器
    2020.9.21
    团队-团队编程项目中国象棋-项目总结
    团队-团队编程项目作业名称-最终程序
    课后作业-阅读任务-阅读提问-4
    《20171130-构建之法:现代软件工程-阅读笔记》
  • 原文地址:https://www.cnblogs.com/changqing8023/p/9691820.html
Copyright © 2011-2022 走看看