测试智能体实战: 云服务 Redis 5.0 升级 7.0 全流程
智能体测试系统架构把"AI 参与测试"拆成了七个阶段,这篇用一句话把它们归拢成测试工程师熟悉的三个词,再用一个完整案例——公司云服务把 Redis 从 5.0 升级到 7.0——走一遍每个阶段智能体怎么用、产出什么。
三个词与七阶段的对应关系
阶段 |
包含的七阶段环节 |
核心问题 |
主要产出 |
|---|---|---|---|
测试策略 |
1 需求理解 |
测什么、不测什么、风险在哪、怎么算通过 |
需求点清单 + 测试策略契约(JSON) |
测试设计 |
2 用例生成、3 用例评审、4 脚本生成 |
怎么测、用什么数据、怎么断言 |
编号化用例、分级评审意见、可执行脚本 |
测试执行 |
5 用例执行(传统框架,非 AI)、6 失败分诊、7 报告生成 |
实际结果是什么、失败是谁的问题、能不能发布 |
执行结果、分诊结论、测试报告 |
三条贯穿全程的纪律(出处见架构篇,案例里每一步都会体现):
阶段间只传结构化契约,不传对话历史——下游永远面对确定的 JSON;
生成与评审分离,用不同模型/不同会话,防止"自己认可自己";
强制证据:预期结果必须引用文档原文出处,文档没写的标"需澄清",不许编造。
案例背景
公司云数据库服务(多租户、按实例计费、主从+哨兵架构)计划把引擎从 Redis 5.0 升级到 7.0。输入给测试智能体的材料:
docs/requirements/redis-7-upgrade.md # 升级需求: 在线热升级、数据不丢、租户无感
docs/api/redis-cloud-openapi.yaml # 云服务控制台 API(创建/升降级实例等)
docs/redis/5-to-7-changelog.md # 官方 release notes 整理(兼容性变更清单)
tests/cases/ # 历史用例库(5.0 时代的存量用例)
docs/errcode/redis-cloud.md # 云服务错误码表
升级的技术风险点(这部分是领域知识,人来准备,写进需求文档):
兼容性: 废弃命令(
SLAVEOF→REPLICAOF、BRPOPLPUSH→BLMOVE)、行为变更(部分命令返回错误码变化)、RESP3 协议默认不启用但客户端可能协商;数据: RDB/AOF 版本兼容(7.0 能读 5.0 的 RDB,反之不行——回滚路径是高危点);
新特性是否开放: Function(
FCALL)、Sharded Pub/Sub、ACL v2 selector——多租户云服务通常要禁用或隔离,这本身就是测试点;云服务特有: 在线升级过程的连接闪断、升级中实例的配额/计费一致性、控制台"升级中"状态机、多租户隔离不因升级破防。
第一阶段: 测试策略(对应阶段 1 需求理解)
智能体干什么: 读齐所有输入材料,把"升级 Redis"这件模糊的事拆成结构化需求点清单,并给出策略判断——范围、优先级、不测什么、通过标准。
Prompt(模板库中的 strategy 模板填槽后)
你是资深云服务测试专家。阅读以下材料:
- docs/requirements/redis-7-upgrade.md
- docs/redis/5-to-7-changelog.md
- docs/api/redis-cloud-openapi.yaml
- docs/errcode/redis-cloud.md
为 Redis 5.0 → 7.0 升级输出测试策略, 保存为 tests/strategy/redis-7.json, 要求:
1. 需求点清单: 每条含 id / 描述 / 出处(文件+章节) / 风险等级(P0-P2) / 建议测试类型
2. 策略判断: 测试范围、明确不测的项(给理由)、环境拓扑、发布通过标准(量化)
3. 兼容性变更逐条列出: 废弃命令、行为变更、协议变更, 每条标注对存量租户的影响面
4. 文档没明确说明的行为, 标 "需澄清" 并列出向谁澄清, 不许编造
5. 只输出符合 schema 的 JSON
输出: 测试策略契约(节选)
{
"requirement_points": [
{"id": "RP-01", "desc": "实例在线热升级, 数据零丢失, 业务连接闪断 < 5s",
"source": "docs/requirements/redis-7-upgrade.md#2.1", "risk": "P0",
"test_types": ["功能", "可靠性", "性能"]},
{"id": "RP-02", "desc": "废弃命令 SLAVEOF/BRPOPLPUSH 的兼容策略: 代理层映射或拒绝",
"source": "docs/redis/5-to-7-changelog.md#deprecated", "risk": "P0",
"test_types": ["兼容性"], "note": "需澄清: 需求文档未说明代理层是否做命令映射, 找架构组确认"},
{"id": "RP-03", "desc": "新命令 FCALL/FUNCTION 在多租户下禁用, 调用返回明确错误码",
"source": "docs/requirements/redis-7-upgrade.md#4.3", "risk": "P1",
"test_types": ["功能", "安全"]},
{"id": "RP-04", "desc": "升级失败可回滚到 5.0, 回滚后数据与升级前一致",
"source": "docs/requirements/redis-7-upgrade.md#2.4", "risk": "P0",
"test_types": ["可靠性"], "note": "高危: 7.0 写的 RDB 5.0 读不了, 回滚依赖升级前快照"}
],
"scope": {
"in": ["兼容命令集", "在线升级流程", "回滚", "控制台 API 状态机", "配额计费一致性", "多租户隔离", "性能回归基准"],
"out": [
{"item": "Redis Cluster 模式", "reason": "本期产品只卖主从+哨兵形态"},
{"item": "RESP3 协议", "reason": "服务端默认不启用, 客户端兼容由客户端团队负责"}
]
},
"environment": "3 套: 5.0 存量实例池 / 升级中实例 / 7.0 新实例池, 每套 3 租户",
"pass_criteria": "P0 用例 100% 通过; P1 ≥ 95%; 性能回归(基准 ops/sec)退化 < 3%; 升级过程数据一致性校验零差异"
}
人的动作: 评审策略契约——重点看 out(不测的项)和 需澄清 条目,这些是 AI 最容易"默默漏掉"的地方。澄清结论(如"代理层做 SLAVEOF→REPLICAOF 映射")回填需求文档后,策略阶段重跑——DAG 节点缓存机制下,只有这一个节点重算。
第二阶段: 测试设计(阶段 2-4)
步骤 2.1 用例生成(阶段 2)
你是资深云服务测试专家。阅读 tests/strategy/redis-7.json 中 RP-01~RP-04 及引用文档,
为每条需求点设计用例, 保存到 tests/cases/redis-7-upgrade.md, 要求:
1. 每个需求点按矩阵展开: 正常流 / 边界 / 权限(跨租户越权) / 升级中状态 / 回滚路径
2. 兼容性专项: 5-to-7-changelog.md 中每条废弃/变更命令各一条用例, 断言 5.0 与 7.0 行为差异
3. 每条用例: 编号 / 关联需求点 / 前置条件 / 步骤 / 预期结果 / 优先级
4. 预期结果必须引用文档原文出处; 文档没写的标 "需澄清", 不许编造
输出: 用例文件(节选)
编号 |
需求点 |
用例 |
预期结果 |
优先级 |
|---|---|---|---|---|
TC-0101 |
RP-01 |
实例写入 10 万 key 后触发在线升级, 升级前后逐 key 校验 |
数据零差异; 闪断期间客户端自动重连成功(出处: 需求文档 2.1) |
P0 |
TC-0201 |
RP-02 |
5.0 和 7.0 实例分别执行 |
7.0 返回 "unknown command" 或被代理映射为 REPLICAOF(需澄清, 依赖 RP-02 澄清结论) |
P0 |
TC-0207 |
RP-02 |
7.0 实例执行 |
与 changelog 记录的废弃行为一致(出处: changelog#deprecated) |
P1 |
TC-0301 |
RP-03 |
租户 A 执行 |
返回云服务错误码 |
P1 |
TC-0302 |
RP-03 |
租户 A 通过 ACL 尝试给自己加 FCALL 权限后调用 |
仍被拒; 且不影响租户 B(越权隔离) |
P1 |
TC-0401 |
RP-04 |
升级中注入失败(杀掉 7.0 节点), 触发回滚 |
回滚到 5.0, 数据 = 升级前快照(出处: 需求文档 2.4) |
P0 |
TC-0501 |
RP-01 |
升级中查询实例配额与计费计量 |
计量不中断、不重复计费(需求文档未说明计量精度, 需澄清) |
P1 |
步骤 2.2 用例评审(阶段 3, 换模型评审)
claude -p "你是测试评审员, 只审 tests/cases/redis-7-upgrade.md, 不修改任何文件。
对照 tests/strategy/redis-7.json、docs/redis/5-to-7-changelog.md 和错误码表逐项检查:
1. 遗漏: 哪些需求点/废弃命令/错误码没有对应用例
2. 错误: 哪些预期结果与文档矛盾或无出处
每条意见给出 文档出处 + 用例编号, 按 阻断/建议 分级, 不写客套话" \
--dangerously-skip-permissions --allowedTools "Read,Grep,Glob" \
> tests/cases/redis-7-upgrade.review.md
输出: 评审意见(节选)
[阻断] TC-0201 的预期结果仍是"需澄清", 但 RP-02 的澄清结论已回填需求文档 3.2 节
(代理层映射), 用例未同步更新。出处: docs/requirements/redis-7-upgrade.md#3.2
[阻断] changelog#protocol 列出 "SUBSCRIBE 在事务上下文中行为变更", 无用例覆盖。
[建议] TC-0101 只校验 key 内容, 建议补充 TTL 与 expire 存活校验(7.0 对过期
删除时机有内部调整, 出处: changelog#expiry)。
[建议] 缺性能回归用例: 策略 pass_criteria 要求 ops/sec 退化 < 3%, 无用例对应。
评审意见喂回生成方修订一到两轮,定稿(人工确认)后进入脚本生成。
步骤 2.3 脚本生成(阶段 4)
根据 tests/cases/redis-7-upgrade.md 中 P0/P1 用例, 生成 pytest 测试脚本,
保存到 tests/api/test_redis7_upgrade.py, 要求:
- 框架 pytest + redis-py, 连接信息从环境变量读取
- 每个测试标注对应用例编号, 方便回溯
- 禁止修改用例文件和策略 JSON
输出: 可执行脚本(节选)
import os, redis, pytest
def conn(ver): # REDIS_50_URL / REDIS_70_URL
return redis.Redis.from_url(os.environ[f"REDIS_{ver}_URL"])
def test_tc_0201_slaveof_removed():
"""TC-0201: 7.0 上 SLAVEOF 行为(直连引擎, 绕过代理层验证兜底)"""
r7 = conn("70")
with pytest.raises(redis.ResponseError):
r7.execute_command("SLAVEOF", "127.0.0.1", 6379)
def test_tc_0301_fcall_disabled_for_tenant():
"""TC-0301: 多租户下 FCALL 返回云服务错误码"""
r = conn("70")
with pytest.raises(redis.ResponseError, match="Redis.CommandDisabled"):
r.execute_command("FCALL", "mylib", 1, "k")
@pytest.mark.p0
def test_tc_0401_rollback_data_consistency(upgrade_fixture):
"""TC-0401: 注入升级失败, 回滚后数据等于升级前快照"""
before = snapshot_keys(conn("50"))
upgrade_fixture.inject_failure(node="redis7-new")
upgrade_fixture.wait_rollback()
assert snapshot_keys(conn("50")) == before
第三阶段: 测试执行(阶段 5-7)
步骤 3.1 执行(阶段 5, 非 AI)
执行用传统测试框架和执行机,智能体不参与判断对错——这是架构篇的明确边界: 执行是确定性工作,AI 的价值在上下游的设计与归因。执行机跑完产出原始结果:
collected 47 items
tests/api/test_redis7_upgrade.py::test_tc_0201_slaveof_removed PASSED
tests/api/test_redis7_upgrade.py::test_tc_0301_fcall_disabled_for_tenant FAILED
tests/api/test_redis7_upgrade.py::test_tc_0401_rollback_data_consistency FAILED
===== 2 failed, 45 passed in 312.4s =====
步骤 3.2 失败分诊(阶段 6)
kimi -p "你是云服务测试失败分诊专家。下面是 Redis 7 升级测试的失败日志和最近 20 条提交。
只输出一个 JSON 对象, 不要 markdown 代码块:
{\"root_cause\": \"一句话根因\", \"evidence\": \"关键日志原文\",
\"suspect_commits\": [\"hash\"], \"is_flaky\": true/false,
\"confidence\": 0到1, \"suggested_owner\": \"嫌疑模块\", \"next_action\": \"建议下一步\"}
日志:
$(tail -n 800 ci-failure.log)
最近提交:
$(git log --oneline -20)"
输出: 分诊结论
[
{"case": "TC-0301",
"root_cause": "FCALL 未被禁用而是返回了 Redis 原生 NOAUTH 错误, 疑似代理层命令黑名单配置未下发到 7.0 实例组",
"evidence": "redis.ResponseError: NOAUTH Authentication required (期望 Redis.CommandDisabled)",
"suspect_commits": ["a1b2c3d (proxy: command filter 支持按引擎版本分组)"],
"is_flaky": false, "confidence": 0.85,
"suggested_owner": "proxy-gateway",
"next_action": "检查 proxy 命令过滤配置对 engine_version=7.0 分组是否生效"},
{"case": "TC-0401",
"root_cause": "回滚后丢失升级窗口内写入的 3 个 key, 快照机制只覆盖升级前数据",
"evidence": "AssertionError: missing keys {'w:1001','w:1002','w:1003'} — 均为 upgrade_window 期间写入",
"suspect_commits": [], "is_flaky": false, "confidence": 0.95,
"suggested_owner": "upgrade-orchestrator",
"next_action": "这是产品设计问题而非实现 bug: 回滚语义需明确'升级窗口写入是否保留', 升级需求文档"}
]
注意第二条: suggested_owner 指向了需求文档——分诊把"实现 bug"和"需求没定义清楚"区分开,这正是强制证据纪律的回报。confidence 低的条目人工深挖,这两条高置信度直接转缺陷单/澄清单。
步骤 3.3 报告生成(阶段 7)
根据本次执行结果与分诊结论(附 JSON), 生成 Redis 7 升级测试报告,
保存到 reports/redis-7-upgrade-2026-W42.md, 要求:
1. 按策略契约的 pass_criteria 逐条判定: 达成/未达成/无法判定(给原因)
2. 每个未达成项附: 用例编号 + 分诊结论 + 缺陷单链接占位
3. 给出发布建议: 通过 / 有条件通过(列条件) / 不通过
输出: 报告结论(节选)
发布建议: 不通过(P0 阻断 2 项)
| 通过标准 | 结果 | 证据 |
|---------|------|------|
| P0 用例 100% 通过 | 未达成 | TC-0301(缺陷: proxy 黑名单未对 7.0 生效)、TC-0401(回滚丢升级窗口数据) |
| 性能退化 < 3% | 达成 | 基准 142k ops/sec vs 5.0 的 138k, 无退化 |
| 升级数据一致性零差异 | 未达成 | TC-0401 见上 |
需产品决策: 回滚语义是否承诺保留升级窗口写入(RP-04 的语义边界), 决策后更新
需求文档并重跑 RP-04 相关节点。
收尾: 沉淀回流(飞轮转一圈)
案例跑完不是结束,按"沉淀触发器"纪律,复盘时只问一句"这次有什么值得固化":
本次经验 |
沉淀到哪 |
|---|---|
"Redis 类引擎升级测试, 回滚语义必须显式定义升级窗口写入" |
知识层: |
"代理层配置按引擎版本分组下发" 这个失败模式 |
模板层: 分诊 prompt 加一行判断提示; 长期进 golden 集 |
人工定稿的用例与分诊结论 |
抽 10% 回流 golden 评测集, 下次换模型时回归用 |
TC-0201 这类"依赖澄清结论"的用例写法 |
模板层: 用例生成模板增加"引用需求点澄清状态"字段 |
总结
测试策略回答"测什么": 智能体读齐材料产策略契约,人审
out和需澄清;测试设计回答"怎么测": 生成-评审对抗出用例,再落成脚本,全程编号可回溯;
测试执行回答"结果怎样": 执行交给传统框架,AI 只做失败分诊与报告——判断对错的权力(oracle)不外包给 AI,这是三个阶段共同的底线。
参考资料
智能体测试系统架构: 多智能体协作与模型可替换设计——七阶段契约、三种拓扑、golden 集
云服务测试的 AI 转型——用例生成/评审/分诊的 prompt 模板原型
Agent 测试系统的意义与"通用 DAG"辨析——为什么测试骨架该用 DAG 定死