e2e-testing

对真实运行系统做端到端验证:按业务旅程编排步骤、跨步骤共享状态,验证跨组件最终一致状态。触发:"跑一遍完整流程看看对不对"、"真实链路测试"、"端到端验证"、"全链路验证"、"检查跨系统终态"。

SKILL.md

GitHub

端到端真实操作测试(e2e-testing)

概述

目的:把"端到端验证"从手点多系统、肉眼比对,变成"AI 读旅程、编排步骤、跑真实操作、验跨组件终态"。针对真实运行中的系统执行完整业务旅程(注册→下单→支付→查状态…),验证代码实现是否符合需求/设计规格(黑盒验收),而非"代码能跑通就行"。

两个验证维度:

  • 断言式 e2e(基础):预设 Scenario/Step/assert,跑真实链路验正确性(PASS/FAIL)。见「工作流程」。
  • 动态体验验证(增强):e2e 通过后,agent 像真人一样操作系统,观察并评估体验质量、发现断言覆盖不到的问题。见「动态体验验证」。

验收定位(黑盒 · 需求驱动):

  • e2e 是黑盒验收:断言锚定需求/设计文档,而非代码内部实现。只关心「给定入参 → 返回/副作用是否符合规格」,不读内部函数、不依赖内部状态、不为迎合实现而写断言。
  • 与单元测试划界:单测验证内部逻辑(白盒、可 mock、快);e2e 验证对外契约与跨组件终态(真实链路、不 mock、慢)。两者物理分离(见「目录与隔离」)。

与 api-testing 的关系:api-testing 聚焦单个 HTTP 接口的"连通性 + 业务断言",彼此隔离、数据是构造的。本技能不重复实现接口测试,而是在 api 类步骤上仅引用 api-testing 已文档化的约定(响应结构、业务断言、凭证脱敏、报告风格),把其能力作为 e2e 编排中的一个动作类型。具体约定见下文「与 api-testing 的约定引用」与 reference.md。

使用场景:

  • 用户说"帮我跑一遍完整下单流程""做个端到端验证""真实链路测试一下"
  • 需要验证跨系统终态:下单后 DB 是否落库、消息是否发出、库存是否扣减
  • 一个操作的输出要喂给后续操作(如建出的 user_id 用于下单)
  • 涉及真实副作用且需要 setup/teardown 与确认门禁
  • 动态体验:e2e 通过后,用户说"帮我体验一下这个功能好不好用""验收一下真实体验""看看反馈够不够全面"→ 走「动态体验验证」流程

何时不使用本技能(反例,避免误用):

  • 只想测单个 HTTP 接口(连通性 + 单接口业务断言)→ 用 api-testing
  • 系统尚未运行 / 无需真实环境(纯逻辑、可 mock)→ 用单元测试(快、隔离)
  • 只要浏览器冒烟(页面能打开、无崩溃)→ 轻量 UI 检查即可,无需完整旅程编排
  • 对存量前端做体验体检(点一遍挑体验问题 / 看加载性能,非验收场景)→ 用 frontend-walkthrough
  • 只做静态验证(格式 / 配置 / 规则检查)→ 用对应专项工具,e2e 编排是过度设计

目录与隔离(tests/e2e)

e2e 测试产物必须与单元测试物理分离,避免被单测 CI 误跑、误用配置或混入白盒用例。

  • 约定目录:所有 e2e 场景定义、生成的客户端/脚本、运行产物与报告统一放在 tests/e2e/(不要放在 tests/、test/、__tests__/ 等单测目录,也不要与单测文件同目录)。
  • 单测排除 e2e:单元测试套件不得执行 tests/e2e/。按所用框架配置排除:
    • pytest:在 pyproject.toml/pytest.ini 加 norecursedirs = tests/e2e,pytest 收集时跳过该目录(单测目录本身用 testpaths 指向,如 testpaths = ["tests/unit"]);CI 中 e2e 单独以 pytest tests/e2e 运行。
    • unittest(Python):discover 时指定单测目录/ pattern,e2e 单独 discover tests/e2e。
    • Node(jest/vitest):testPathIgnorePatterns 加入 tests/e2e,e2e 用独立 testMatch 或脚本运行。
    • 通用:CI 拆两个 job——unit(快、隔离)与 e2e(需真实环境 + .env.e2e),互不影响。
  • env 文件不入库(.env.e2e 优先、回退 .env):见「敏感信息外部化」。

