Playwright 1.62 新增 AbortSignal 与隔离重试:代理测试如何更安全地停止和恢复

纸艺浏览器测试通道通过可控停止闸门

代理测试的失败方式与普通界面测试不同:页面本身可能正常,但某个出口极慢;隧道可能已建立,却迟迟收不到响应正文;认证重试也可能在结果早已失去业务价值后继续占用 worker。Playwright 1.62 带来两项与此高度相关的控制能力:多数操作及 Web-first 断言可接收 AbortSignal,测试配置新增 isolated 重试策略。

它们不会让代理本身变得可靠,但能让失败边界更清楚。团队可以在业务时限到达时主动终止任务,区分“被取消”和“网络故障”,并避免大量失败会话与健康的首轮测试争抢资源。

这次更新带来了什么

多数动作、导航、等待和 Web-first 断言现在可以接收 AbortSignal。信号触发后,操作可在自身超时之前被取消;除非明确关闭,原有默认超时仍然有效。

testConfig.retryStrategy 新增 isolated 模式。启用后,失败用例会在主测试轮次结束后,由单个 worker 逐一重试。默认策略仍是在 worker 可用时立即重试。

对代理验证而言,两者处理的是不同层次:

  • AbortSignal 限制单个操作或完整业务流程的最长有效生命期;
  • 隔离重试决定失败用例在何时、何种资源条件下再次执行。

为什么普通超时还不够

一个测试通常同时存在连接、导航、断言、用例和整批任务等多个时间预算。如果每层只认识自己的计时器,请求即使在技术上仍未超时,也可能早已超过业务允许的窗口。

例如,一次区域可用性检查必须在 20 秒内完成。导航最多等待 15 秒,后续断言又可等待 10 秒。没有共享取消信号时,整个流程可能耗时 25 秒,而它在第 20 秒就已经失去业务价值。

可以用一个控制器表示外层截止时间,并把同一信号传给属于该流程的操作:

import { test, expect } from '@playwright/test';

test('区域线路满足购买流程时限', async ({ page }) => {
  const controller = new AbortController();
  const deadline = setTimeout(() => controller.abort('workflow deadline'), 20_000);

  try {
    await page.goto('https://en.98ip.com/', {
      waitUntil: 'domcontentloaded',
      timeout: 15_000,
      signal: controller.signal,
    });
    await expect(page.locator('body')).toBeVisible({
      timeout: 5_000,
      signal: controller.signal,
    });
  } finally {
    clearTimeout(deadline);
  }
});

只测试你有权访问的目标。代理账号应放在环境变量或密钥管理系统中,不得写进代码、trace、截图或测试名称。

“取消”应当成为独立结果

不要把所有中止操作都并入笼统的“代理错误”。至少记录:

  • 操作名称和线路标签;
  • 计划截止时间与实际耗时;
  • 是业务预算触发、人工触发,还是父任务清理触发;
  • 不含凭据的代理会话标识;
  • 可用时记录出口区域和网络协议族;
  • 最后完成的阶段:隧道、TLS、响应头、正文或断言;
  • 重试轮次及最终处置。

这对采购决策非常关键。持续无法满足 20 秒预算的线路、认证被拒的线路、以及收到目标站策略响应的线路,需要采取完全不同的措施。

隔离重试什么时候有价值

立即重试适合偶发瞬态故障,但也可能放大问题。如果多个 worker 同时遇到慢出口池,立即重试会在资源已经异常时增加流量、消耗新会话、扭曲成功率并提高成本。

import { defineConfig } from '@playwright/test';

export default defineConfig({
  retries: 1,
  retryStrategy: 'isolated',
  workers: 6,
});

首轮反映正常并发条件;隔离轮次则判断去除资源争用后故障是否仍存在。若六 worker 时失败、单 worker 时通过,更像并发、配额或共享资源问题;若隔离后仍失败,则更可能与线路、目标兼容性、配置或确定性测试缺陷有关。

代理测试套件的落地步骤

1. 先定义业务截止时间

为登录、搜索、结账、数据采集和广告验证分别设定“仍有价值”的最长时限,不要简单采用最大的技术超时。

2. 保留分层超时

AbortSignal 应补充而不是替代连接、导航、断言和用例超时。除非另有强制截止机制,否则不要把默认超时设为零。

3. 使用结构化取消原因

采用 workflow_deadlinequota_guardoperator_cancelled 等稳定原因码,不要只依赖异常文本。

4. 分开统计首轮与重试

分别报告首轮成功率、重试恢复率和最终成功率。最终 99% 成功率可能掩盖昂贵的 15% 重试率。

5. 对比立即重试与隔离重试

保持目标、并发和会话规则一致,对比恢复率、延迟、出口复用、传输字节和每个可用结果成本。

6. 按线路小批量上线

先选择少量区域和流程,确认取消操作能关闭页面、释放会话,且不会遗留后台请求。

采购与运维检查清单

  • 每个关键流程是否都有明确业务时限?
  • 能否区分主动取消与代理连接失败?
  • 是否分别报告首轮和重试结果?
  • 重试时是有意保持会话还是有意更换出口?
  • 是否按账号、区域和目标执行并发上限?
  • 被取消请求是否纳入带宽和成本?
  • 能否在隔离 worker 中保持其他变量不变地复测?
  • trace、截图、日志和示例中是否完全没有凭据?

常见错误

把取消当成资源清理。 页面、context、流和定时器仍应在 finally 中释放。

对所有取消都自动重试。 超过业务时限的流程可能不值得重试。

同时改变出口和并发。 这样无法判断恢复原因。

只报告最终成功率。 采购方还需要首轮成功率、延迟分布、重试恢复率及单位有效结果成本。

合规说明

仅在获得授权的系统和数据范围内进行代理测试,并遵守目标站条款、速率限制、隐私义务和区域规则。取消与重试控制应减少无意义流量,而不是用于绕过访问控制。

FAQ

AbortSignal 会替代 Playwright 超时吗?

不会。它增加了一条独立取消路径。仍需保留合理的操作和用例超时,以便准确诊断。

所有代理失败都应该隔离重试吗?

不应该。只重试瞬态且幂等的工作。认证失败、策略拒绝、无效配置和主动取消通常应先检查。

隔离重试失败就能证明是代理问题吗?

不能。目标站、测试逻辑、DNS、TLS 和会话策略仍可能导致失败。

采购时应比较哪些指标?

在同一矩阵下比较首轮成功率、p50/p95 延迟、意外轮换、重试恢复率、取消率、传输字节和每个有效流程成本。

相关 98IP 指南