mcpField
T
testing-in-production

testing-in-production

github.com/petrkindlmann测试与质量2221.1k 次安装6 天前更新
代码仓库

关于 testing-in-production

面向 QA 与工程团队的生产环境测试技能,提供通过受控流量、监控指标和回滚机制验证发布质量的方法。内容涵盖功能标记、渐进式发布、生产冒烟测试及回滚验证。

主要功能

  1. 01功能标记状态测试
  2. 02渐进式流量发布
  3. 03发布后冒烟测试
  4. 04护栏指标与自动回滚
  5. 05合成账户与非破坏性检查

适用场景

  1. 01逐步向用户开放新功能
  2. 02部署后检查关键生产路径
  3. 03依据指标暂停发布或回滚
  4. 04验证回滚已恢复服务

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/petrkindlmann/qa-skills --skill testing-in-production

安装后在 Claude Code 中输入/testing-in-production确认已加载。

附带文件references/patterns.mdreferences/rollout-policy.md

详细介绍

生产环境才是真正的生产环境。其他所有环境都只是近似环境——预发布环境无法复现真实的数据量、流量或第三方服务的各种特性。本技能介绍如何在生产环境中安全地验证质量:控制影响范围、自动回滚、设置护栏指标,以及在用户发现问题之前捕捉问题的冒烟测试。它要防止的常见故障是:面向 100% 的用户发布,却没有可关闭的功能开关、没有可供对比的基线,也没有经过测试的回退方案。

快速导航

情况前往
在功能开关后发布功能功能开关测试
通过关卡将流量从 1% 逐步提升至 100%渐进式发布 + references/rollout-policy.md
需要在每次发布后执行检查生产环境冒烟测试 + references/patterns.md
确定哪些数值作为发布关卡护栏指标
新代码路径尚无用户可见的变化暗发布
验证回滚确实有效验证

调研问题

先检查 .agents/qa-project-context.md。如果文件存在,请将其作为上下文,并跳过其中已有答案的问题。

功能开关系统:

  • 你是否有功能开关平台?(LaunchDarkly、Statsig — 现属 OpenAI、GrowthBook、Unleash、Flagsmith、Harness FME — 前身为 Split、自定义平台、无)
  • 如何管理开关?(控制面板、配置文件、环境变量)
  • 能否将开关定向到特定用户、百分比或细分群体?
  • 当前有多少个启用的开关?是否有清理流程?

发布能力:

  • 能否只向部分流量发布?(Canary 基础设施、加权路由、功能开关)
  • 部署需要多长时间?回滚需要多长时间?
  • 是否采用蓝绿部署或滚动部署?
  • 能否按区域、用户群体或百分比路由流量?

监控成熟度:

  • 已部署哪些可观测性工具?(APM、日志记录、错误跟踪、指标)
  • 是否有展示错误率、延迟和业务指标的仪表板?
  • 是否根据适当的阈值配置了告警?
  • 能否实时对比 Canary 与基线指标?

生产环境访问与安全:

  • 谁可以访问生产环境?是否有审批流程?
  • 生产环境中是否有专用测试账户?
  • 能否在不影响真实用户数据的情况下于生产环境运行操作?
  • 是否有生产事故响应流程?

核心原则

1. 生产环境是最终测试环境

预发布环境只是对生产环境的近似模拟。它无法复现生产环境的数据量、流量模式、第三方集成、基础设施特性或用户行为。在生产环境中测试并非鲁莽,反而更贴近现实。关键不在于是否要在生产环境中测试,而在于如何安全地进行测试。

2. 通过控制影响范围来保障安全

每项生产环境测试都必须回答:“如果出了问题,会影响多少用户?”答案必须尽可能小。功能开关、Canary 部署和流量拆分的作用,就是将影响范围从 100% 缩小到 1% 或更低。

3. 始终准备好经过测试的回滚方案

