跳到主要内容

接口测试

接口测试通过系统对外提供的调用边界,验证输入处理、权限、业务行为与输出是否符合约定。HTTP 状态正常只是其中一层证据:创建订单返回成功后,订单是否可读、金额是否正确、重复调用是否多扣一次,都需要相应检查。

接口自动化把这些检查变成可重复执行的程序。重点是建立明确的前置状态和断言,并把结果与失败证据保留下来;使用请求工具或写出一段 HTTP 调用,还不等于已经完成有效测试。

1. 面试核心​

先记住这几条,再读正文
  • 接口契约要说明方法、路径、字段、身份、状态码及业务效果。Schema 可以检查结构,但不能单独证明余额、权限和状态流转正确。卡 · 契约与测试条件
  • 断言应覆盖协议结果、关键业务字段和必要的最终状态。只检查 HTTP 200 或 JSON 能解析,会漏掉错误业务结果。卡 · 多层断言
  • 权限测试要同时改变身份与资源归属,已登录不代表可以操作任意 ID 对应的资源。卡 · 综合题
  • 多租户或多房间业务要验证数据进入正确范围,且不会进入不相关范围;负向观察需要明确时间窗口与证据边界。卡 · 业务数据隔离
  • 自动化用例应具备可重建的准备、独立执行与确定的清理。请求超时和清理失败也要成为可观察结果。卡 · 最小自动化实现
  • 幂等与并发检查要核对业务副作用,返回相同响应不保证只执行了一次,启动多个线程也不保证同时进入关键区间。卡 · 综合题
  • 异步接口要区分接受与完成,在明确期限内验证最终状态,并保留等待过程与失败原因。卡 · 重复、并发与异步
  • 接口与 UI 测试观察的边界不同。接口通过不能证明浏览器交互正确,UI 通过也不能覆盖所有服务端输入和权限组合。卡 · 执行证据与测试范围

2. 契约与测试条件​

接口契约是调用方与提供方对交互的约定。OpenAPI 可以描述路径、参数、请求体、响应结构和安全要求;业务规则还需要说明资源状态、权限范围和副作用。

以创建文章为例,可以先整理:

条件需要确定的规则与测试
请求表示方法、路径、Content-Type、字段是否必填及类型
输入范围标题长度、内容限制、缺失、空值和非法格式
身份权限未认证、作者、其他用户、管理员的可操作范围
当前状态草稿、已发布、已删除时允许哪些操作
成功结果返回 ID、作者归属、初始状态和可读取的内容
失败结果错误码、错误结构及不得发生的写入
重复与竞争同一操作重试、同时修改、重复发布

协议细节见 HTTP。测试这里使用方法与状态语义,不重新定义一套“接口专用 HTTP”。

字段规则用 等价类划分和边界值分析选输入;多个规则共同决定结果时,先明确优先关系。输入非法但身份也无效时,一次拒绝不能证明两条检查都有效。

3. 多层断言​

断言应由独立契约推导,并与这条用例的目标一致。对创建操作,可以按观察层次核对:

层次示例断言能说明什么
协议约定的 201,内容类型为 JSON响应形式符合接口要求
结构ID 存在且类型正确,必填字段齐全响应形状符合约定
业务标题与输入一致,作者是当前用户关键字段具有正确含义
状态读取新 ID 得到约定记录对外读取路径观察到创建结果
副作用只产生一条记录,失败不扣配额检查必要的业务不变量

GET 能读到记录,仍不自动证明数据库已经完成符合要求的持久化,读取可能来自缓存。若测试目标是重启后数据仍保留,就需要对应的持久化与恢复场景;若只测接口外部行为,则不必为每条用例都直接查询内部表。

Schema 校验也有边界。一个响应即使每个字段类型正确,仍可能把别人的文章返回给当前用户。结构、权限与业务断言需要分别建立。

预期失败要检查约定错误,而不是只写 status_code != 200。接口崩溃返回 500、跳转登录页返回 302 和按契约拒绝返回 403,含义并不相同。

4. 权限与资源归属​

权限检查至少考虑“谁、对哪个资源、做什么”。认证机制见 认证与授权,接口测试则把边界转成可执行组合。

例如用户 A 的私人草稿:A 可读取和修改,B 不可读取和修改,未登录请求被拒绝。对每种身份都使用同一个已知草稿 ID,才能验证资源归属,而不是碰巧请求一个不存在的 ID。

同时核对失败没有泄露受保护内容,没有改变作者或状态。修改请求体里的 author_id 也不应让普通用户冒充别人;服务端应依据可信身份决定归属,测试不能只检查界面隐藏了输入框。

管理员能力要按真实授权规则建模,不默认拥有所有操作。通过错误码隐藏资源存在性时,预期的 403 或 404 也要服从明确契约。

4.1 业务数据隔离​

业务隔离检查验证产品是否把数据送给正确对象,与测试用例自身的数据隔离不是同一件事。例如直播间 A 的弹幕不能出现在直播间 B,可以给测试弹幕带唯一内容标识,同时建立两个房间的观察端。

