接口自动化测试实战:“优购商城”电商平台测试报告深度解析
项目背景:在线购物商城网站,涵盖用户管理(注册/登录)、商品管理(上架/下架)、订单支付全流程。测试目标:构建高可靠性电商系统自动化测试方案,验证核心业务链路的稳定性(如:商品浏览→下单→支付→订单校验)。2. 项目。
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)
- 单接口测试:9 个用例(

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 条(需进一步验证);
商品详情 :返回字段包含goodsId、goods_name、original_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 测试成功
更多推荐


所有评论(0)