开始任何生产环境测试之前,必须确定回滚机制、对其进行测试,并确保回滚速度足够快。“关闭功能开关”是不错的回滚方案。“重新部署上一版本”也可以接受。“到时候再想办法”不算方案。你从未执行过的回滚只是一个假设,而不是方案——请参阅验证,了解如何证明它有效。

4. 监控是前提,而非锦上添花

没有监控,就无法在生产环境中测试。如果无法实时测量错误率、延迟和业务指标,就无法检测问题。在添加生产环境测试之前,先补齐监控缺口。

5. 生产测试必须无破坏性

生产测试绝不能损坏真实用户数据、向真实用户发送真实通知、从真实支付方式扣款,或造成需要手动清理的副作用。必须使用合成账户、测试标记和隔离资源。


功能标记测试

功能标记是最安全的生产测试机制。它们将部署与发布解耦,并支持即时回滚。

测试标记开启和关闭时的状态

每项带标记的功能都需要在两种状态下进行测试。标记关闭时的路径就是回滚路径,必须可靠运行——使用 setFeatureFlag(name, true|false, { userId: TEST_USER_ID }) 驱动这两种状态。完整的开启/关闭测试组合见 references/patterns.md。

标记生命周期测试

标记并非只有开启和关闭两种状态。它们会在不同状态间转换,每次转换都必须经过验证。

Flag lifecycle:
  Created → Targeting internal users → Canary (1%) → Partial (10-50%) → Full (100%) → Cleanup (removed)

Test at each stage:
  - Internal: Feature works for internal accounts, hidden from external
  - Canary: Metrics are comparable between flag-on and flag-off cohorts
  - Partial: No performance degradation at scale
  - Full: All user segments work correctly
  - Cleanup: Code with flag removed behaves identically to flag-on
清理过期标记

留在代码中的标记会成为技术债务。运行一个每周 CI 作业,查询标记提供方,找出已 100% 推出的且创建时间超过 14 天的标记。这些标记可作为代码清理的候选项——移除标记分支逻辑,只保留已启用的路径。移除标记却不删掉死代码,只完成了一半清理工作。

标记组合测试

多个标记相互影响时,应测试重要的组合。不要测试所有 2^N 种组合——重点测试影响同一用户流程的标记(例如,new-checkout、express-pay、discount-engine-v2 都会影响结账流程)。选出关键组合:全部采用新方案、一个具有代表性的混合状态,以及全部采用旧方案。组合测试循环见 references/patterns.md。


渐进式推出

厂商原生的金丝雀分析。 在手动编写下面的推出策略 YAML 之前,先确认你的平台是否已具备相应功能:LaunchDarkly Guarded Rollouts(基于指标的自动监控渐进式推出,并可自动回滚;自 2026 年初起采用频率学派序贯检验分析模型)、Statsig Auto-tune、Argo Rollouts AnalysisRun、Flagger、Harness Continuous Verification。如果已有这类功能,优先使用——它与指标和回滚机制的集成成本低于维护自定义分析循环。

AI 功能推出是一种独立模式:将模型变体和提示词作为标记值,并配备成本保护措施和紧急停止开关。LaunchDarkly AI Configs / AgentControl(AI Configs 于 2026 年 5 月宣布更名并纳入 AgentControl 品牌体系)是通过渐进式推出上线大模型功能的文档化方案。完整模式见 release-readiness。

金丝雀阶段:1% 到 100%

结构化推出,并为每个阶段设定明确的晋级标准。

阶段流量保持时间关键检查项
金丝雀1%15-30 分钟错误率、崩溃率、异常
早期采用者10%1-2 小时P95 延迟、转化率
部分推出50%2-4 小时所有保护措施、业务指标
全面推出100%监控 24 小时长尾问题、批处理作业兼容性
自动晋级和回滚