先确认两个观察端都已完成对应订阅,再向 A 发送弹幕:A 应收到正确内容,B 在约定观察窗口内不应收到该标识。让 A 成功收到是必要的正向证据,否则 B 没收到可能只是消息根本没有发送成功。

还应检查切换房间、重新连接和旧订阅释放后是否残留错误路由。负向等待有时间边界,不能凭短时间没观察到就证明永远不会泄漏;结合订阅关系和服务端路由证据,才能进一步判断隔离是否有效。

5. 最小自动化实现​

下面示例用 pytest 8.4 与 Requests 2.32 验证一个简化笔记服务。它是测试客户端,要求目标测试服务提供这些接口:

  • PUT /notes/{id}:新 ID 和合法标题返回 201;标题必须为 1 到 40 个 Unicode 码点的字符串,非法输入返回 422 和 {"code": "INVALID_TITLE"},且不保存。
  • GET /notes/{id}:存在返回 200 和 {id, title},不存在返回 404。
  • DELETE /notes/{id}:删除成功返回 204,不存在返回 404。

本例省略认证,只演示准备、请求、断言与清理;它不代表上节的权限检查已经完成。将代码保存为 test_note_api.py,并把 CODING101_TEST_BASE_URL 配置为提供上述契约的测试服务地址。

import os
from uuid import uuid4

import pytest
import requests

@pytest.fixture
def note_api():
base_url = os.environ["CODING101_TEST_BASE_URL"].rstrip("/")
note_id = uuid4().hex
url = f"{base_url}/notes/{note_id}"
with requests.Session() as client:
try:
yield client, url, note_id
finally:
result = client.delete(url, timeout=(1, 2), allow_redirects=False)
assert result.status_code in (204, 404)

def test_create_and_read(note_api):
client, url, note_id = note_api
created = client.put(
url, json={"title": "draft"}, timeout=(1, 2), allow_redirects=False
)
assert created.status_code == 201
assert created.headers["Content-Type"].split(";", 1)[0] == "application/json"
assert created.json()["id"] == note_id

fetched = client.get(url, timeout=(1, 2), allow_redirects=False)
assert fetched.status_code == 200
assert fetched.json() == {"id": note_id, "title": "draft"}

@pytest.mark.parametrize("title", ["", None, 7, "x" * 41])
def test_invalid_title_does_not_create_record(note_api, title):
client, url, _ = note_api
result = client.put(
url, json={"title": title}, timeout=(1, 2), allow_redirects=False
)
assert result.status_code == 422
assert result.json()["code"] == "INVALID_TITLE"
assert client.get(url, timeout=(1, 2), allow_redirects=False).status_code == 404

在目标环境安装依赖后执行:

python -m pytest -q test_note_api.py

服务符合示例契约时应收集并通过五项测试。每项使用独立 ID,因此清理可以在 PUT 失败或响应无法解析时仍使用已知地址,不依赖成功响应里才返回的资源标识。

allow_redirects=False 保留原始状态,避免请求被重定向到另一个页面后得到 200,掩盖真正结果。json= 负责 JSON 编码及相应内容类型;timeout=(1, 2) 指连接与读取等待配置,不是整个用例固定三秒的总期限。完整时间预算仍需结合调用截止时间设计。

清理失败会作为 fixture 的错误报告,而不是悄悄忽略。真实服务还需要记录运行标识、残留数据和补偿清理策略。fixture 生命周期的具体机制见 pytest。

这个例子故意使用精确响应比较,适合契约只包含固定字段的服务。如果实际允许新增可选字段,应只断言需要的字段和明确约束,避免把合法扩展误报为缺陷。

6. 重复、并发与异步​

幂等测试检查同一业务操作重试后是否产生额外效果。可以依次验证同一个键与相同请求、同一个键与不同请求,以及不同键代表的新操作;期望由接口约定决定,不能认为返回相同 JSON 就说明没有重复扣款。

请求超时后也可能已经写入。需要用稳定业务标识查询最终结果,并检查重试是否重复执行;实现机制见 幂等键。

并发测试要验证共享状态竞争下的规则。例如仅剩一个名额时,两个请求竞争后最多一个成功,名额不能变成负数。可以使用客户端屏障让请求尽量同时发出,但服务器是否同时进入关键区间还要由日志、追踪或受控测试钩子确认;线程启动时间相近只是一项条件。

并发结果应核对成功与失败集合、最终状态以及副作用数量。若应用使用数据库事务,测试应经过真实事务边界;用单线程内存替身通过,不能证明数据库并发控制正确。

异步接口测试区分任务接受和任务完成。收到 202 后按约定查询状态,在明确总期限内等待成功或失败终态;每次查询有自己的超时,整体也要有期限。终态为成功后再核对产物,失败或期限耗尽时保留任务 ID、状态历史和关联日志。

固定睡眠两秒后查询一次可能在快环境浪费时间、慢环境误报;无限轮询又会把真正未完成的问题藏起来。等待条件和预算都应明确。

7. 执行证据与测试范围​

一条失败应能追溯到测试版本、环境、输入、请求标识、原始响应和相关业务记录。日志应脱敏,避免把认证凭证直接写进报告;重试后通过也应保留首次失败与尝试次数。

