1. 项目简介

项目背景:在线购物商城网站,涵盖用户管理(注册/登录)、商品管理(上架/下架)、订单支付全流程  。
测试目标:构建高可靠性电商系统自动化测试方案,验证核心业务链路的稳定性(如:商品浏览→下单→支付→订单校验)。
项目技术栈:Python+pytest+sqlalchemy+requests+allure+jsonpath+yaml+Jenkins+Linux

2. 项目自动化框架核心实现

本自动化测试框架以数据驱动和高度可扩展为核心,结合 Pytest、Allure 等工具,实现了接口自动化测试的全流程闭环。

框架执行流程图如下:

核心实现主要体现在以下几个方面:

2.1 用例驱动与参数化

  • 用例管理:所有测试用例均以 YAML数据文件形式存储在 testcase/ 目录下,便于维护和扩展。
  • 参数化执行:通过 pytest.mark.parametrize 结合自定义的 YAML 读取工具。(如 common.readyaml),实现用例的批量参数化执行,极大提升了用例复用性和覆盖率。
 # 参数化,yaml数据驱动
    @pytest.mark.parametrize('base_info,testcase', get_testcase_yaml("./testcase/Single interface/addUser.yaml"))
    def test_add_user(self, base_info, testcase):
        allure.dynamic.title(testcase['case_name'])
        RequestBase().specification_yaml(base_info, testcase)

2.2 请求封装与数据替换

  • 统一请求入口:所有接口请求均通过 base/apiutil.py 或 base/apiutil_business.py 封装,支持 GET/POST 等多种请求方式。
  • 动态参数替换:支持用例中参数的动态替换(如 ${token()}),通过 common.debugtalk.py 实现自定义函数,满足复杂业务场景下的参数依赖和数据生成。
    def replace_load(self, data):
        """yaml数据替换解析"""
        str_data = data
        if not isinstance(data, str):
            str_data = json.dumps(data, ensure_ascii=False)
            # print('从yaml文件获取的原始数据:', str_data)
        for i in range(str_data.count('${')):
            if '${' in str_data and '}' in str_data:
                start_index = str_data.index('$')
                end_index = str_data.index('}', start_index)
                ref_all_params = str_data[start_index:end_index + 1]
                # 取出yaml文件的函数名
                func_name = ref_all_params[2:ref_all_params.index("(")]
                # 取出函数里面的参数
                func_params = ref_all_params[ref_all_params.index("(") + 1:ref_all_params.index(")")]
                # 传入替换的参数获取对应的值,类的反射----getattr,setattr,del....
                extract_data = getattr(DebugTalk(), func_name)(*func_params.split(',') if func_params else "")

                if extract_data and isinstance(extract_data, list):
                    extract_data = ','.join(e for e in extract_data)
                str_data = str_data.replace(ref_all_params, str(extract_data))
                # print('通过解析后替换的数据:', str_data)

        # 还原数据
        if data and isinstance(data, dict):
            data = json.loads(str_data)
        else:
            data = str_data
        return data

2.3 断言与结果校验

  • 统一断言封装:所有断言逻辑集中在 common/assertions.py,支持多种断言方式(如响应码、响应体、数据库校验等),保证用例结果的准确性和一致性。
# 示例代码
    def contains_assert(self, value, response, status_code):

        # 断言状态标识,0成功,其他失败
        flag = 0
        for assert_key, assert_value in value.items():
            if assert_key == "status_code":
                if assert_value != status_code:
                    flag += 1
                    allure.attach(f"预期结果:{assert_value}\n实际结果:{status_code}", '响应代码断言结果:失败',
                                  attachment_type=allure.attachment_type.TEXT)
                    logs.error("contains断言失败:接口返回码【%s】不等于【%s】" % (status_code, assert_value))
            else:
                resp_list = jsonpath.jsonpath(response, "$..%s" % assert_key)
                if isinstance(resp_list[0], str):
                    resp_list = ''.join(resp_list)
                if resp_list:
                    assert_value = None if assert_value.upper() == 'NONE' else assert_value
                    if assert_value in resp_list:
                        logs.info("字符串包含断言成功:预期结果【%s】,实际结果【%s】" % (assert_value, resp_list))
                    else:
                        flag = flag + 1
                        allure.attach(f"预期结果:{assert_value}\n实际结果:{resp_list}", '响应文本断言结果:失败',
                                      attachment_type=allure.attachment_type.TEXT)
                        logs.error("响应文本断言失败:预期结果为【%s】,实际结果为【%s】" % (assert_value, resp_list))
        return flag