定义可由机器检查的阶段晋级条件——hold_duration 加指标条件(error_rate_5xx < 0.5%、latency_p95 < 500ms、crash_rate == 0)。触发保护措施违规时自动回滚,无需人工批准:error_rate_5xx > 2x_baseline for 5m、latency_p99 > 3x_baseline for 5m、crash_rate > 0.1% for 2m,并分别通知值班人员。应以错误预算消耗速率作为门槛,而非仅看原始倍数,以便发现虽缓慢但仍会突破 SLO 的问题。完整的晋级 YAML、回滚触发条件和 SLO 门槛配置见 references/rollout-policy.md。

验证回滚是否正确触发

自动回滚触发不代表事故已解决。回滚触发后,在确认系统确实已恢复之前,不要宣布“已恢复”:

  1. 重新运行健康检查冒烟测试,针对生产环境执行(GET /api/health 返回 healthy 和之前的 version)。
  2. 确认标志/部署状态已恢复——查询标志平台,确认标志已关闭(或部署正在提供之前的构建版本),不要想当然。
  3. 确认护栏指标已恢复至基线——错误率、P99 延迟和崩溃率均回到部署前的范围内。
  4. 确认回滚通知已送达值班人员(Slack/PagerDuty),确保有人负责处理事故。

只有以上四项全部满足,才算验证回滚成功。请参阅验证,了解首次用于生产环境之前证明这条链路有效的预演。


生产冒烟测试

部署后的关键路径测试

每次部署后立即运行,作为流水线阶段(而不仅仅是在部署前的 CI 中运行)。这些测试会验证核心功能在生产配置、数据和基础设施下是否正常:/api/health 检查、使用合成凭据进行的身份验证流程、核心数据加载和搜索。配置 retries: 1 和 timeout,避免部署后运行偶发失败,导致流水线因首次短暂故障而受阻。完整的 production-smoke.spec.ts 请参阅 references/patterns.md。

合成用户账号

生产测试账号必须与真实用户明显区分:使用保留的邮箱模式(smoke-test+{env}@yourcompany.com)、is_synthetic = true 标志,并从分析、计费和邮件营销活动中排除。通过管理 API 创建,并优先使用短时效的 OIDC/工作负载身份令牌,而非长期有效的密码。完整约定请参阅 references/patterns.md。

非破坏性断言

生产冒烟测试必须只读,不写入数据。如果无法避免写入,必须在测试夹具拆卸阶段清理,确保测试无论通过还是失败都会执行清理。

不要在 test() 主体内调用 test.afterEach()——Playwright 会在 describe/文件级别注册钩子,因此在测试中途注册的钩子不会安排拆卸操作,并会抛出 test.afterEach() can only be called in a describe block。数据会泄漏。请使用自动清理夹具,记录创建的资源 ID 并在拆卸时删除(或者在一次性脚本中使用 try/finally)。基于夹具的创建-验证-清理模式请参阅 references/patterns.md。


护栏指标

发布期间要监控的内容
类别指标比较方法告警阈值
错误HTTP 5xx 率与部署前基线比较超过基线 2 倍,持续 5 分钟
错误未处理异常数与部署前基线比较出现任何新的异常类型
延迟P50 响应时间与部署前基线比较超过基线 1.5 倍
延迟P95 响应时间与部署前基线比较超过基线 2 倍
延迟P99 响应时间与部署前基线比较超过基线 3 倍
业务转化率与 7 天平均值比较下降超过 5%
业务每次会话收入与 7 天平均值比较下降超过 10%
客户端崩溃率(移动端)与上一版本比较增加超过 0.1%
客户端JavaScript 错误率与部署前基线比较超过基线 2 倍
基础设施CPU 利用率绝对值持续超过 80%
基础设施内存利用率绝对值持续超过 85%
基线比较

将金丝雀指标与运行上一版本的对照组进行比较,而不应仅与历史数据比较。

Comparison approaches (best to worst):
  1. Canary vs. control: split traffic, compare groups in real time (best)
  2. Before/after: compare post-deploy metrics to pre-deploy window (good)
  3. Historical: compare to same time last week (acceptable for trends)
  4. Absolute thresholds: fixed thresholds regardless of baseline (fragile)