接口自动化可以快速组合身份、输入和状态,但不会执行浏览器的 DOM、事件处理或页面渲染。UI 测试能够检查用户看到的行为,却难以经济地覆盖所有服务端异常组合。应按验证对象安排层次,通用原则见 测试金字塔。

图形请求工具也可以保存集合、参数化并参与自动化。选择脚本不是为了证明工具不够专业,而是看是否需要复杂准备、代码复用、并发控制、版本审查和持续集成。关键是同一份契约能否形成清晰、稳定的检查。

8 · 面试题卡片​

本页题目与参考回答

8.1 设计接口测试时应覆盖哪些维度?​

考察重点:契约、输入、身份、状态和副作用。

相关内容:契约与测试条件、多层断言。

参考回答

从接口契约出发,覆盖请求表示、有效与无效输入、身份权限、业务状态、成功和失败结果。 再根据接口副作用补重复请求、并发与异步场景。

每个维度都要有可核对结果,例如错误请求不落库、创建成功后能读到正确归属的记录。Schema 只能覆盖结构,不能替代权限和业务断言。

8.2 接口自动化为什么不能只断言 HTTP 200?​

考察重点:响应结构、业务语义与最终状态。

相关内容:多层断言。

参考回答

HTTP 200 只表示这一层的成功响应,不保证业务字段、资源归属或持久化结果正确。 应按契约检查准确状态、内容类型、关键字段和必要的状态变化。

负例也要断言约定错误及无副作用,不能把任何非 200 都算正确拒绝。具体断言范围由用例目标决定,避免既漏关键状态又过度依赖内部实现。

8.3 怎样按角色设计文章发布接口的权限测试?​

题型:综合题

考察重点:身份、资源归属、动作与非法状态。

相关内容:契约与测试条件、权限与资源归属。

参考回答

用同一个资源分别验证本人、其他用户、未登录者和各授权角色的操作结果。 同时组合草稿、已发布等状态,权限与状态规则都以契约为准。

不要只检查是否登录,还要测试修改资源 ID、伪造作者字段等越权路径。拒绝后确认没有泄露内容或改变记录,管理员权限也不能未经规则确认就全部放行。

8.4 一套接口自动化用例怎样做到独立执行和可靠清理?​

考察重点:可重建前置、资源标识、失败路径与清理结果。

相关内容:最小自动化实现。

参考回答

为每项测试建立明确前置和独立数据,用生命周期管理准备与清理,并在失败路径保留已知资源标识。 不依赖另一条测试先运行或留下记录。

请求与等待都设置合理预算,清理失败单独报告,残留数据可按运行标识追查。断言来源于契约,还应通过错误响应验证测试确实能够失败。

8.5 怎样检查接口幂等性,并让多个请求竞争同一个资源?​

题型:综合题

考察重点:重复业务效果、竞争时序与最终不变量。

相关内容:多层断言、重复、并发与异步。

参考回答

幂等检查重试后是否只产生一次预期业务效果;并发检查竞争共享状态后是否仍满足业务规则。 相同键相同内容、相同键不同内容和新键操作应分别按契约验证。

并发请求可用屏障协调发出,并用服务端证据确认目标竞争窗口。最后核对成功数量、库存或余额、关联记录和重复副作用,不能只比较响应文本或统计线程数。

8.6 异步创建接口返回 202 后,应怎样验证最终成功?​

考察重点:接受与完成、终态、总期限及证据。

相关内容:重复、并发与异步。

参考回答

先取得任务标识,再按约定在总期限内等待成功或失败终态,成功后核对实际产物。 202 只说明请求被接受,不能直接视为业务完成。

每次查询应有超时,整体等待也要有上限。失败或超时时保留任务状态历史和日志,不能靠固定睡眠猜完成时间或无限重试掩盖问题。

8.7 接口自动化与 UI 自动化分别能发现什么问题?​

考察重点:验证边界、成本与互补关系。

相关内容:执行证据与测试范围。

参考回答

接口测试直接验证服务交互,适合大量输入、权限、状态及异常组合;UI 测试验证用户可见的页面交互和完整流程。 接口通过不能证明按钮绑定、页面状态和浏览器兼容正确。

UI 的准备与定位成本更高,也不适合穷举服务端全部边界。把规则检查放到能有效发现问题的较小范围,再用关键 UI 流程补真实协作证据。

8.8 怎样验证一个直播间的弹幕不会出现在另一个直播间?​

考察重点:业务范围、正向对照和负向观察的边界。

相关内容:业务数据隔离。

参考回答

建立两个已确认订阅完成的观察端,向 A 房间发送带唯一标识的弹幕,同时核对 A 收到、B 未收到。 只看到 B 没有消息还不够,A 的正向结果证明发送链路确实工作。

按约定设置观察窗口,并补切换、重连和旧订阅清理场景。保留消息标识、订阅关系与路由日志;有限窗口中的未观察结果不能单独证明不存在延迟泄漏。

9. 参考资料​

来源:Coding 101 原文 · 免费阅读,引用请保留出处。内容使用说明