• 第八章 设计zrlog项目接口自动化测试框架(8.5章节)


    感谢大家关注,帮忙分享呦,你们的阅读就是我的动力!!!

    公众号:小李测试随笔

    第八章 设计zrlog项目接口自动化测试框架(8.5章节)

    8.5 zrlog接口测试框架核心层级设计

    8.5.1 建立common核心层并封装base.py文件

    common核心层主要用作存放接口框架中所需要的公共方法,这些公共方法将通过base.py文件进行封装,并供框架中其他类使用。建立common层并封装base.py文件的步骤可以分为三步

    第一步,在zrlog接口自动化项目下新建common包名

    第二步,在common包下新建base.py文件

    第三步,在base.py文件编写公共方法

    # coding=utf-8
    # 导入json库
    import json
    # 导入Template类
    from string import Template
    # 导入re库
    import re
    
    # 根据参数匹配内容
    def find(data):
        # 判断data类型是否为字典
        if isinstance(data, dict):
            # 对象格式化为str
            data = json.dumps(data)
            # 定义正则匹配规则
            pattern = "\\${(.*?)}"
            # 按匹配进行查询,把查询的结果返回
            return re.findall(pattern, data)
    # 进行参数替换
    def relace(ori_data, replace_data):
        # 对象格式化为str
        ori_data = json.dumps(ori_data)
        # 处理字符串的类,实例化并初始化原始字符
        s = Template(ori_data)
        # 使用新的字符,替换
        return s.safe_substitute(replace_data)
    # 根据var,逐层获取json格式的值
    def parse_relation(var,resdata):
        # 判断变量var是否存在
        if not var:
            # 不存在直接返回resdata内容
            return resdata
        else:
            # 存在则获取数组第1个内容
            resdata = resdata.get(var[0])
            # 从数组中删除第1个内容
            del var[0]
            # 递归
            return parse_relation(var,resdata)
    
    # 测试代码
    if __name__ == '__main__':
        ori_data = {"admin-token": "${token}"}
        replace_data = {'token': 'x015k878'}
        print(relace(ori_data, replace_data))
        red = find({"id":"${id_name}","editorType":"markdown","title":"付出才能杰出","alias":"${alias_name}","thumbnail":None,"typeId":"1","keywords":None,"digest":"

    付出

    ","canComment":False,"recommended":False,"privacy":False,"content":"

    付出

    \n","markdown":"付出","rubbish":False}) print(red)

    8.5.2 建立testcase核心层并封装test_run.py文件

    testcase层是整个接口框架中最重要的层级,用来存放接口框架中的主程序文件test_run.py文件。test_run.py文件提供用例执行的入口,用例执行,结果验证等功能。建立testcase层并封装test_run.py文件的步骤可分为三步。

    第一步,在zrlog接口自动化项目下新建testcase包名

    第二步,新建test_run文件

    第三步,编写接口框架主程序脚本

    # coding=utf-8
    # 导入datetime库
    import datetime
    # 导入DynamicParam类
    from config.settings import DynamicParam
    # 导入logger对象
    from utils.logutil import logger
    # 导入base()方法
    import common.base as Base
    # 导入json库
    import json
    # 导入pytest框架
    import pytest
    # RdTestcase类
    from utils.readmysql import RdTestcase
    # 导入RequestSend类
    from utils.requestsutil import RequestSend
    
    # 初始化类
    attribute = DynamicParam()
    # 实例化测试用例对象
    case_data = RdTestcase()
    # 根据测试用例对象获取测试用例列表
    case_list = case_data.is_run_data('zrlog')
    # 获取当前时间
    current_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    
    # 测试用例执行类
    class TestApi:
        # 类方法,运行开始前只执行1次
        def setup_class(self):
            # 打印日志
            logger.info(f"***** 开始执行测试用例,开始时间为:{current_time} *****")
    
        # 类方法,运行结束后只执行1次
        def teardown_class(self):
            # 打印日志
            logger.info(f"***** 执行用例完成,完成时间为:{current_time} *****")
    
        # 测试用例参数化
        @pytest.mark.parametrize('case', case_list)
        def test_run(self, case):
            # 定义变量
            res_data = None
            # 根据条件,从数据库获取url信息,并拼接完整url信息
            url = case_data.loadConfkey('zrlog', 'url_api')['value'] + case['url']
            # 获取method内容
            method = case['method']
            # 获取headers内容,格式化字符为字典
            headers = eval(case['headers'])
            # 获取cookies内容,格式化字符为字典
            cookies = eval(case['cookies'])
            # 获取请求内容,格式化字符为字典
            data = eval(case['request_body'])
            # 获取关联内容
            relation = str(case['relation'])
            # 获取测试用例名称
            case_name = case['title']
    
            # 根据关联,获取headers参数中是否有变量需要被替换,有则替换,无则默认
            headers = self.correlation(headers)
            # 根据关联,获取cookies参数中是否有变量需要被替换,有则替换,无则默认
            cookies = self.correlation(cookies)
            # 根据关联,获取data参数中是否有变量需要被替换,有则替换,无则默认
            data = self.correlation(data)
    
            # 异常处理
            try:
                # 打印日志
                logger.info("正在执行{}用例".format(case_name))
                # 执行测试用例,发送http请求
                res_data = RequestSend().send(url, method, data=data, headers=headers, cookies=cookies)
                # 打印日志
                logger.info("用例执行成功,请求的结果为{}".format(res_data))
            # 异常捕获
            except:
                # 打印日志
                logger.info("用例执行失败,请查看日志找原因。")
                # 断言结果为失败
                assert False
            # 判断res_data是否存在
            if res_data:
                # res_data存在后,判断relation不为None
                if relation != "None":
                    # 根据响应结果,以及关联信息(token=cookies.admin-token),设置变量token的值为响应结果的信息
                    self.set_relation(relation, res_data)
            # 结果进行验证
            self.assert_respoes(case, res_data)
            # 返回res_data信息
            return res_data
    
        # 响应结果关联设置函数
        def set_relation(self, relation, res_data):
            # 异常处理
            try:
                # 判断relation内容为True
                if relation:
                    # 根据,进行分割,结果为List
                    relation = relation.split(",")
                    # 循环打印relation列表
                    for i in relation:
                        # 根据=进行分割
                        var = i.split("=")
                        # 列表第1个值设置为var_name
                        var_name = var[0]
                        # 列表第2值内容按.进行分割,结果内容保存变量var_tmp
                        var_tmp = var[1].split(".")
                        # 在响应结果res_data中,根据条件var_tmp进行匹配
                        res = Base.parse_relation(var_tmp, res_data)
                        # 打印信息
                        print(f"{var_name}={res}")
                        # 把定义的变量名称以及值 以属性的方式设置到DynamicParam类中,实现动态存储
                        setattr(DynamicParam, var_name, res)
    
            # 捕获异常
            except Exception as e:
                # 打印异常信息
                print(e)
        # 根据关联,获取该变量内容
        def correlation(self, data):
            # 根据正则,获取数据
            res_data = Base.find(data)
            # 判断res_data为True
            if res_data:
                # 定义空的字典
                replace_dict = {}
                # 循环打印
                for i in res_data:
                    # 根据名称,从DynamicParam动态获取属性值,并把结果内容赋值给变量data_tmp
                    data_tmp = getattr(DynamicParam, str(i), "None")
                    # 把结果更新到字典replace_dict中
                    replace_dict.update({str(i): data_tmp})
                # 参数进行替换,并把str转换为python对象
                data = json.loads(Base.relace(data, replace_dict))
            # 返回结果
            return data
    
        # 结果验证方法
        def assert_respoes(self, case, res_data):
            # 变量初始化为False
            is_pass = False
            # 异常处理,捕获assert抛出的异常,不直接抛出
            try:
                # 根据结果进行断言验证
                assert int(res_data['body']['error']) == int(case['expected_code'])
                # 打印信息
                logger.info("用例断言成功")
                # 设置变量为True
                is_pass = True
            # 捕获异常
            except:
                # 设置变量为False
                is_pass = False
                # 打印日志
                logger.info("用例断言失败")
            # 无论是否出现异常,都执行下面内容代码
            finally:
                # 把结果更新到数据库
                case_data.updateResults(res_data, is_pass, str(case['id']))
                # 根据变量结果是True/False,进行断言验证,成功则通过,失败则未通过
                assert is_pass
            # 返回该变量结果
            return is_pass
    
    # 主程序执行入口
    if __name__ == '__main__':
        pytest.main(['-s', '-v', 'test_run.py'])
    
    

    8.5.3 通过pytest框架运行test_run.py文件

    8.5.4 通过log层查看运行日志

    8.5.5 通过report层查看测试报告

    report层负责存储测试报告,脚本运行完成后,将会在该层下自动生成HTML格式的测试报告。

    可以看到,11个测试用例都全部通过

    END


     

  • 相关阅读:
    大模型系统和应用——Transformer&预训练语言模型
    【经历】跨境电商公司目前已在职近2年->丰富且珍贵
    数据结构:队列详解 c++信息学奥赛基础知识讲解
    (前端)「状态」设计模式在项目开发中的应用
    快速构建基于Paddle Serving部署的Paddle Detection目标检测Docker镜像
    Python 博客园备份迁移脚本
    React 模态框的设计(七)整合与测试
    探索 Chrome 插件开发之旅
    实在智能:RPA领域如何使用CRM实现业务精益化管理
    健康先行微信小程序设计与实现
  • 原文地址:https://blog.csdn.net/ljs_fighting/article/details/126103499