需求绑定(requirement_ref)

e2e 是验收型测试,判据必须来自需求/设计,而非代码。每个 Scenario 必须绑定需求来源:

  • 输入即需求文档:执行 e2e 前,先确定被判定的需求/设计文档(或对话中明确的需求条目)。若用户未提供需求来源,须确认,不臆测终态。
  • requirement_ref 字段:Scenario 顶层声明 requirement_ref(如 REQ-register-order),指向需求条目 ID;场景内的断言应可追溯到该规格。
  • 断言对照规格:写 assert 时以需求描述的"给定 X 应得到 Y"为判据,只校验入参→返回/副作用,不引入对代码内部实现的假设。
  • 写断言前不读实现代码:AI 应仅依据需求文档 + 对外接口契约(入参/返回)编写 assert,避免先读源码再写"能通过"的断言,防止迎合实现而非验收需求。

核心概念

💡 本技能是给 AI 的编排规范,而非被独立引擎解析执行的 DSL:下方 Step / Context / ${ctx.x} 是 AI 的认知与编排框架。AI 在运行时按约定自行选择工具并实现每一步(如 api 步骤选 httpflex 或项目自有客户端、db 步骤选对应驱动),而非由某解析器机械读取 YAML。文档中的 YAML 示例仅用于表达"意图与结构"。

1. Scenario(业务旅程)

一次完整验证的目标,例如"用户注册并下单"。必须绑定需求/设计文档(见「需求绑定」):包含 requirement_ref(对应需求条目 ID)、env(环境信息,值来自 env 文件:.env.e2e 优先,回退 .env)、credentials(脱敏后的凭证,值来自 env 文件)、有序的 steps 列表。

2. Step(抽象可扩展步骤)

统一的步骤契约,使不同类型的动作能被同一引擎编排。完整字段见 reference.md:

- id: create_order
  type: api                      # 步骤类型(见下方目录)
  name: 创建订单
  depends_on: [register]        # 顺序/并行依赖(决定执行次序)
  config: { ... }               # 类型相关配置
  produces: [order_id]          # 执行后写回 Context 的键
  on_fail: abort                # abort(默认) / continue / retry
  assert: { ... }               # 可选内联断言

3. Context(跨步骤状态流转)—— 本技能灵魂

一张跨步骤共享的状态字典,让真实操作的输出在旅程中流动:

ctx = {
  env:        { base_url, env_name, ... },
  credentials:{ token, cookie, ... },   # 运行时会话内可持完整凭证以发起真实请求
  data:       { user_id, order_id, ... } # 业务实体,由 step.produces 写入
}

⚠️ 凭证脱敏边界:ctx.credentials 在 AI 运行会话内存中可持有完整 token/cookie(否则无法发起真实请求);仅在写入文件或展示给用户时做脱敏(只显前缀,如 Bearer eyJ…)。切勿将完整凭证写入 ctx.data 或任何落盘文件。

取值采用 A+B 结合:

  • A. 依赖顺序:depends_on: [register] 决定执行先后,并支持无依赖步骤并行。
  • B. 占位符取值:step 配置中用 ${ctx.data.user_id}(或简写 ${user_id} 优先解析 ctx.data)引用上游产出,执行前统一解析。
  • 详见 reference.md §Context。

4. Setup / Teardown(生命周期)

  • setup:旅程前准备(建测试租户、清旧数据、起依赖服务)。
  • teardown:旅程后清理(删测试数据、释放资源)。真实操作有副作用时强烈建议对称清理;缺失时必须在报告中提示。
  • 必须幂等:二者都应支持旅程重复执行——setup 先处理"数据已存在"、teardown 容错"数据已不存在",避免二次运行报错或污染。详见 reference.md §3.9/3.10。