2.4 日志与报告

  • 日志管理:通过 common/recordlog.py 实现日志的自动生成、轮转和过期清理,方便问题追踪和回溯。
  • 多样化报告:支持 Allure、TMReport 两种报告风格,报告内容丰富,集成环境信息(environment.xml),并可自动打开报告页面。
# 示例代码片段
    if REPORT_TYPE == 'allure':
        pytest.main(
            ['-s', '-v', '--alluredir=./report/temp', './testcase', '--clean-alluredir',
             '--junitxml=./report/results.xml'])

        shutil.copy('./environment.xml', './report/temp')
        os.system(f'allure serve ./report/temp')

2.5  配置与环境管理

  • 集中配置:所有环境、数据库、邮件、报告等配置统一存放在 conf/config.ini 和 conf/setting.py,通过封装类(如 conf/operationConfig.py)读取,方便环境切换和维护。
  • 依赖参数管理:接口间依赖参数通过 extract.yaml 动态存储和读取,支持跨用例数据传递。

3.  Allure报告展示

3.1 报告总览页

  • 用例执行统计 :
    18/18 用例通过(绿色进度圈),耗时仅 437ms,体现框架高效性
  • 测试套分类 :
    • 单接口测试:9 个用例(testcase.Single interface
    • 业务流程测试:5 个用例(testcase.Business interface
    • 商品管理模块:4 个用例(testcase.ProductManager

3.2 测试套详细执行情况

以 ​​#1 商品列表​​ 为例:

  • 请求阶段log关键点:
    身份验证 token 字段表明接口需登录态访问;
    分页参数 page=1&size=20 控制返回商品数量;
    无 Cookie 依赖 :系统采用 Token 认证而非 Session 方式。

INFO     common.recordlog:sendrequest.py:135 接口名称:商品列表  
INFO     common.recordlog:sendrequest.py:136 请求地址:http://127.0.0.1:8787/coupApply/cms/goodsList  
INFO     common.recordlog:sendrequest.py:137 请求方式:Get  
INFO     common.recordlog:sendrequest.py:138 测试用例名称:获取商品列表  
INFO     common.recordlog:sendrequest.py:139 请求头:{'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 'token': '3A7a17B5C55D63CBDe8096D4697ba'}  
INFO     common.recordlog:sendrequest.py:140 Cookie:None  
INFO     common.recordlog:sendrequest.py:150 请求参数:{'params': {'msgType': 'getHandsetListOfCust', 'page': 1, 'size': 20}}  
  •  响应阶段log关键点
    缓存控制 cache:0 表示本次请求未命中缓存;
    分页统计 :all[90=21+33+36] 暗示总商品数为 90 条(需进一步验证);
    商品详情 :返回字段包含 goodsIdgoods_nameoriginal_price 等核心信息。

INFO     common.recordlog:sendrequest.py:108 接口返回信息:{"api_info":"today:21 max:10000 all[90=21+33+36];expires:2030-12-31","cache":0,"error_code":"0000","goodsList":[{"goodsId":"18382788819",...}]}
  • 断言验证log关键点
    基础校验 :通过 error_code="0000" 确认接口无异常
    数据提取 :从响应中提取商品 ID 列表供后续用例复用
    断言策略 :采用「包含关系」而非严格匹配,提升用例鲁棒性

INFO     common.recordlog:apiutil_business.py:201 json提取到参数:{'goodsIds': ['18382788819', '33809635011', '56996760797', '82193785267', '74190550836']}  
INFO     common.recordlog:assertions.py:170 yaml文件预期结果:[{'contains': {'error_code': '0000'}}]  
INFO     common.recordlog:assertions.py:45 字符串包含断言成功:预期结果【0000】,实际结果【0000】  
INFO     common.recordlog:assertions.py:198 测试成功  

Logo

电商企业物流数字化转型必备!快递鸟 API 接口,72 小时快速完成物流系统集成。全流程实战1V1指导,营造开放的API技术生态圈。

更多推荐