统计显著性

对于业务指标(转化率、收入),较小的样本量会产生较大噪声。得出结论前,请等待结果达到统计显著性。

Minimum sample sizes for rollout decisions:
  - Error rate: 1,000 requests (errors are rare events, need volume)
  - Latency: 500 requests (more stable, converges faster)
  - Conversion rate: 5,000 sessions (business metrics have high variance)
  - Crash rate: 10,000 app launches (crashes are rare events)

Rule of thumb: if you don't have enough traffic at 1% to reach
significance in 30 minutes, increase to 5% or extend the hold window.

暗发布

暗发布会将新功能部署到生产环境,但对用户隐藏。真实的生产流量会经过新代码路径,而不会对用户造成可见影响。

流量影子测试

将传入请求复制到新服务。比较响应,但不将新响应返回给用户。

Request flow:
  User → Load Balancer → Production Service (returns response to user)
                       ↘ Shadow Service (processes request, logs result, discards)

What to compare:
  - Response status codes: shadow should match production
  - Response body: diff for semantic equivalence (ignore timestamps, IDs)
  - Latency: shadow should not be significantly slower
  - Error rate: shadow should not produce more errors
并行执行

对于迁移(新数据库、新算法、新服务),在生产环境中同时运行新旧路径。旧路径将结果返回给用户;新路径异步运行、记录差异,并丢弃其结果。持续跟踪匹配率——切换前目标是达到 99% 以上。

Shadow launch timeline:
  Week 1: Deploy shadow, start comparing, expect <50% match
  Week 2: Fix mismatches, match rate should climb to 90%+
  Week 3: Match rate stable at 99%+, handle remaining edge cases
  Week 4: Cut over: shadow becomes primary, old becomes shadow
  Week 5: Remove old path after 1 week of stability

反模式

在生产环境测试却不进行监控

在没有仪表板和告警的情况下运行生产测试,就像盲目飞行。只有用户报告问题时,你才会知道测试是否造成了问题。 解决方法: 监控是前提条件。添加任何生产测试之前,请确认你能实时查看错误率、延迟和关键业务指标。首次运行测试前先设置告警。

没有回滚计划

“出了问题我们就部署修复”不算回滚计划。在压力之下,修复会耗时更长、引入新 Bug,并延长故障时间。 解决方法: 每项生产测试或发布都必须有一份记录在案的回滚机制,可在 5 分钟内执行——禁用功能标志、恢复到之前的部署,或重定向流量——并且包含一个验证步骤,以确认系统确实已恢复(参见验证)。

在生产测试中执行破坏性操作

会创建真实订单、发送真实邮件或修改真实用户数据的生产测试,不是测试,而是随时可能发生的事故。 解决方法: 使用标记为测试数据的合成账户。对支付和邮件使用沙盒模式。在 fixture teardown 中清理创建的数据,确保清理总会执行。如果某项测试无法做到非破坏性,就不应在生产环境中运行。

仅在成功时运行清理

将清理步骤放在断言之后,意味着断言失败时永远不会执行清理,正好会泄漏本应删除的测试数据。在 test() 主体中调用 test.afterEach() 也是同样的陷阱——它会抛出错误或被忽略。 解决方法: 将 teardown 放入自动清理 fixture 或 finally 块中,确保无论测试通过还是失败都会运行。参见 references/patterns.md。

用生产环境测试取代预生产测试

生产测试是对预生产测试的补充,而非替代。如果 staging 环境出了问题,而你因为它是唯一可用的环境就在“生产环境中测试”,请先修复 staging。 解决方法: 维护可用的预生产环境。生产测试应验证只有生产环境才能验证的内容:真实流量、真实数据量和真实的第三方集成。

金丝雀发布却不进行对比

将部署范围限制在 1% 的流量,却不将金丝雀指标与对照组进行比较,会完全偏离金丝雀发布的初衷。你只是在放慢部署速度,而不是发现问题。 解决方法: 始终将金丝雀指标与基线进行比较。使用并排仪表板或自动金丝雀分析工具(Kayenta、Argo Rollouts analysis)。