5. Safety Gate(安全门禁,中等强度)

  • 写/删等危险操作需用户显式确认后才执行。
  • 不强制 dry-run,但提供 dry-run 预览(只打印将执行的操作,不落地)。
  • 环境可指定;若指向生产 → 强告警但不硬阻断。
  • 凭证脱敏:token/cookie 只在 Context 与报告中存前缀(如 Bearer eyJ…),不回显完整凭证。
    • 详见 reference.md §安全门禁。

敏感信息外部化(.env.e2e 主,兼容 .env)

🔐 与「凭证脱敏」互补:凭证脱敏管出口(报告/落盘不回显完整凭证);本节点管入口(测试定义文件里禁止出现真实 secret/endpoint)。

e2e 需要真实凭证才能发起请求,但测试定义文件(scenario/脚本)中禁止内联任何真实密钥、token、URL、DB 连接串等敏感信息:

  • 一律外部化到 env 文件:定义文件中只写变量引用,如 ${ENV.API_BASE_URL}、${ENV.API_TOKEN};真实值由运行时的 env 文件注入。
    • 首选 .env.e2e:避免与应用自身 .env 混淆,且应用默认的 .env 加载器不会自动加载它,天然隔离。若 .env.e2e 不存在,回退读取项目根 .env(兼容已有项目),此时 .env 视为 e2e 专用来源、不再被应用默认 .env 加载器当作应用配置。
    • 加载与解析:load_dotenv('.env.e2e')(若存在)否则 load_dotenv('.env')(python-dotenv)或等价方式;解析时机在旅程启动、阶段 2 之前:定义文件中的 ${ENV.XXX} 占位符先由 env 文件取值——ENV.API_BASE_URL → ctx.env.base_url、ENV.API_TOKEN → ctx.credentials.token(去掉 ENV. 前缀映射到 ctx.env / ctx.credentials),再由「Context 解析」统一处理 ${ctx.x}。定义文件本身始终保持无密。
    • 启动前自检:执行 e2e 前,AI 应确认实际使用的 env 文件未被 git 跟踪——git check-ignore .env.e2e(或回退时的 .env)有命中即安全;若被跟踪(无忽略),先提醒用户将其加入 .gitignore,避免密钥误入库。
  • 提供模板 .env.e2e.example:列出所有需要的键(如 API_BASE_URL=、API_TOKEN=),留空或填占位,提交入库供他人复制为 .env.e2e(回退 .env 时同样可复制为 .env)。
  • env 文件必须 gitignore:绝不提交真实的 .env.e2e / .env;在 .gitignore 中加入 .env.e2e(及广义敏感项),仅 .env.e2e.example 入库。
  • 禁止项:definition/脚本里不得出现 base_url: "https://prod..."、token: "Bearer eyJ真实串"、password: "..." 等字面值;host、key/secret 均从 env 文件取。

工作流程(7 阶段)

[0]解析意图 → [1]拆 step+依赖 → [2]setup+建 Context → [3]按序/并行执行
   → [4]跨步断言+终态校验 → [5]teardown → [6]出 journey 报告

阶段 0:解析测试意图

  • 定位需求来源:按「需求绑定」章节确认被判定的规格并记录 requirement_ref;用户未提供需求来源时须确认,不臆测终态。
  • 提取目标业务旅程、涉及的环境与凭证(按「敏感信息外部化」约定从 env 文件注入,缺失须确认)、期望终态(如"订单落库且库存-1",须可追溯至需求条目)。

阶段 1:拆解为 Scenario + Steps

