尧图精选

基于Requests的接口自动化测试框架搭建实战

🕒 发布时间:2026/10/2 3:58:45 📁 来源:尧图网络
1. 为什么接口自动化测试框架先选Requests做测试做了这么多年我越来越觉得接口自动化是投入产出比最高的一个环节。UI自动化要处理元素定位、等待机制、浏览器兼容这些乱七八糟的坑跑一次全量回归能让人盯到眼瞎。接口自动化就没这么多破事它直接对着接口发请求、验响应逻辑清晰、执行稳定还能在CI流水线里跑得飞快。我最早做接口测试的时候用的是Postman调试确实方便但一旦用例多起来Postman那套集合管理就有点不够用了而且它不适合做复杂的断言逻辑和数据驱动。后来我把目光转向Python生态发现Requests库几乎是为接口测试量身定做的。它的API设计得非常人性化拿官方文档的话说就是HTTP for Humans意思是拿它发HTTP请求就像跟人说话一样自然。你不需要自己拼URL、处理Cookie、管理连接池这些底层细节Requests全帮你搞定了。所谓搭建基础接口自动化测试框架做的是这么几件事把业务接口封装成可复用的函数、把测试数据和用例分离开、把断言逻辑做成统一规范、最后把测试报告生成出来。这套框架一旦建好后面对接新项目、扩充用例都是顺水推舟的事。这篇文章适合刚接触接口自动化测试的朋友也适合那些用过Postman但想往代码方向深造的测试工程师。我会把从环境准备到框架落地再到问题排查的完整过程都写出来全程有代码、有截图思路、有踩坑记录照着做基本能跑通。2. 动手前的准备工作环境、依赖与基础概念2.1 Python环境与虚拟环境配置先说环境。Requests是一个纯Python库所以前提条件就是你机器上得有Python。近几年我用的都是Python 3.8以上版本了Python 2已经在2020年停止维护别再纠结选哪个直接上3.x推荐3.9到3.12之间的稳定版本。装Python的时候有一个细节大家最容易忽略安装时一定要勾选Add Python to PATH否则后面命令行里敲python会提示找不到命令你还得手动配环境变量很烦。Python装好之后我强烈建议你创建一个虚拟环境。虚拟环境的作用是给每个项目隔离一套独立的依赖包防止多个项目之间的包版本互相打架。我见过太多人把pytest、requests这些包一股脑全装到全局环境里结果某天升级了一个包好几个项目全挂了排查起来非常痛苦。创建虚拟环境用Python自带的venv模块就行不需要额外装东西# 在项目根目录下执行 python -m venv venv # Windows激活 venv\Scripts\activate # macOS/Linux激活 source venv/bin/activate激活之后命令行前面会多出一个(venv)前缀这时候你装的包都进这个虚拟环境了跟系统全局环境互不干扰。2.2 安装Requests及相关依赖包接着把核心依赖装上。我推荐一套组合Requests pytest pytest-html。Requests负责发HTTP请求pytest负责测试用例的组织和执行pytest-html负责生成可视化测试报告。后面还可以根据需求加pytest-rerunfailures失败重跑、allure-pytest更精美的报告等。pip install requests pytest pytest-html如果你是刚接触pip的新手加载慢或者出现Defaulting to user installation because normal site-packages is not writeable这类提示不用慌前者是因为默认走的国外源可以换用清华源pip install -i https://pypi.tuna.tsinghua.edu.cn/simple requests pytest pytest-html后者是因为当前Python环境是系统级的写不进去解决方案就是前面说的用虚拟环境。在虚拟环境里pip安装默认就会装进虚拟环境不会碰到这个报错。装完之后在Python交互式环境里验证一下import requests print(requests.__version__)能正常打印出版本号就说明Requests可用了。接着简单发个请求试试水import requests resp requests.get(https://httpbin.org/get) print(resp.status_code) print(resp.json())httpbin是一个非常常用的在线接口测试服务发什么请求它会原样返回什么很适合拿来练习。2.3 先理解Requests库的几个核心对象在开始搭框架之前我建议你先花十几分钟把Requests库的几个核心对象搞清楚后面写代码会顺很多。第一个是Response对象。你调用requests.get或requests.post之后返回的就是它。这个对象里装着你发起HTTP请求后的所有结果包括状态码、响应头、响应体、cookie、请求耗时等。判断接口通没通第一步必然是先看resp.status_code要取业务数据就得解析resp.text或resp.json()。第二个是Session对象。这个特别关键Session让你能跨多个请求保持同一个TCP连接和cookies。你登录之后后续请求需要携带会话凭证就是把同一个Session对象传给后续所有请求。很多新手犯的错是每个请求都直接用requests.get结果登录态压根没带上接口返回401还一脸懵。第三个是Request对象它是你发起HTTP请求前构造的那份意图。虽然日常直接用requests.get就能发起请求但如果你想做统一的请求预处理、日志记录、加密签名就得在Request层动手脚。框架搭建后面对请求做增强基本都围绕这一层。3. 框架怎么搭目录设计与分层思想3.1 为什么接口测试框架要分层我见过不少初学者的代码风格打开一个Python文件从上到下把用例一条条写进去每个用例里直接requests.post然后简单assert一下。这种写法在小项目里跑通没问题但一旦用例到了几十条上百条你就会发现第一接口地址和参数散落在各个用例里后端接口的域名换了要全局搜索替换参数结构变了要逐个改维护成本极高。第二公用逻辑没法复用比如登录、鉴权、加密、日志每个用例都要写一遍代码又长又臭。第三没法做数据驱动新增一条用例必须改代码而你明明只需要加一行测试数据。所以框架的核心价值在于分层把接口请求用例组织数据管理断言验证这些不同职责拆开各管一摊互不干扰。3.2 一套适合多数项目的目录骨架下面这套目录结构是我在多个项目里打磨出来的适合中小型接口自动化项目拿来直接用就行api_test_framework/ ├── config/ │ └── settings.py # 全局配置域名、超时、环境等 ├── common/ │ ├── request_client.py # Requests二次封装 │ ├── assert_utils.py # 断言工具 │ ├── log_utils.py # 日志工具 │ └── yaml_utils.py # YAML读取工具 ├── api/ │ ├── __init__.py │ ├── base_api.py # 接口基类 │ ├── user_api.py # 用户模块接口 │ └── order_api.py # 订单模块接口 ├── data/ │ └── user_cases.yaml # 登录用例数据 ├── testcases/ │ ├── __init__.py │ ├── conftest.py # pytest夹具 │ └── test_login.py # 登录测试用例 ├── reports/ │ └── (运行时自动生成的html报告) ├── requirements.txt └── pytest.ini # pytest配置这个结构看着简单但每层都有明确的职责config层管所有环境相关的配置比如测试环境的域名、超时时间、请求头模板common层放通用组件如封装的请求客户端、断言和日志工具api层把每个业务模块的接口封装成Python函数一个接口对应一个函数调用方不用关心HTTP细节testcases层专门写测试用例一个用例文件对应一个功能模块data层存测试数据一条数据跑一遍用例实现数据驱动reports层收集测试报告给领导或团队看结果用。3.3 目录该怎么使用从配置到用例的调用链路理解了目录设计还要理解数据流向。简单来说就是testcases里的用例函数调用api层的接口封装函数api层调common层的请求客户端请求客户端从config层读取配置测试数据从data层传给用例函数。我拿登录用例举例实际调用链路是这样的testcases/test_login.py里面定义了一个test_login_success函数参数从data/user_cases.yaml读取。用例函数调用api/user_api.py里的login接口函数传入用户名密码和预期结果。login函数拿着这些参数调用common/request_client.py里的request封装方法传入接口路径、请求方式、参数等信息。request_client从config/settings.py里读到测试环境的base_url、超时时间等配置发起真正的HTTP请求。请求结果返回到用例层用例层通过断言工具做校验。这个链路看起来很绕但好处非常明显接口域名变了只改config接口入参结构变了只改api层对应的那个函数断言规则变了只改common里的工具测试数据变了只改data层的YAML文件。每一层的变化被限制在对应目录里谁都不会动手改别人的地盘。这就是基础接口自动化测试框架的核心价值所在。4. 核心代码实现请求封装、配置管理、断言工具与用例编写4.1 把Requests二次封装一个更顺手的请求客户端Requests本身已经很好用了但直接裸用还是有几个痛点超时不设置会一直等、请求失败没有任何重试机制、日志靠print不专业、不同接口号统一处理返回逻辑。所以我们要在不破坏Requests原有能力的前提下做一层薄封装。我写了一个request_client.py核心思路是保持接口风格接近Requests原生API但默认帮用户处理超时、会话、日志、重试这些通用逻辑。这个封装的精华在于Session对象的使用。Session会自动管理cookie可以跨请求保持登录态还会自动复用底层连接性能也比每次新建连接好不少。下面是一份可以直接用的简化实现import requests import logging from urllib3.util.retry import Retry from requests.adapters import HTTPAdapter from config.settings import BASE_URL, TIMEOUT, MAX_RETRIES logger logging.getLogger(api_test) class RequestClient: def __init__(self, base_urlBASE_URL): self.base_url base_url self.session requests.Session() # 配置重试策略最多重试MAX_RETRIES次支持连接错误和5xx状态码 retry Retry( totalMAX_RETRIES, backoff_factor1, status_forcelist[500, 502, 503, 504], allowed_methods[GET, POST, PUT, DELETE] ) adapter HTTPAdapter(max_retriesretry) self.session.mount(https://, adapter) self.session.mount(http://, adapter) def _merge_headers(self, headersNone): default_headers { Content-Type: application/json;charsetutf-8, User-Agent: Mozilla/5.0 (compatible; ApiTest/1.0) } if headers: default_headers.update(headers) return default_headers def request(self, method, url, **kwargs): # 组合完整URL full_url url if url.startswith(http) else self.base_url url # 超时兜底 kwargs.setdefault(timeout, TIMEOUT) kwargs[headers] self._merge_headers(kwargs.get(headers)) logger.info(f请求方式: {method.upper()}, URL: {full_url}, 参数: {kwargs.get(params) or kwargs.get(json) or kwargs.get(data)}) resp self.session.request(method, full_url, **kwargs) logger.info(f响应状态码: {resp.status_code}, 响应体: {resp.text[:500]}) return resp def get(self, url, **kwargs): return self.request(GET, url, **kwargs) def post(self, url, **kwargs): return self.request(POST, url, **kwargs) def put(self, url, **kwargs): return self.request(PUT, url, **kwargs) def delete(self, url, **kwargs): return self.request(DELETE, url, **kwargs)这里有两个很重要的设计细节。一个是Retry重试策略它解决的是接口偶发超时、服务端偶发5xx的问题。接口测试最怕的就是不稳定明明接口是通的网络抖动一下用例就红了排查半天发现是虚惊。设置重试策略能把这些偶发问题兜住但注意重试次数不要太多我一般建议总的重试次数不超过3次太多会导致整体测试时间暴涨。另一个是timeout兜底我要是不设置超时接口一旦卡死requests会一直等下去整个测试套件就挂在半路上了。这个问题在搭建框架初期特别容易忽略等接口多了就等着哭吧。4.2 让测试数据和代码分家配置管理怎么做我一直坚持的原则是代码里不要写死任何环境相关的东西比如域名、账号密码这些都要放到配置文件里。用Python模块做配置是最简单的方案因为不需要引入额外的第三方库写起来也顺手。我在config/settings.py里维护这样一些东西import os # 环境切换dev/sit/uat/prod按需改动或通过环境变量注入 ENV os.getenv(API_TEST_ENV, dev) ENVIRONMENTS { dev: { base_url: http://127.0.0.1:8000, common_headers: {X-Env: dev} }, sit: { base_url: http://sit-api.example.com, common_headers: {X-Env: sit} } } current_env ENVIRONMENTS[ENV] BASE_URL current_env[base_url] TIMEOUT 10 MAX_RETRIES 3这里用了个环境变量API_TEST_ENV来做环境切换默认跑dev环境。当你在命令行执行API_TEST_ENVsit pytest的时候框架会自动用sit环境的域名跑用例非常方便。如果你不想依赖环境变量改成手动改ENV变量也行看团队习惯。除了环境配置测试数据也要和代码分家。接口测试里最典型的场景是同一个用例登录用一组正确账号、一组错误密码、一组不存在的账号预期结果各不相同。把这些数据放到data/user_cases.yaml里用例函数只负责读取数据并执行断言就实现了数据驱动。login_case: - case_name: 登录成功 username: test_user password: 123456 expected_code: 200 expected_biz_code: 0 - case_name: 密码错误 username: test_user password: wrong_password expected_code: 200 expected_biz_code: 1001 - case_name: 用户名不存在 username: no_such_user password: 123456 expected_code: 200 expected_biz_code: 1002给用例配置一个公用的数据格式很重要。我这里的约定是expected_code是HTTP状态码expected_biz_code是业务返回码。为什么要把这两个分开因为很多接口即使业务出错HTTP状态码仍然是200真正的错误信息是塞在响应体里的业务码字段里的。断言时两个都要看但先看HTTP层是否正常再看业务层是否符合预期逻辑会很清晰。读取YAML文件很简单装一下pyyamlpip install pyyaml然后在common/yaml_utils.py里写import yaml import os def load_yaml(file_path): with open(file_path, r, encodingutf-8) as f: return yaml.safe_load(f) def get_case_data(file_name, case_key): base_dir os.path.join(os.path.dirname(os.path.dirname(__file__)), data) data load_yaml(os.path.join(base_dir, file_name)) return data.get(case_key)4.3 一套能用的断言工具从状态码到业务码的断言体系做接口测试的时候断言是决定用例是否通过的关键。我见过太多人只会assert resp.status_code 200但其实接口测试的断言体系远不止这么浅。我的断言体系分三层第一层HTTP状态码断言。它验证的是接口通不通。如果连HTTP层都不通比如404、500说明服务或网络有问题后面都不用往下查了。第二层业务码断言。很多接口规范会把业务处理结果放进响应体的一个字段比如code或者bizCode。业务码为0通常代表成功1001代表密码错误1002代表用户名不存在。这一层验证的是业务到底成没成。第三层业务数据断言。有些敏感的业务场景比如数据库里改了一个金额、更新了一个用户状态光靠接口返回码不够还得校验返回的data字段。如果响应体里带了关键信息直接通过表达式从response.json()里把对应字段取出来做校验。写一个简单的断言工具类import json class AssertUtils: staticmethod def assert_status_code(resp, expected_code): assert resp.status_code expected_code, ( fHTTP状态码校验失败期望: {expected_code}, 实际: {resp.status_code}, 响应体: {resp.text} ) staticmethod def assert_biz_code(resp, expected_biz_code, fieldcode): resp_json resp.json() actual_biz_code resp_json.get(field) assert actual_biz_code expected_biz_code, ( f业务码校验失败期望: {expected_biz_code}, 实际: {actual_biz_code} ) staticmethod def assert_json_field(resp, field_path, expected_value): field_path支持简单路径比如data.user.name resp_json resp.json() keys field_path.split(.) current resp_json for key in keys: if not isinstance(current, dict) or key not in current: raise AssertionError(f字段路径不存在: {field_path}) current current[key] assert current expected_value, ( f字段值校验失败字段: {field_path}, 期望: {expected_value}, 实际: {current} )这段代码看着不复杂但有几个细节帮你避免测试过程的最大尴尬。所有断言失败信息里都带上期望值、实际值和响应体内容。你想想跑完100条用例后如果只是assert失败你还得一个个去翻日志才知道到底是哪不对。把关键信息直接打在断言消息里定位问题就快多了。断言工具一定要放在common层这样所有用例模块都能复用它。4.4 接口封装层怎么写把业务接口变成函数项目里的接口五花八门登录、注册、下单、查询、删除如果每个用例都直接拼URL、整请求代码风格很容易失控。所以我在api层做一个接口函数封装约定所有接口函数统一通过RequestClient发起请求。先写一个api/base_api.py把RequestClient实例初始化好from common.request_client import RequestClient request_client RequestClient() class BaseApi: def __init__(self): self.client request_client然后在api/user_api.py里把用户模块的接口封装成函数from api.base_api import BaseApi class UserApi(BaseApi): def login(self, username, password): payload { username: username, password: password } return self.client.post(/api/v1/user/login, jsonpayload) def get_user_info(self, user_id): return self.client.get(f/api/v1/user/{user_id}) def update_user(self, user_id, **kwargs): return self.client.put(f/api/v1/user/{user_id}, jsonkwargs)每个接口函数只暴露业务参数比如username和password把HTTP细节全藏起来。用例层调它的时候只需要关心这个接口的业务意义不需要关心它是POST还是GET、路径是什么、请求头长什么样。你可能会问每个项目接口签名都不一样这个封装层是不是每次都要重写对项目之间接口天生就是不同的所以api层本来就是需要针对具体项目定制的。框架要复用的不是api层代码而是它底下的config、common、testcases组织结构这套东西换项目时可以直接搬过去。4.5 pytest用例怎么组织conftest、夹具与参数化pytest是这套框架里的测试执行引擎。它有几样东西非常好用分别是fixture、参数化和断言。先给pytest写一个配置文件pytest.ini让它在项目根目录下就能找到所有测试模块[pytest] testpaths testcases python_files test_*.py python_functions test_* addopts -s -v --htmlreports/report.html --self-contained-htmladdopts里的-v是让控制台打印更详细--html是让pytest-html生成报告。--self-contained-html这个参数一定要写意思是把css、js全部内联进html文件报告发给别人的时候只要发一个文件就行否则会有一堆静态资源跟报告分离传个文件还带个文件夹很麻烦。然后写testcases/conftest.py这里放pytest的fixture。fixture可以理解为测试的预处理和后置逻辑比如连接数据库、准备测试数据、清理数据、生成登录token。import pytest from api.user_api import UserApi pytest.fixture(scopesession) def login_token(): 整个测试会话只登录一次返回登录后的token user_api UserApi() resp user_api.login(test_user, 123456) token resp.json().get(data, {}).get(token) assert token, 登录未返回token后续依赖登录态的用例将无法执行 return token pytest.fixture(scopeclass) def auth_headers(login_token): 返回带鉴权的请求头 return {Authorization: fBearer {login_token}}fixture的scope参数很关键。scopesession表示整个测试会话只执行一次适合登录这种耗时且重复的步骤scopeclass表示每个测试类执行一次scopefunction是默认值每个用例函数都会执行一次。合理设置scope能省不少测试时间。接着写testcases/test_login.py用pytest的parametrize实现数据驱动import pytest from api.user_api import UserApi from common.assert_utils import AssertUtils from common.yaml_utils import get_case_data case_data get_case_data(user_cases.yaml, login_case) pytest.mark.parametrize(case, case_data, ids[c[case_name] for c in case_data]) def test_login(case): user_api UserApi() resp user_api.login(case[username], case[password]) AssertUtils.assert_status_code(resp, case[expected_code]) AssertUtils.assert_biz_code(resp, case[expected_biz_code])这才是接口自动化测试框架的核心样貌。你新增一条测试用例只需要往YAML里加一条数据不需要动代码。要增加一个新的接口测试模块只需要复制一个test文件替换成对应api层函数即可。5. 实战演示一个登录接口从写用例到出报告的完整流程理论讲再多都不如亲手跑一遍。我拿一个典型的登录接口来做一次完整的实战演示这个接口是我本地用Flask起的模拟服务接口逻辑就是校验用户名密码并返回token。模拟服务端代码很简单就一个main.pyfrom flask import Flask, request, jsonify app Flask(__name__) app.route(/api/v1/user/login, methods[POST]) def login(): data request.get_json() username data.get(username) password data.get(password) if username test_user and password 123456: return jsonify({code: 0, message: success, data: {token: fake_token_abc123}}) if username ! test_user: return jsonify({code: 1002, message: user not found, data: None}) return jsonify({code: 1001, message: wrong password, data: None}) if __name__ __main__: app.run(port8000)这个服务在本地跑起来后我按上面搭好的框架把用例数据、接口封装、用例文件准备好然后在项目根目录执行pytestpytest会自动扫描testcases目录下的test_*.py文件并执行。跑完之后控制台会显示每个用例的通过还是失败。框架的日志还会输出每个请求的URL、参数和响应体前500个字符方便做失败排查。最终会在reports目录下生成一个report.html用浏览器打开后能看到完整的测试报告通过率、执行时间、每个用例的状态、失败原因、请求参数和响应快照全都在里面。这个报告拿去做领导汇报或者团队成员对接基本是够了的。跑一次真实执行你就会发现这个框架的构建过程其实从写用例到出报告没有一步是多余的用例数据放在data里登录逻辑封装在api层请求细节收敛在common层断言规则统一由AssertUtils把控报告报告自动生成。以后新项目只需要改config、写api层、维护data数据框架的核心资产可以直接复用。6. 常见问题与排查技巧我在实战中踩过的坑6.1 请求超时与上游限流429状态码怎么办接口自动化跑起来之后第一个高频问题就是请求太频繁导致服务端限流。我在做一轮冒烟回归的时候用例里有一个循环遍历用户的接口连续发了几百个请求跑到一半就开始出现429 Too Many Requests的错误提示。原因很简单测试环境的网关或服务端设置了访问频率限制请求太快就被拦截了。解决办法有两个方向。第一个方向是在代码层面控制请求频率最简单的办法是每次请求之间加一个小sleepimport time time.sleep(0.5)第二个方向是用重试策略配合退避机制。在4.1小节里我提过Retry的backoff_factor参数它的含义是第一次重试等待1秒第二次等待2秒第三次等待4秒指数退避。遇到429这类限流状态码退避重试就相当有用等一小段时间再重发一次就通过了。第三个方向是从数据量上做减法。全量数据没必要每次都跑抽样跑一部分或者打散到一天的多个时间点分批跑既降低了对测试环境的压力也避免了触发限流。6.2 登录态失效Session和Token过期问题跑全量用例的时候最尴尬的情况是前面几十条登录相关的用例全过了后面跑着跑着突然出现一片401未授权。原因多半是登录返回的token有有效期而你的用例全是背着旧token在跑。这个问题分两种情况处理。一种情况是项目用的是SessionCookie机制那Requests的Session对象已经帮你管cookie了正常情况下不会失效如果失效多半是服务端设置了session超时时间比如30分钟。这种情况我建议把登录做成一个独立的session级fixture并在关键用例前置做一次是否已过期的检查。另一种情况是项目用的是Token认证机制比如JWT。token放在请求头里过期时间通常比较短比如1小时。这种情况下我的做法是把token的获取封装成独立的fixture每个可能执行时间较长的测试模块在自己模块内重新获取一次token或者做一个带token请求被401时自动重新登录并重试一次的机制。后者实现起来稍微复杂但很值得遇到偶发401的问题重试一下通常就绿了。6.3 SSL证书错误与自签名证书处理测试环境里最常见的另一个坑是SSL证书错误。很多公司内部测试环境用的是自签名证书Requests默认开着证书校验直接请求会抛出SSLError。这时候先别急着把verifyFalse一关了之有问题要分清楚。如果你的请求目标是公开互联网服务比如httpbin、github api出现SSL错误大概率是本地环境问题优先检查机器时间和根证书。如果你的目标本来就是内网自签证书的服务那就只能对测试环境关闭证书校验resp self.session.request(method, full_url, verifyFalse)在requests原生验证出现exceeded retry limit这类报错时核心信息其实是请求尝试了多次依然失败。我排查的时候会抓两个点第一是重试前就报错还是重试之后才报错第二是连接层失败还是HTTP层错误。连接层失败可能是网络不通或DNS解析不了HTTP层错误才需要去看服务端日志。思路对了排查速度能快上一倍。6.4 中文乱码与响应编码问题接口返回的JSON里如果包含中文在控制台打印响应体时经常看到一坨\uXXXX的转义序列。这不是bug是JSON本身的设计计算机里的中文默认以Unicode转义形式存在很多测试工具会自动帮你解码但Requests不会。处理办法是拿到响应体后用Python的json.dumps美化一下再打印import json text json.dumps(resp.json(), ensure_asciiFalse, indent2) print(text)ensure_asciiFalse是关键它让json模块不要把非ASCII字符转义成\u形式。另外有些接口返回的不是JSON而是HTML或XML这时候直接用resp.text就够了Requests会根据响应头里的charset自动解码偶尔有乱码的话手动指定一下encodingresp.encoding utf-86.5 断言失败不要慌先分清是框架问题还是接口问题跑测试的时候断言红了新手第一反应是我的用例写错了。但做接口测试断言失败的原因五花八门我把常见的排查路径整理成一个速查表现象可能原因排查方向建立连接超时服务没起、端口错了、防火墙拦了先手动访问接口地址确认服务可达404 状态码URL路径不对、路由没注册打开服务端路由表对比路径500 状态码服务端代码异常查服务端日志重点看堆栈业务码与预期不符测试数据不对、数据库状态不对检查前置数据是否准备好接口响应时间过长服务端慢查询、网络弱看日志里耗时的接口做性能分析这张表看着简单但我在项目里无数次靠它快速定位问题。接口测试用例红了不一定是自动化脚本的问题很可能是环境、数据、服务端代码三方面任一环节出了问题。遇到红色用例先跑一遍这个排查流程比闷着头改代码省时间得多。7. 框架的后续扩展思路基础框架跑通之后如果你想让它更强一点我按优先级给你三个扩展方向。第一个方向是把接口依赖管理起来。真实业务里接口之间往往有依赖比如先要创建订单才能支付订单支付后才能查询支付状态。pytest的fixture天然适合做这个把创建订单做成一个返回订单号的fixture支付用例依赖这个fixturepytest会自动先创建订单再执行支付。下单 - 支付 - 查询这类链路就能一条龙串起来。第二个方向是接入CI/CD流水线。框架本身是命令行工具pytest天然适合被Jenkins、GitLab CI这类工具调用。在流水线里加一个步骤跑pytest并把生成的report.html作为构建产物归档就能实现每次代码提交后自动跑一遍接口回归。这个扩展方向价值非常高因为手工触发回归总有人忘记跑。第三个方向是加上数据库断言。接口测试本质是对业务逻辑做验证有些场景只验证接口返回不够比如创建订单后数据库库存扣减是否正确。这种就需要测试代码里连数据库把订单表里的库存字段查出来跟预期比对。做法是在common层加一个数据库连接工具封装查询方法然后在用例里配合assert用。我自己做接口自动化这些年最深的体会是框架这个东西不在于多炫多复杂而在于稳定、可复用、好维护。Requests加pytest这套组合短小精悍但五脏俱全应付绝大多数项目的接口回归测试绰绰有余。今天这套基础框架如果你能动手敲一遍把登录、用户信息这些常见的接口模式跑通后面接任何新项目你都能用最快的速度把接口测试能力复制过去。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →