test-reliability
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese<objective>
A retried test that still flakes will eventually fail 3-of-3 during your most critical release, and a silently auto-repaired test may now verify a different element entirely. This skill builds suites teams can trust: resilient locators, classified flakes, environment-aware healing, data healing, and observable repair with confidence scoring — every automated fix produces evidence a human can review.
</objective>
<objective>
即使重试后仍存在Flaky问题的测试,最终会在你最关键的发布中出现3次全失败的情况,而静默自动修复的测试可能会完全验证错误的元素。本技能旨在构建团队可信赖的测试套件:具备韧性的定位器、分类后的Flaky测试、环境感知修复、数据修复以及带置信度评分的可观测修复——每一次自动修复都会生成可供人工审核的证据。
</objective>
Quick Route
快速指引
| Situation | Go to |
|---|---|
| Test flakes in CI, root cause unknown | Flake Classification → decision tree |
| Locator broke, want resilient replacement | Locator Resilience |
| Action fails, suspect slow backend not UI bug | Environment-Aware Healing |
| 401/404/429 mid-test from stale data | Data Healing |
| Want auto-repair with review gate | Observable Repair Workflow |
| Isolate a flaky test without blocking CI | Quarantine Management |
| Step-by-step triage of one flaky test | |
| 场景 | 操作路径 |
|---|---|
| CI中出现Flaky测试,根因未知 | Flake测试分类 → 决策树 |
| 定位器损坏,需要具备韧性的替代方案 | 定位器韧性优化 |
| 动作执行失败,怀疑是后端缓慢而非UI Bug | 环境感知修复 |
| 测试中因数据过期出现401/404/429错误 | 数据修复 |
| 需要带审核环节的自动修复 | 可观测修复流程 |
| 隔离Flaky测试而不阻塞CI | 隔离管理 |
| 单个Flaky测试的分步诊断 | |
Discovery Questions
调研问题
Check first — it carries known flaky areas, selector strategy, and CI environment details. Skip any question it already answers.
.agents/qa-project-context.md- What is your current flaky test rate? Check CI failure stats over the last 30 days. Below 2% is healthy; 2-5% needs attention; above 5% is eroding team trust.
- Where is the pain concentrated? Locator breakage? Timing? Test data? Environment? If unknown, instrument first (see Flake Classification).
- What is your current selector strategy? data-testid everywhere, mixed CSS and role-based, or no strategy (whatever works)? This sets the stability-score baseline.
- How do you handle flaky tests today? Retry and hope, skip and forget, or something structured? Decides how much process you need to add.
- What CI environment runs the tests? Same machine every time or different runners? Consistent or variable resources? Drives the environment-vs-test diagnosis.
- What is your test data strategy? Shared database, per-test fixtures, factory seeding, or external services? Decides whether data healing applies.
先查看——其中包含已知的Flaky区域、选择器策略和CI环境细节。跳过其中已解答的问题。
.agents/qa-project-context.md- 当前Flaky测试率是多少? 查看过去30天的CI失败统计数据。低于2%为健康状态;2-5%需要关注;高于5%会逐渐降低团队对测试套件的信任。
- 问题集中在哪些方面? 定位器损坏?时序问题?测试数据?环境?如果未知,先进行检测(参见Flake测试分类)。
- 当前采用的选择器策略是什么? 全量使用data-testid、混合CSS和基于角色的选择器,还是无固定策略(能用就行)?这会设定稳定性评分基线。
- 目前如何处理Flaky测试? 重试碰运气、跳过忽略,还是采用结构化流程?这决定了需要新增多少流程。
- 运行测试的CI环境是什么样的? 每次使用同一台机器还是不同运行器?资源是稳定还是可变?这会影响环境与测试的诊断方向。
- 测试数据策略是什么? 共享数据库、单测试固定数据、工厂模式生成数据,还是依赖外部服务?这决定了数据修复是否适用。
Core Principles
核心原则
-
Prevention over cure. Writing a resilient test costs 1x. Investigating a flaky one costs 10x. Losing team trust in the suite costs 100x.
-
Healing must be observable and reviewable. Every automated repair produces evidence: what broke, what was tried, what worked, the confidence score. Silent fixes erode trust as fast as silent failures.
-
Classify before fixing. The fix for a timing issue is completely different from the fix for a data dependency. Wrong diagnosis wastes effort and can make things worse.
-
Flaky tests are bugs. Not annoyances to tolerate. A flaky test either has a test bug (fix the test), reveals an app bug (fix the app), or exposes an environment issue (fix the environment).
-
Track reliability as a metric, not a feeling. Measure flaky rate, mean time to heal, quarantine age, and selector stability. What gets measured gets fixed.
-
Self-healing is a spectrum. Start with resilient locators (Level 1), add fallback strategies (Level 2), then environment-aware healing (Level 3), then confidence-scored auto-repair (Level 4). Do not jump to Level 4 before mastering Level 1.
-
预防胜于补救。编写具备韧性的测试成本为1倍,排查Flaky测试的成本为10倍,失去团队对测试套件的信任成本为100倍。
-
修复必须可观测、可审核。每一次自动修复都会生成证据:哪里出了问题、尝试了哪些方案、最终生效的方案是什么、置信度评分。静默修复和静默失败一样,都会快速消耗团队信任。
-
先分类再修复。时序问题的修复方案与数据依赖问题的完全不同。错误的诊断会浪费精力,甚至让问题恶化。
-
Flaky测试是Bug。不是可以容忍的小麻烦。Flaky测试要么存在测试Bug(修复测试),要么暴露了应用Bug(修复应用),要么揭示了环境问题(修复环境)。
-
将可靠性作为指标追踪,而非凭感觉判断。测量Flaky率、平均修复时间、隔离时长和选择器稳定性。可测量的指标才能被解决。
-
自修复是一个渐进过程。从具备韧性的定位器开始(第1级),添加回退策略(第2级),然后引入环境感知修复(第3级),最后实现带置信度评分的自动修复(第4级)。在掌握第1级之前,不要直接跳到第4级。
Locator Resilience
定位器韧性优化
Multi-Attribute Selectors (Beyond Fallback Chains)
多属性选择器(超越回退链)
A single locator strategy is a single point of failure. Multi-attribute selectors combine multiple signals for one element lookup — resilience without fallback-chain complexity.
The key insight: instead of "try A, then B, then C," use "find element matching A AND B AND C with tolerance for one signal missing."
typescript
// Multi-attribute locator: tries combinations from most specific to least
const submitBtn = await multiAttributeLocator(page, {
testId: 'checkout-submit', // most stable signal
role: 'button', // semantic signal
name: /place order/i, // accessible name
nearText: 'Order Summary', // visual context
});
// Internally: tries testId+role+name first, then testId alone, then role+name,
// then text, then nearText+role. Returns first visible match.
// Unlike fallback chains, it combines signals for higher confidence.单一定位器策略是单点故障。多属性选择器结合多个信号来查找元素——无需回退链的复杂性即可实现韧性。
核心思路: 不要采用“尝试A,然后B,然后C”的方式,而是使用“查找匹配A且B且C的元素,允许其中一个信号缺失”。
typescript
// Multi-attribute locator: tries combinations from most specific to least
const submitBtn = await multiAttributeLocator(page, {
testId: 'checkout-submit', // most stable signal
role: 'button', // semantic signal
name: /place order/i, // accessible name
nearText: 'Order Summary', // visual context
});
// Internally: tries testId+role+name first, then testId alone, then role+name,
// then text, then nearText+role. Returns first visible match.
// Unlike fallback chains, it combines signals for higher confidence.DOM Similarity / Neighbor Context Matching
DOM相似度/相邻上下文匹配
When a locator fails, the element may still exist with changed attributes. Use surrounding DOM context to find it:
- Parent + tag + type: Find the container (by testId), then locate by tag and type within it.
- Preceding label: Find sibling text (label), then locate the adjacent input/button.
- Nearby text context: Find visible text near the target, then locate the element type in the same parent.
These are repair candidates scored by the confidence system below — not runtime fallbacks.
当定位器失效时,元素可能仍然存在只是属性发生了变化。使用周围的DOM上下文来查找元素:
- 父容器+标签+类型:先找到容器(通过testId),再在其中按标签和类型定位元素。
- 前置标签:找到兄弟文本(标签),再定位相邻的输入框/按钮。
- 附近文本上下文:找到目标元素附近的可见文本,再在同一父容器中定位对应类型的元素。
这些是修复候选方案,会通过下方的置信度系统评分——而非运行时回退。
Selector Stability Scoring
选择器稳定性评分
Rate every selector on a 0-5 scale to prioritize refactoring.
| Score | Strategy | Survives |
|---|---|---|
| 5 | | CSS, text, and structural changes |
| 4 | | CSS and structural changes |
| 3 | | CSS changes; breaks on label rewording |
| 2 | | Breaks on any copy change |
| 1 | | Breaks on CSS or structural change |
| 0 | | Breaks on any DOM change |
Target: Average score of 3.5+ across the suite. Audit monthly. Prioritize fixing score-0 and score-1 selectors. Emit one score per locator to (or a CI step) and report the suite average so the 3.5 target is verifiable, not asserted.
selector-stability.md为每个选择器按0-5分评分,优先重构低评分的选择器。
| 评分 | 策略 | 可抵御的变化 |
|---|---|---|
| 5 | | CSS、文本和结构变化 |
| 4 | | CSS和结构变化 |
| 3 | | CSS变化;标签文字修改会导致失效 |
| 2 | | 任何文案修改都会导致失效 |
| 1 | | CSS或结构变化都会导致失效 |
| 0 | | 任何DOM变化都会导致失效 |
目标: 整个测试套件的平均评分达到3.5分以上。每月进行审计。优先修复0分和1分的选择器。为每个定位器生成评分并写入(或CI步骤),并报告套件平均分,确保3.5分的目标可验证而非空谈。
selector-stability.mdFlake Classification Framework
Flake测试分类框架
Every flaky test has a root cause category. Classifying correctly determines the fix.
每个Flaky测试都有根因类别。正确分类才能确定修复方案。
Categories
类别
| Category | Signal | Root Cause | Fix Direction |
|---|---|---|---|
| Timing | Timeout errors, passes on retry, worse in CI | Race condition, animation, async operation | Wait for condition, not time |
| Data dependency | Fails with other tests, passes alone | Shared state, missing cleanup | Isolate per-test, fixture cleanup |
| Environment | Fails on specific runner, correlates with load | Resource contention, network latency | Mock externals, increase resources |
| Order dependency | Fails with --shard or fullyParallel | Depends on another test's side effect | Self-contained setup |
| Time sensitivity | Fails at specific times (midnight, month-end) | Uses real clock, date boundary | Mock clock, relative comparisons |
| Visual rendering | Screenshot diff flickers, subpixel differences | Font rendering, antialiasing, animation frame | Increase threshold, mask dynamic regions |
| External service | Correlates with third-party status | Real HTTP calls in tests | Mock external APIs |
| 类别 | 信号 | 根因 | 修复方向 |
|---|---|---|---|
| 时序问题 | 超时错误、重试可通过、CI中问题更严重 | 竞态条件、动画、异步操作 | 等待条件而非固定时长 |
| 数据依赖 | 与其他测试一起运行时失败、单独运行可通过 | 共享状态、清理不彻底 | 单测试数据隔离、固定数据清理 |
| 环境问题 | 在特定运行器上失败、与负载相关 | 资源竞争、网络延迟 | 模拟外部依赖、增加资源 |
| 执行顺序依赖 | 使用--shard或全并行模式时失败 | 依赖其他测试的副作用 | 独立的测试前置设置 |
| 时间敏感 | 在特定时间点失败(午夜、月末) | 使用真实时钟、日期边界问题 | 模拟时钟、相对时间比较 |
| 视觉渲染 | 截图对比闪烁、亚像素差异 | 字体渲染、抗锯齿、动画帧 | 提高阈值、屏蔽动态区域 |
| 外部服务 | 与第三方服务状态相关 | 测试中调用真实HTTP接口 | 模拟外部API |
Classification Decision Tree
分类决策树
Test is flaky
│
├── Does it pass when run alone?
│ ├── YES → ORDER DEPENDENCY or DATA DEPENDENCY
│ │ ├── Does another test create/modify data it needs? → ORDER DEPENDENCY
│ │ └── Does it share a database/file/cache? → DATA DEPENDENCY
│ │
│ └── NO → Not order/data dependent. Continue below.
│
├── Does it fail more often in CI than locally?
│ ├── YES → TIMING or ENVIRONMENT
│ │ ├── Timeout errors? → TIMING (CI is slower)
│ │ ├── Connection errors? → ENVIRONMENT (network latency / service)
│ │ └── Resource errors (OOM, disk)? → ENVIRONMENT (resource contention)
│ │
│ └── NO → Same rate locally and CI. Continue below.
│
├── Does it fail at specific times?
│ ├── YES → TIME SENSITIVITY
│ │ ├── Near midnight? → Date boundary issue
│ │ ├── Near month/year end? → Calendar calculation
│ │ └── Specific hour? → Timezone issue
│ │
│ └── NO → Continue below.
│
├── Does it involve screenshots or visual comparison?
│ ├── YES → VISUAL RENDERING
│ │
│ └── NO → Continue below.
│
├── Does it call external HTTP APIs?
│ ├── YES → EXTERNAL SERVICE
│ │
│ └── NO → TIMING (most likely — default classification)
│ └── Investigate: what async operation is not being awaited?The fix per category lives in (Step 4) with full code patterns.
references/flaky-test-runbook.mdTest is flaky
│
├── Does it pass when run alone?
│ ├── YES → ORDER DEPENDENCY or DATA DEPENDENCY
│ │ ├── Does another test create/modify data it needs? → ORDER DEPENDENCY
│ │ └── Does it share a database/file/cache? → DATA DEPENDENCY
│ │
│ └── NO → Not order/data dependent. Continue below.
│
├── Does it fail more often in CI than locally?
│ ├── YES → TIMING or ENVIRONMENT
│ │ ├── Timeout errors? → TIMING (CI is slower)
│ │ ├── Connection errors? → ENVIRONMENT (network latency / service)
│ │ └── Resource errors (OOM, disk)? → ENVIRONMENT (resource contention)
│ │
│ └── NO → Same rate locally and CI. Continue below.
│
├── Does it fail at specific times?
│ ├── YES → TIME SENSITIVITY
│ │ ├── Near midnight? → Date boundary issue
│ │ ├── Near month/year end? → Calendar calculation
│ │ └── Specific hour? → Timezone issue
│ │
│ └── NO → Continue below.
│
├── Does it involve screenshots or visual comparison?
│ ├── YES → VISUAL RENDERING
│ │
│ └── NO → Continue below.
│
├── Does it call external HTTP APIs?
│ ├── YES → EXTERNAL SERVICE
│ │
│ └── NO → TIMING (most likely — default classification)
│ └── Investigate: what async operation is not being awaited?每个类别的修复方案可查看(第4步)中的完整代码示例。
references/flaky-test-runbook.mdEnvironment-Aware Healing
环境感知修复
Not all test failures are test problems. Some are environment problems. Environment-aware healing distinguishes the two and adapts.
并非所有测试失败都是测试本身的问题,有些是环境问题。环境感知修复可区分这两种情况并进行适配。
Slow Backend vs True UI Failure
后端缓慢 vs 真实UI故障
When an action fails, check backend health before blaming the test:
- Action fails → Hit .
/api/health - Backend unhealthy (5xx or timeout) → Retry with exponential backoff. Diagnose as . This is not a UI bug.
backend_down - Backend healthy (2xx) → This is a real UI/test failure. Do not retry.
Return a structured diagnosis: . This feeds flake classification — backend issues are environment issues, not test bugs.
{ success: boolean; diagnosis: 'backend_down' | 'ui_failure' | 'backend_slow_recovered' }当动作执行失败时,先检查后端健康状况再归咎于测试:
- 动作执行失败 → 调用接口。
/api/health - 后端不健康(5xx或超时) → 指数退避重试。诊断为,这不是UI Bug。
backend_down - 后端健康(2xx) → 这是真实的UI/测试故障,不进行重试。
返回结构化诊断结果:。该结果会用于Flake测试分类——后端问题属于环境问题,而非测试Bug。
{ success: boolean; diagnosis: 'backend_down' | 'ui_failure' | 'backend_slow_recovered' }Resource Contention Detection
资源竞争检测
Before declaring a test failure in CI, check for resource contention:
- Browser health: Load . If it takes > 2s (baseline < 500ms), the runner is overloaded.
about:blank - API health: Hit . If it takes > 5s (baseline < 1s), the backend is under pressure.
/api/health - Diagnosis: If either check fails, classify as an environment issue and annotate the test result. Do not count resource-contention failures toward flaky test rates.
在CI中判定测试失败前,先检查是否存在资源竞争:
- 浏览器健康:加载。如果耗时超过2秒(基线<500ms),说明运行器负载过高。
about:blank - API健康:调用。如果耗时超过5秒(基线<1秒),说明后端压力过大。
/api/health - 诊断:如果任一检查失败,分类为环境问题并标注测试结果。资源竞争导致的失败不计入Flaky测试率。
Data Healing
数据修复
Test data expires, gets cleaned up, or becomes invalid. Data healing detects and regenerates stale test data.
测试数据会过期、被清理或失效。数据修复可检测并重新生成过期的测试数据。
Common Data Failure Patterns
常见数据失败模式
| Pattern | Signal | Fix |
|---|---|---|
| Expired auth token | 401 response during test | Regenerate token in fixture |
| Deleted test record | 404 when accessing seeded data | Re-seed before test |
| Uniqueness violation | 409 or constraint error | Generate unique identifiers per run |
| Stale cache | Wrong data returned | Clear cache in setup |
| Exceeded quota | 429 or rate limit error | Reset quotas or use dedicated test account |
| 模式 | 信号 | 修复方案 |
|---|---|---|
| 认证令牌过期 | 测试中出现401响应 | 在固定数据中重新生成令牌 |
| 测试记录被删除 | 访问预生成数据时出现404 | 测试前重新生成数据 |
| 唯一性冲突 | 409或约束错误 | 每次运行生成唯一标识符 |
| 缓存过期 | 返回错误数据 | 前置步骤中清除缓存 |
| 配额超限 | 429或速率限制错误 | 重置配额或使用专用测试账号 |
Self-Healing Test Data Fixture Pattern
自修复测试数据固定模式
Build fixtures that verify data exists and regenerate if stale.
typescript
// Pattern: verify → heal → use → cleanup
testUser: async ({ request }, use, testInfo) => {
// 1. Try to find existing test user by deterministic email
// 2. Verify auth token is still valid (GET /api/me)
// 3. If token expired → refresh it (POST /refresh-token), mark as healed
// 4. If user missing → create new one, mark as healed
// 5. If healed → annotate testInfo for observability
// 6. use(user) → run the test
// 7. Cleanup: delete test user (guaranteed by fixture, even on failure)
}Key patterns:
- Use in email/identifiers for per-test uniqueness.
testInfo.testId - Annotate when healing occurs, for observability.
testInfo.annotations - Always clean up in the fixture's post-use block, not in — fixtures guarantee cleanup on failure.
afterEach
构建可验证数据存在性并在过期时重新生成的固定数据。
typescript
// Pattern: verify → heal → use → cleanup
testUser: async ({ request }, use, testInfo) => {
// 1. Try to find existing test user by deterministic email
// 2. Verify auth token is still valid (GET /api/me)
// 3. If token expired → refresh it (POST /refresh-token), mark as healed
// 4. If user missing → create new one, mark as healed
// 5. If healed → annotate testInfo for observability
// 6. use(user) → run the test
// 7. Cleanup: delete test user (guaranteed by fixture, even on failure)
}核心模式:
- 在邮箱/标识符中使用实现单测试唯一性。
testInfo.testId - 修复发生时,在中添加标注,便于观测。
testInfo.annotations - 始终在固定数据的使用后块中进行清理,而非——固定数据可确保即使测试失败也会执行清理。
afterEach
Observable Repair Workflow
可观测修复流程
Core guardrail: Healing must be observable and reviewable. Every repair follows this flow:
Failure Detected
│
▼
Candidate Repair Generated
│
▼
Confidence Score Computed (0.0 - 1.0)
│
▼
Evidence Diff Produced (what changed, what was tried)
│
▼
Approval Policy Applied
│ ├── Score >= 0.9 → Auto-apply, log for batch review
│ ├── Score 0.7-0.89 → Apply in quarantine, flag for individual review
│ ├── Score 0.5-0.69 → Do NOT apply, open PR with evidence for review
│ └── Score < 0.5 → Discard, manual investigation required
│
▼
Intent Fidelity Check (does repaired test still test the same thing?)
│
▼
Rollback if intent fidelity drops核心准则: 修复必须可观测、可审核。每一次修复都遵循以下流程:
Failure Detected
│
▼
Candidate Repair Generated
│
▼
Confidence Score Computed (0.0 - 1.0)
│
▼
Evidence Diff Produced (what changed, what was tried)
│
▼
Approval Policy Applied
│ ├── Score >= 0.9 → Auto-apply, log for batch review
│ ├── Score 0.7-0.89 → Apply in quarantine, flag for individual review
│ ├── Score 0.5-0.69 → Do NOT apply, open PR with evidence for review
│ └── Score < 0.5 → Discard, manual investigation required
│
▼
Intent Fidelity Check (does repaired test still test the same thing?)
│
▼
Rollback if intent fidelity dropsConfidence Scoring
置信度评分
Score each repair candidate on six dimensions (weighted sum, 0.0-1.0):
| Dimension | Weight | Scoring |
|---|---|---|
| Match specificity | 0.30 | testId=1.0, role=0.9, text=0.7, context=0.5, CSS=0.3 |
| Element visible | 0.15 | 1.0 if visible, 0.0 if not |
| Same parent container | 0.15 | 1.0 if same container, 0.0 if different |
| Same element type | 0.15 | 1.0 if same tag+role, 0.0 if different |
| Text similarity | 0.15 | 0.0-1.0 (Levenshtein ratio of accessible name) |
| Attribute overlap | 0.10 | 0.0-1.0 (Jaccard of shared attributes) |
Score thresholds (half-open bands — 0.9 belongs to the auto-apply tier only):
- >= 0.9 — Auto-apply, log for batch review.
- 0.7-0.89 — Apply in quarantine, flag for individual review.
- 0.5-0.69 — Do not apply; open a PR with evidence for review.
- < 0.5 — Discard, manual investigation required.
references/flaky-test-runbook.md从六个维度对每个修复候选方案进行评分(加权求和,0.0-1.0):
| 维度 | 权重 | 评分规则 |
|---|---|---|
| 匹配特异性 | 0.30 | testId=1.0, role=0.9, text=0.7, context=0.5, CSS=0.3 |
| 元素可见性 | 0.15 | 可见为1.0,不可见为0.0 |
| 父容器一致性 | 0.15 | 同一容器为1.0,不同为0.0 |
| 元素类型一致性 | 0.15 | 标签+角色相同为1.0,不同为0.0 |
| 文本相似度 | 0.15 | 0.0-1.0(可访问名称的Levenshtein相似度) |
| 属性重叠度 | 0.10 | 0.0-1.0(共享属性的Jaccard系数) |
评分阈值(半开区间——0.9仅属于自动应用层级):
- >= 0.9 — 自动应用,记录日志供批量审核。
- 0.7-0.89 — 在隔离环境中应用,标记为需单独审核。
- 0.5-0.69 — 不应用,提交包含证据的PR供审核。
- < 0.5 — 丢弃,需人工排查。
references/flaky-test-runbook.mdRepair Evidence
修复证据
Every repair produces an evidence record containing: test file, test name, failure type, original locator, candidate replacements (each with confidence, evidence string, and intent-preserved flag), which candidate was selected, timestamp, approval path, rollback trigger, and a recording of the repair run (Playwright 1.59+ with annotations — the "agentic video receipt"). Without the screencast, a Level-3/4 healed test asks reviewers to trust a JSON record; with it, the diff and the runtime are both inspectable.
screencast.webmpage.screencastshowActions每一次修复都会生成证据记录,包含:测试文件、测试名称、失败类型、原始定位器、候选替代方案(每个方案包含置信度、证据字符串和意图保留标记)、最终选择的方案、时间戳、审批路径、回退触发条件,以及修复运行的录屏(Playwright 1.59+的功能,带标注——即“智能代理视频凭证”)。如果没有录屏,3/4级修复的测试只能让审核人员信任JSON记录;有了录屏,差异和运行过程都可被检查。
screencast.webmpage.screencastshowActionsBuy vs Build
外购 vs 自研
Hand Levels 3-4 to a vendor when you don't want to own a confidence-scored healer; build in-house when you need on-prem/air-gapped deployment, an explicit AI-prompt audit trail, or quarantine logic your tracker can't express. Building stops being worth it once a hosted tool already fingerprints + clusters + auto-quarantines for you.
- For Selenium / Selenide / Robot Framework suites, Healenium remains the dedicated self-healing layer (now on AWS Marketplace).
- For agent-driven self-healing in Playwright, Playwright MCP is the canonical path — it gives the agent live browser control to discover replacement locators when CLI + skills isn't enough.
- Hosted platforms shipping this workflow: Trunk Flaky Tests (auto-quarantine + AI failure clustering; its 2026 Quarantined Tests API returns the current quarantine list programmatically — same hygiene workflow this skill builds by hand), CloudBees Smart Tests (formerly Launchable; agents searching old docs may find the old name), and Datadog Test Optimization (renamed from "Datadog Test Visibility" in December 2024). All three offer fingerprinting + clustering + auto-quarantine that maps onto Levels 3-4.
当你不想维护带置信度评分的修复系统时,可将3-4级功能交给供应商;当你需要本地/离线部署、明确的AI提示审计轨迹,或追踪系统无法实现的隔离逻辑时,可选择自研。当已有托管工具可实现指纹识别+聚类+自动隔离时,自研就不再划算。
- 对于Selenium / Selenide / Robot Framework测试套件,Healenium仍是专用的自修复层(现已上架AWS Marketplace)。
- 对于Playwright中的智能代理驱动自修复,Playwright MCP是标准方案——当CLI+技能不足以解决问题时,它可让智能代理获得浏览器实时控制权来查找替代定位器。
- 提供该流程的托管平台:Trunk Flaky Tests(自动隔离+AI失败聚类;其2026年的Quarantined Tests API可程序化返回当前隔离列表——与本技能手动构建的卫生流程一致)、CloudBees Smart Tests(前身为Launchable;查阅旧文档的智能代理可能会看到旧名称)、Datadog Test Optimization(2024年12月从“Datadog Test Visibility”更名)。这三个平台都提供指纹识别+聚类+自动隔离功能,对应3-4级能力。
Intent Fidelity Checking
意图一致性检查
After applying a repair, verify the test still exercises the same user intent:
- Element type changed (e.g. →
button) — intent NOT preserved, rollback.a - ARIA role changed (e.g. →
button) — intent NOT preserved, rollback.link - Form action changed (targets a different endpoint) — intent NOT preserved, rollback.
- Same tag, role, and form action — intent preserved, keep repair.
A repair that changes WHAT the test verifies (not just HOW it finds elements) must be rolled back.
应用修复后,需验证测试是否仍符合用户意图:
- 元素类型变更(如→
button)——意图未保留,回退修复。a - ARIA角色变更(如→
button)——意图未保留,回退修复。link - 表单动作变更(指向不同端点)——意图未保留,回退修复。
- 标签、角色和表单动作均一致——意图保留,保留修复。
如果修复改变了测试验证的对象(而非仅改变查找元素的方式),必须回退。
Quarantine Management
隔离管理
Quarantine isolates flaky tests so they run but do not block CI. See (Step 6) for the full config and CI wiring; the essentials:
references/flaky-test-runbook.mdtypescript
// Tag the flaky test
test('intermittent WebSocket reconnect', {
tag: ['@quarantine'],
annotation: {
type: 'quarantine',
description: 'Flaky since 2026-03-15. Race condition in WebSocket handler. Ticket: BUG-1234.',
},
}, async ({ page }) => { /* ... */ });typescript
// playwright.config.ts — separate projects
projects: [
{ name: 'stable', testMatch: /.*\.spec\.ts/, grep: /^(?!.*@quarantine)/ }, // exclude quarantine
{ name: 'quarantine', grep: /@quarantine/, retries: 3 },
],In CI, run as a blocking step and with so the quarantine project never blocks the pipeline.
--project=stable--project=quarantinecontinue-on-error: true隔离可将Flaky测试单独运行,不阻塞CI。完整配置和CI集成可查看(第6步);核心内容如下:
references/flaky-test-runbook.mdtypescript
// Tag the flaky test
test('intermittent WebSocket reconnect', {
tag: ['@quarantine'],
annotation: {
type: 'quarantine',
description: 'Flaky since 2026-03-15. Race condition in WebSocket handler. Ticket: BUG-1234.',
},
}, async ({ page }) => { /* ... */ });typescript
// playwright.config.ts — separate projects
projects: [
{ name: 'stable', testMatch: /.*\.spec\.ts/, grep: /^(?!.*@quarantine)/ }, // exclude quarantine
{ name: 'quarantine', grep: /@quarantine/, retries: 3 },
],在CI中,运行作为阻塞步骤,运行时设置,确保隔离项目永远不会阻塞流水线。
--project=stable--project=quarantinecontinue-on-error: trueQuarantine Lifecycle
隔离生命周期
1. DETECT — Test identified as flaky (CI reporter or manual triage)
2. TAG — Add @quarantine annotation with ticket link and date
3. ISOLATE — Quarantine project runs separately, does not block
4. DIAGNOSE — Follow the flaky test runbook (references/flaky-test-runbook.md)
5. FIX — Apply the fix pattern for the classified category
6. VERIFY — Run 50x with --repeat-each, zero failures required
7. RELEASE — Remove @quarantine tag, add annotation documenting the fix1. 检测 — 识别出Flaky测试(CI报告器或人工诊断)
2. 标记 — 添加@quarantine标注,包含工单链接和日期
3. 隔离 — 隔离项目单独运行,不阻塞流水线
4. 诊断 — 遵循Flaky测试手册(references/flaky-test-runbook.md)
5. 修复 — 应用对应分类的修复模式
6. 验证 — 使用--repeat-each运行50次,要求零失败
7. 解除隔离 — 移除@quarantine标签,添加标注记录修复内容Quarantine Hygiene Rules
隔离卫生规则
- Maximum quarantine age: 14 days. After 14 days, fix it or delete it. Permanent quarantine is permanent rot.
- Every quarantine entry has a ticket link. No anonymous quarantines.
- Weekly review. Check the quarantine list every sprint. Aging quarantines get escalated.
- Track quarantine size. More than 5% of tests in quarantine signals a systemic problem requiring process change, not just test fixes.
- 最长隔离时长:14天。14天后,要么修复要么删除。永久隔离就是永久腐化。
- 每个隔离条目都要有工单链接。不允许无来源的隔离。
- 每周审核。每个迭代检查隔离列表。超期的隔离条目需升级处理。
- 追踪隔离规模。超过5%的测试处于隔离状态,说明存在系统性问题,需要调整流程而非仅修复测试。
Anti-Patterns
反模式
1. Silent Selector Replacement
1. 静默选择器替换
Replacing a broken selector with no logging, review, or confidence scoring. The repaired test may now verify a different element entirely. Every repair must produce evidence.
替换损坏的选择器但不记录日志、不审核、不进行置信度评分。修复后的测试可能会验证错误的元素。每一次修复都必须生成证据。
2. "Just Retry It" as a Fix
2. “重试就行”作为修复方案
Retries are a detection mechanism, not a fix. A test that needs retry 2-of-3 will eventually fail 3-of-3 during your most critical release.
重试是检测机制,而非修复方案。需要重试2次才能通过的测试,最终会在最关键的发布中出现3次全失败。
3. Disabling Flaky Tests Permanently
3. 永久禁用Flaky测试
test.skip('flaky, will fix later')test.skip('flaky, will fix later')4. Treating All Flakiness the Same
4. 所有Flakiness一视同仁
Timing issues and data dependencies need completely different fixes. Adding to a data-dependency problem makes the test slower and still flaky.
waitForTimeout(5000)时序问题和数据依赖问题需要完全不同的修复方案。为数据依赖问题添加只会让测试变慢,仍然存在Flaky问题。
waitForTimeout(5000)5. waitForTimeout as a Stability Fix
5. 使用waitForTimeout作为稳定性修复方案
typescript
// NEVER the right fix
await page.waitForTimeout(5000);
// Wait for the actual condition
await expect(page.getByRole('table')).toBeVisible();
await page.waitForResponse(resp => resp.url().includes('/api/data') && resp.status() === 200);typescript
// NEVER the right fix
await page.waitForTimeout(5000);
// Wait for the actual condition
await expect(page.getByRole('table')).toBeVisible();
await page.waitForResponse(resp => resp.url().includes('/api/data') && resp.status() === 200);6. Healing Without Observability
6. 无观测性的修复
Auto-repair that produces no logs, evidence, or confidence scores. You cannot improve what you cannot measure, and you cannot trust what you cannot review.
自动修复不生成日志、证据或置信度评分。你无法改进无法测量的东西,也无法信任无法审核的东西。
7. Over-Engineering Healing Before Writing Stable Tests
7. 未编写稳定测试就过度设计修复框架
Building a complex self-healing framework before adopting basic resilient-locator patterns. Start with multi-attribute selectors and proper waits. Add healing infrastructure only when data shows where breakage occurs.
在采用基本的韧性定位器模式之前,就构建复杂的自修复框架。先从多属性选择器和正确的等待方式开始。只有当数据显示出具体的损坏点时,再添加修复基础设施。
8. No Quarantine Expiry
8. 无隔离过期机制
Tests sit in quarantine for months. Quarantine is a temporary state, not a permanent home. Enforce a 14-day maximum.
测试在隔离状态下停留数月。隔离是临时状态,而非永久归宿。强制执行14天的最长隔离时长。
Failure Modes
故障模式
| Symptom | Likely cause | Fix or check |
|---|---|---|
Backend health check itself flaps → false | Health endpoint is itself flaky/slow | Track the health endpoint's own p99 separately; don't gate diagnosis on a single probe |
| Artifact storage balloons after enabling repair video | | Record only on the repair path, not the happy path |
| Auto-repair accuracy drops below 80% | Confidence threshold too low, or intent-fidelity check skipped | Raise the auto-apply floor; never skip the intent check |
| Quarantine project blocks the pipeline | Missing | Add it; the quarantine project must never block merges |
| 症状 | 可能原因 | 修复或检查方案 |
|---|---|---|
后端健康检查本身出现波动 → 错误的 | 健康端点本身存在Flaky问题/响应缓慢 | 单独追踪健康端点的p99指标;不要仅依赖单次探测进行诊断 |
| 启用修复录屏后,制品存储急剧膨胀 | | 仅在修复路径中录屏,而非正常路径 |
| 自动修复准确率低于80% | 置信度阈值过低,或跳过了意图一致性检查 | 提高自动应用的阈值;永远不要跳过意图检查 |
| 隔离项目阻塞流水线 | 隔离CI步骤缺少 | 添加该配置;隔离项目永远不能阻塞合并 |
Verification
验证
- Reproduce the flake: — it must fail at least once before you trust any fix.
npx playwright test <spec> --repeat-each=20 --workers=4 --trace=on - After fixing, prove stability: — require 50/50 passes, in CI conditions too.
npx playwright test <spec> --repeat-each=50 --workers=4 - Confirm quarantine routing: excludes
npx playwright test --project=stabletests and@quarantineruns only them.--project=quarantine - Confirm selector audit emits numbers: the stability report lists a score per locator and a suite average.
- 复现Flaky问题:——在信任任何修复之前,必须至少失败一次。
npx playwright test <spec> --repeat-each=20 --workers=4 --trace=on - 修复后验证稳定性:——要求50次全部通过,且在CI环境中也需满足。
npx playwright test <spec> --repeat-each=50 --workers=4 - 确认隔离路由:会排除
npx playwright test --project=stable测试,@quarantine仅运行隔离测试。--project=quarantine - 确认选择器审计生成数值:稳定性报告列出每个定位器的评分和套件平均分。
Done When
完成标准
- Every flaky test is identified and categorized by root cause (timing, data dependency, environment, etc.).
- Each flaky test is quarantined or fixed — no test silently retried without a documented plan and ticket reference.
- (or the CI report) lists a stability score per locator and reports a suite average >= 3.5.
selector-stability.md - The flaky-test-rate metric (% of tests passing on retry) is published to the CI dashboard and visible to the team.
- Every quarantine entry has a ticket reference and an expiry date <= 14 days out.
- 每个Flaky测试都已识别并按根因分类(时序、数据依赖、环境等)。
- 每个Flaky测试都已隔离或修复——没有测试在无文档化计划和工单引用的情况下被静默重试。
- (或CI报告)列出每个定位器的稳定性评分,且套件平均分>=3.5。
selector-stability.md - Flaky测试率指标(重试后通过的测试占比)已发布到CI仪表板,团队可见。
- 每个隔离条目都有工单引用,且过期日期<=14天。
Related Skills
相关技能
- selector-drift-recovery — go there to bulk-regenerate many selectors offline after a planned UI refactor; this skill heals one test at runtime.
- playwright-automation — full Playwright setup, Page Object Model, fixtures, and CI integration that the patterns here build on.
- ci-cd-integration — pipeline configuration, parallel execution, and the quarantine job wiring referenced above.
- qa-metrics — track flaky rate, mean-time-to-heal, quarantine size, and selector stability over time.
- ai-bug-triage — when flake investigation reveals a real app bug, hand the failure to the triage pipeline to classify and report it.
- selector-drift-recovery — 计划内UI重构后批量重新生成多个选择器时使用;本技能在运行时修复单个测试。
- playwright-automation — 完整的Playwright设置、页面对象模型、固定数据和CI集成,本技能的模式基于此构建。
- ci-cd-integration — 流水线配置、并行执行和上述引用的隔离任务集成。
- qa-metrics — 长期追踪Flaky率、平均修复时间、隔离规模和选择器稳定性。
- ai-bug-triage — 当Flaky测试排查发现真实应用Bug时,将失败信息提交到分类流水线进行分类和报告。