将旅程拆成步骤,标注每个 step 的 type 与 depends_on,并标出哪些 step 产出哪些 key(produces)供下游 ${ctx.x} 引用。具体用哪些类型由被测功能决定(不预设固定集)。

  • 有索引时先用(挑关键路径 + 定终态校验点):仓库已建 .fe-index/ → use_skill("index-lookup") 读 INDEX.md 匹配涉及文件——前端 apis/*.md / pages/*.md 给出"这个操作走哪些接口",后端 tables.md / modules/*.md 给出"终态该落在哪张表、哪些模块会连带变",据此选跨组件断言点;无索引 / 未命中 / 过期 → 按原流程,不阻塞

阶段 2:搭建 Context(执行 setup)

先跑 setup 类步骤,初始化 ctx.env / ctx.credentials / ctx.data。

阶段 3:按序 / 并行执行 Steps

  • 按 depends_on 拓扑排序;无依赖链的步骤可并行。
  • 执行前解析 ${ctx.x} 占位符。
  • api 类步骤遵循 api-testing 约定发请求并做业务断言。
  • 异步/最终一致处用 wait 步骤轮询,直到条件满足或超时。
  • 失败处理:默认 abort 整个旅程(后续步骤依赖前置状态);独立探针标 continue;抖动标 retry。
  • 根因不明时转排错:失败若非编排配置问题(produces/depends_on 写错、断言口径错),而是疑似服务逻辑、环境、数据状态或异步时序导致,调用 use_skill("debug") 定位根因——本 skill 判定「是否失败」,不负责定位「服务为什么失败」。

阶段 4:跨步断言 + 终态校验

  • 每个 step 的内联 assert 在自身执行后校验。
  • 独立的 assert 步骤可做跨 step 的终态比对(如"DB 状态 == API 返回状态")。
  • db / mq 类步骤直接验证真实落地(落库行、发布事件)。

阶段 5:Teardown 清理

执行 teardown 类步骤,回滚/清理真实副作用;缺失则报告中显式提示。

阶段 6:出 Journey 级报告

按下方模板输出(风格对齐 api-testing)。

Step 类型目录(概览,契约见 reference.md)

类型 用途 典型 produces
api HTTP 调用(遵循 api-testing 约定) 响应 data 中的业务键
db 数据库查询/执行,校验真实落库 查询结果/受影响行
ui 浏览器交互(真实页面) 提取的 DOM 值/状态
mq 消息发布/消费,校验事件真实发出 收到的消息
cli 命令行/脚本执行 stdout/exit code
wait 轮询条件直到满足/超时(异步最终一致) 轮询结果
assert 纯跨步校验,无副作用 无
transform 纯计算/派生值写入 ctx,无副作用 派生键
setup 旅程前准备 测试数据/环境句柄
teardown 旅程后清理 无

目录为示例且可扩展:被测功能需要其他真实操作类型时,按统一 Step 契约新增即可。

与 api-testing 的约定引用

当 step.type == api 时,引用(不运行时调用)api-testing 技能(skills/api-testing)已文档化的规范:

  1. 响应结构:归一化为 { result: bool, code: int, message: str, data: any };失败也返回结构不抛异常。
  2. 业务断言:不仅看 code,还要校验 data 的字段存在性 / 类型 / 取值(可取嵌套 data.user.name)。仅借鉴该断言思路(校验 data 而非只看 code),具体 HTTP 客户端由被测项目的工具决定,不强依赖 httpflex——可用的库都可(项目自有客户端、requests、httpx 等),只要产出归一化的 {result,code,message,data} 结构供本技能做 assert 即可。
  3. 凭证脱敏:token/cookie 只显前缀,不回显完整凭证。
  4. 报告风格:明细表 + 失败根因,与本技能 journey 报告对齐。

若项目已用 httpflex-py,可直接照搬 api-testing/reference.md 的客户端模板生成 api 步骤客户端;否则按项目既有方式发请求,只需遵循上述响应结构与业务断言约定。本技能只负责编排与状态流转,不绑定具体 HTTP 实现。

报告模板(Journey 级)

# E2E 测试报告:{scenario 名}

## 概览
- 通过步骤:X / 总 Y(teardown 不计入判定)
- 环境:staging.api.x.com(env_name: staging)
- 旅程状态:✅ PASS / ❌ FAIL(abort 于 step: create_order)

## 明细
| 步骤 | 类型 | 状态 | 关键 evidence | 失败根因 |
|------|------|------|---------------|----------|
| register | api | ✅ | code=201, data.id=123 | — |
| create_order | api | ✅ | code=201, order_id=789 | — |
| db_check | db | ✅ | row exists, status=created | — |
| mq_check | mq | ❌ | 未收到 order.created | 事件未发布/主题不匹配 |
...

## 副作用清单(供审计/teardown)
- 已创建:user_id=123, order_id=789
- 已清理:teardown 删除上述数据 ✅ / ⚠️ 未清理,请手动处理

## 建议
- mq_check 失败:检查订单服务是否确实发布 order.created 事件。

动态体验验证(增强维度)

定位

断言式 e2e 验证"功能对不对"(预设断言 PASS/FAIL);动态体验验证在 e2e 通过后,验证"用起来好不好"——agent 像真人 QA / 体验官,在真实环境亲手操作、观察、判断,发现断言覆盖不到的体验问题(反馈不全、错误提示不友好、可优化点)。

与断言式 e2e 的关系:动态体验是断言式 e2e 的进阶层,不是替代。两者共享真实环境、setup/teardown、安全门禁、敏感信息外部化等基础设施,但驱动方式不同:

维度 断言式 e2e 动态体验验证
驱动 断言驱动(预设 expected,比对 actual) 观察驱动(无预设断言,边做边看)
产物 tests/e2e/ 可复跑脚本 不落盘代码,产出体验观察记录 + 报告
判定 PASS / FAIL 符合预期?+ 体验质量 + 优化建议
路径 预设旅程 + 设计边界 白盒规划覆盖 + 主动探索负面路径
关注 结果正确性 正确性 + 反馈全面性 + 错误反馈友好度 + 可优化点

核心原则:白盒规划 + 黑盒体验(铁律)

  • 白盒规划:体验计划阶段读代码实现,识别每个分支/功能点,规划要体验的路径,确保覆盖完整(不遗漏代码里的分支)。
  • 黑盒体验:体验执行阶段像真人操作 + 观察,不读代码内部,对错由需求规格 + 合理用户预期决定。
  • 边界铁律:读代码只为规划覆盖路径,不为写判据。体验执行时若读代码迎合实现,会破坏验收根基。

与断言式 e2e「写断言前不读实现代码」原则的关系:断言式 e2e 完全不读代码(防迎合实现写断言);动态体验只在规划阶段读代码(识别分支确保覆盖),执行阶段同样不读代码。两者在"判据不来自代码"上一致。

前置门禁:e2e 先通过

动态体验必须在断言式 e2e 通过后进行:

  • 先跑与本次体验范围对应的 e2e 场景(不必全量无关场景),必须全部 PASS。
  • 不通过 → 停止体验,先修 e2e 暴露的正确性问题。基本正确性没保证时,谈体验质量无意义。
  • 通过 → 进入分批体验循环。
  • 无对应 e2e 场景时(新功能/未覆盖模块):至少跑通基本冒烟(核心路径可达)后再体验,并在体验报告中标注"未经 e2e 验证",提示结论置信度。

工作流程(分批循环)

[前置门禁] 对应范围 e2e 全 PASS
    ↓ 不通过 → 停止,先修正确性问题
[分批循环] 每个批次:
    ① 体验计划(白盒):读代码 → 识别分支/功能点 → 出本批体验计划
    ② 体验执行(黑盒):按计划操作+观察 → 正面/边界/负面路径
    ③ 体验评估:正确性 + 反馈全面性 + 错误反馈友好度 + 可优化点
    ④ 用户确认 → 下一批
[产出] 体验报告

阶段 D0:前置门禁

  • 确定本次体验的功能范围,跑对应 e2e 场景,必须全 PASS。
  • 确认环境与凭证(沿用「敏感信息外部化」约定)。

阶段 D1:体验计划(白盒,分批)

  • 读代码:按批次范围阅读功能实现代码,识别分支/功能点(if/else、错误处理路径、不同输入路径、边界条件等)。
  • 映射为体验点:每个代码分支 → 对应的用户可感知行为 → 设计一个体验动作。
  • 规划路径:每个体验点覆盖正面(正常操作)、边界(极端输入)、负面(故意错误操作)三类。
  • 分批:代码庞大时按模块/功能域分批,体验计划分批创建——每批先出该批计划,执行确认后再规划下一批,不一次性规划全部。每批 ≤8 个体验点为宜(超出则拆分)。
  • 计划内容:分支清单 → 体验动作 → 预期体验(正确性 + 体验关注点)→ 负面路径设计。模板见 reference.md。

阶段 D2:体验执行(黑盒)

  • 像真人操作:按计划亲手配置、启动、操作(发请求、点 UI、看日志),不读代码内部。
  • 执行隔离约束:以用户视角操作,不引用 D1 读到的内部实现细节;观察到的异常即便代码里有对应处理(如 try-except 吞异常),仍按用户感知评估(用户看不到内部处理,只看到结果)。
  • 即时观察:边操作边记录输出——返回结构、提示信息、响应速度、错误反馈。
  • 负面路径:故意执行错误操作(输错密码、非法参数、越权请求),观察系统反馈是否合理、友好。
  • 不落盘代码:agent 运行时即时操作,不生成可复跑测试脚本(区别于断言式 e2e)。

阶段 D3:体验评估

对每个体验点,从四个维度评估:

  • 正确性:结果是否符合需求规格(仍锚定需求,不锚定代码)。
  • 反馈全面性:返回/提示信息是否充分(字段、上下文、下一步引导)。
  • 错误反馈友好度:负面路径下,错误提示是否清晰、可操作(而非含糊/技术化/无引导)。
  • 可优化点:即使正确,是否有体验改善空间(冗余步骤、信息缺失、交互不顺)。

阶段 D4:确认与下一批

  • 每批体验完,输出该批体验小结,用户确认后再规划下一批。
  • 全部批次完成 → 汇总为体验报告。

安全门禁(沿用 e2e + 负面路径约束)

动态体验沿用断言式 e2e 的安全门禁,并补充负面路径约束:

  • 危险写操作仍需显式确认(db 写、cli 删除、非幂等 api 写/删)。
  • 负面路径限定为只读/可回滚:故意错误操作仅限"输错密码、非法参数、越权请求"等不产生真实破坏的动作;不做真实破坏性写操作(如真实删除数据)。
  • 负面路径副作用判定(执行前评估):纯查询 / 鉴权失败拒绝类 → 可直接执行;可能成功越权读取他人数据或触发写副作用的 → 需用户确认或跳过(越权读取成功本身是安全事件,非"只读无害")。
  • 生产环境强告警,优先非生产。
  • 凭证脱敏同 e2e。

体验报告

# 动态体验报告:{功能/模块名}

## 前置门禁
- 对应 e2e 场景:X 个,全部 PASS ✅

## 体验范围(分批)
- 批次1:{模块A}(N 个体验点)
- 批次2:{模块B}(M 个体验点)

## 体验明细
| 体验点 | 路径类型 | 正确性 | 反馈全面性 | 错误反馈友好度 | 可优化点 |
|--------|----------|--------|-----------|---------------|----------|
| 登录-正常 | 正面 | ✅ | 返回含 token+用户信息 | — | — |
| 登录-错密码 | 负面 | ✅ | — | "密码错误"可加"剩余N次" | 加剩余次数提示 |
| 下单-库存不足 | 边界 | ✅ | 提示库存不足 | 清晰但无替代建议 | 建议补货提醒 |

## 优化建议(按优先级)
1. 🔴 登录失败应限制重试次数并提示(安全+体验)
2. 🟡 下单库存不足建议补充替代商品推荐
3. 🟢 列表接口返回字段过多,建议精简

## 体验结论
- 覆盖分支:X / 总 Y
- 正确性:全通过
- 体验质量:良好 / 需优化
- 负面路径反馈:{整体评价}

何时不使用动态体验

  • 对应 e2e 场景未通过 → 先修 e2e,不进入体验。
  • 代码尚未实现 → 无从规划体验路径。
  • 只需验证单接口连通性 → 用 api-testing。

体验产物落盘

动态体验不落盘代码(区别于断言式 e2e),但体验计划、体验记录、体验报告需落盘供复盘与追踪。统一存于 tests/e2e/experience/(与 e2e 断言产物同根目录、独立子目录隔离):

tests/e2e/experience/                 # 动态体验产物根目录
├── plans/                            # 体验计划(白盒规划产物,每批一份)
│   └── 2026-08-06-login-batch1.md
├── records/                          # 体验结果记录(黑盒执行产物,对应各批)
│   └── 2026-08-06-login-batch1-records.md
└── reports/                          # 体验报告(全部批次完成后的汇总)
    └── 2026-08-06-login-experience.md
  • 体验计划(plans/):D1 产出,每批一份,含体验点清单(分支/路径类型/动作/预期),供执行对照与复盘。
  • 体验记录(records/):D2 产出,对应各批,记录每个体验点的实际观察与四维评估。
  • 体验报告(reports/):D4 产出,全部批次完成后的汇总(前置门禁/体验范围/明细/优化建议/体验结论)。
  • 命名规范:{YYYY-MM-DD}-{功能slug}-{批次/类型}.md(kebab-case,同项目文档命名约定)。
  • 安全提示:凭证脱敏同 e2e——体验记录/报告中只存脱敏前缀,不落完整 token。

常见陷阱

  • 忘记 produces/depends_on:下游 ${ctx.x} 解析失败 → 每个产出 step 必须声明 produces,消费方必须 depends_on 上游。
  • 把 e2e 当单元测试写:e2e 验证真实副作用与跨组件终态,不要 mock 内部依赖。
  • 异步未用 wait:下单后库存扣减是异步的,直接 db 校验会偶发失败 → 用 wait 轮询。
  • 生产环境误操作:指向生产时务必强告警 + 危险操作确认;优先在非生产环境跑。
  • 凭证泄露:报告/日志只存脱敏前缀,不要把完整 token 写进 ctx.data 或文件。
  • teardown 缺失:有真实创建就必须有对称清理,否则污染测试数据。
  • e2e 与单测混目录:e2e 产物必须放 tests/e2e/ 并配置单测排除,否则被单测 CI 误跑、污染隔离假设。
  • 定义里硬编码密钥/URL:测试定义文件禁止内联真实 secret/endpoint,一律 ${ENV.XXX} 引用 + env 文件(.env.e2e 优先,回退 .env)注入。
  • 断言迎合代码实现:e2e 是黑盒验收,断言对照需求/设计规格(只看入参→返回),不要依据代码内部逻辑写断言。
  • 动态体验跳过前置门禁:e2e 未通过就做体验 → 基本正确性没保证,体验结论无意义;必须 e2e 先 PASS。
  • 白盒越界写判据:动态体验读代码只为规划覆盖路径,若执行时依据代码内部逻辑判断对错 → 破坏黑盒体验根基。
  • 负面路径做真实破坏:故意错误操作仅限只读/可回滚(输错密码、非法参数),不得借负面路径真实删除/破坏数据。
  • 体验计划不分批:代码庞大时一次性规划全部 → 易遗漏且难确认;应分批创建计划、执行确认后再下一批。

更多资源

  • 各 Step 类型完整契约、Context 解析、安全门禁细节:reference.md
  • 完整示例旅程(注册下单 + UI 混合):examples.md
  • HTTP API 步骤约定来源:use_skill("api-testing")