过期的功能标志

功能标志完全发布后却从未移除,会不断累积。一年后,你可能会有 200 个相互作用未知的标志,而且每条代码路径都包含没人理解的分支逻辑。 解决方法: 创建每个标志时都设定过期日期。完全发布并稳定运行 2 周后,移除标志及其无用分支。跟踪标志使用时长,并在标志超过过期日期时发出告警。


验证

在首次用于生产环境之前,证明回滚路径确实会触发——从未触发过的回滚只是一个假设。先做最小检查:

  1. 在预发布环境触发护栏。 在连接了同一 automatic_rollback 策略的预发布发布流程中注入故障(例如,强制 error_rate_5xx 超过 2x_baseline,或让健康检查连续失败 3 次)。确认回滚操作在其 for: 时间窗口内触发。
  2. 确认已恢复到先前状态。 重新运行健康检查冒烟测试,并断言 status === 'healthy' 且 version 为先前的版本。查询标志平台或部署系统,确认当前提供服务的是先前的构建版本——不要想当然。
  3. 确认指标已恢复。 错误率、P99 延迟和崩溃率均回到部署前的范围内。
  4. 确认通知已发送。 回滚警报已送达值班频道(Slack/PagerDuty)。
  5. 冒烟测试已接入流水线。 对预发布环境运行部署作业,确认部署后冒烟测试阶段确实执行并阻止晋级——npx playwright test production-smoke.spec.ts 的退出码为 0。

如果无法在预发布环境中演示步骤 1–4,则回滚未经验证,发布流程尚未就绪。

Agent 快捷方式: LaunchDarkly、GrowthBook、Unleash、Flagsmith、Statsig 和 Harness FME 均提供对应的 MCP 服务,AI Agent 可在这些检查期间直接切换标志并读取发布指标,而无需手动操作仪表板。


完成标准

  • 已记录功能标志发布计划,明确列出各阶段的百分比步骤(1% → 10% → 50% → 100%)以及每个阶段的具名护栏指标。
  • 已配置金丝雀分析及自动化的通过/失败标准,因此晋级和回滚决策不需要手动比较指标。
  • 每次部署时,生产冒烟测试都会作为流水线阶段运行(而不只是在部署前的 CI 中运行),且该阶段针对生产环境的退出码为 0。
  • 已定义并记录回滚触发条件,并在首次用于生产环境之前,通过验证中的预发布试运行演示其能够正确触发(触发护栏 → 触发回滚 → 确认已恢复到先前状态且指标已恢复)。
  • 已记录生产测试数据策略,说明使用的是合成用户还是匿名化真实用户,以及如何将其排除在分析和计费之外。

参考文件(位于 references/ 中)

  • rollout-policy.md — 完整的晋级标准 YAML、自动回滚触发条件,以及错误预算 / SLO 门禁配置。
  • patterns.md — 标志开启/关闭及组合测试、production-smoke.spec.ts 测试套件、合成账户约定,以及基于夹具的非破坏性创建-验证-清理模式。

相关技能

  • release-readiness — 整个版本发布的继续/停止决策;生产测试是其中的部署后验证步骤。需要发布检查清单时查看此项,而不是发布机制。
  • synthetic-monitoring — 发布完成后持续运行的定时探测。需要持续验证 SLA 时查看此项,而不是发布过程中的安全措施。
  • observability-driven-testing — 使用生产环境追踪和日志作为设计新测试的输入。遥测数据告诉你该测试什么时查看此项,而不是需要安全发布时。
  • qa-metrics — 护栏指标和发布标准如何接入仪表板与 KPI。
  • ci-cd-integration — 将冒烟测试阶段和发布门禁接入流水线。
  • test-environments — 生产测试的补充性预生产环境,绝不能取代生产测试。

评论

支持 Markdown