返回博客
QA测试 Playwright 邮件测试 自动化

如何使用 Playwright 测试邮件验证码(2026 完整指南)

· 阅读约 8 分钟

涉及邮件验证的端到端测试向来是 QA 工程师的噩梦。用户点击"注册"后,系统发出一封邮件,而测试脚本必须以自动化、可重复的方式读取该邮件、提取 6 位验证码,并将其填入表单。如果你曾经尝试过解决这个问题,就一定深有体会。

传统方案的困境

大多数团队在测试邮件流程时会遭遇以下几个死胡同:

  • 共享测试账号(Gmail):本地可用,但在 CI 环境中会因 Google 检测到机器人登录而失败。多个并行测试还会产生 OTP 交叉污染。
  • Mailinator 免费版:公开收件箱且免费版无 API 接口。任何人都能读取你的测试邮件。部分服务(包括亚马逊和 Stripe)会主动屏蔽 Mailinator 域名。
  • 自托管 MailHog / MailDev:需要修改应用的 SMTP 配置,对第三方身份验证流程(OAuth 发送真实邮件)无效,还会带来额外的运维负担。
  • 完全 mock 邮件:会错过真实的模板渲染错误、失效链接和字符编码问题——这些 bug 只会在真实邮件中出现。
  • 一次性邮件服务:没有稳定 API、有速率限制、域名随时变化——是不稳定测试的温床。

你真正需要的是一个私有、可通过 API 访问的专属邮箱——可以通过代码创建、可靠轮询,且完全由你掌控。

第一节:使用真实邮箱 API 进行测试

最干净的解决方案是:在每个测试套件运行前通过 API 创建专用测试邮箱,测试期间使用,之后(可选)清理。GridInbox 正好提供了这套能力:REST API 支持创建邮箱、列出邮件、以及从来信中提取已解析的 OTP 验证码。

相比其他方案的核心优势:

  • 每个测试拥有独立收件箱,并行运行时零干扰
  • 收件箱是私有的,不像 Mailinator 那样公开可见
  • OTP 验证码由服务端解析,以结构化 JSON 字段返回
  • 兼容任何邮件提供商——底层接收基础设施为真实 SMTP/SES
  • 支持自定义域名,可使用 @test.yourdomain.com

第二节:完整 Playwright 示例

下面演示一个完整的端到端测试:注册新用户 → 接收验证邮件 → 提取 OTP → 提交验证 → 断言账号已激活。

第一步:通过 API 创建测试收件箱

// helpers/email.ts
const API_BASE = 'https://api.gridinbox.com/api/v1';
const API_KEY  = process.env.GRIDINBOX_API_KEY!;

export async function createTestInbox(label: string) {
  const res = await fetch(`${API_BASE}/mailboxes`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': API_KEY, // 通过请求头传递 API 密钥
    },
    body: JSON.stringify({ name: label }),
  });
  const data = await res.json();
  // 返回 { id, address, name, ... }
  return data as { id: string; address: string };
}

第二步:轮询等待 OTP 邮件

export async function waitForOtp(
  mailboxId: string,
  options = { timeoutMs: 30_000, intervalMs: 2_000 }
): Promise<string> {
  const deadline = Date.now() + options.timeoutMs;

  while (Date.now() < deadline) {
    const res = await fetch(`${API_BASE}/mailboxes/${mailboxId}/messages?limit=1`, {
      headers: { 'X-API-Key': API_KEY },
    });
    const { messages } = await res.json();

    if (messages?.length > 0) {
      const msg = messages[0];
      // GridInbox 服务端已解析 OTP
      if (msg.otp) return msg.otp as string;
      // 兜底:从主题/正文中用正则提取
      const match = (msg.subject + ' ' + msg.text_body).match(/\b(\d{4,8})\b/);
      if (match) return match[1];
    }

    // 等待后重试
    await new Promise(r => setTimeout(r, options.intervalMs));
  }

  throw new Error(`${options.timeoutMs}ms 内未收到 OTP,请检查邮件发送逻辑`);
}

第三步:完整 Playwright 测试用例

// tests/auth/email-verification.spec.ts
import { test, expect } from '@playwright/test';
import { createTestInbox, waitForOtp } from '../helpers/email';

test('用户注册后可完成邮件验证', async ({ page }) => {
  // 1. 为本次运行创建唯一测试收件箱
  const inbox = await createTestInbox(`pw-test-${Date.now()}`);
  const testEmail = inbox.address;

  // 2. 使用测试邮箱注册
  await page.goto('/register');
  await page.fill('[name="email"]', testEmail);
  await page.fill('[name="password"]', 'TestPass123!');
  await page.click('[type="submit"]');

  // 3. 断言已进入验证步骤
  await expect(page.locator('text=Check your email')).toBeVisible();

  // 4. 通过 GridInbox API 获取 OTP
  const otp = await waitForOtp(inbox.id);

  // 5. 填入验证码
  await page.fill('[name="otp"]', otp);
  await page.click('[type="submit"]');

  // 6. 断言跳转到 dashboard
  await expect(page).toHaveURL('/dashboard');
  await expect(page.locator('text=Welcome')).toBeVisible();
});

第三节:在 CI/CD 中运行

将 API Key 作为 Repository Secret 添加到 GitHub Actions,并在 workflow 文件中引用:

# .github/workflows/e2e.yml
name: E2E 测试

on: [push, pull_request]

jobs:
  playwright:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npx playwright install --with-deps
      - name: 运行端到端测试
        env:
          GRIDINBOX_API_KEY: ${{ secrets.GRIDINBOX_API_KEY }}
        run: npx playwright test

由于每个测试都创建了独立的收件箱,Playwright 的并行执行和分片功能(--shard=1/4)可以完美运行,不会出现任何收件箱冲突。

第四节:最佳实践

  • 语义化命名收件箱:使用 pw-{testName}-{timestamp} 格式前缀,方便在调试时识别收件箱归属。
  • 根据 SES 投递速度设置合理的轮询超时:AWS SES 通常在 2–5 秒内投递。30 秒超时足够充裕;对于较慢的 SMTP 中继,可适当增加至 60 秒。
  • 测试后清理收件箱:test.afterAll 钩子中调用 API 删除测试邮箱,保持 GridInbox 面板整洁,避免存储积累。
  • 使用 fixture 模式管理收件箱生命周期:Playwright fixture 可在一个测试文件的多个用例间共享同一收件箱,而无需每次重新创建——适合"一次登录、测试多个页面"的场景。
  • 永远不要硬编码邮件地址:始终为每次运行生成唯一地址。硬编码地址在 CI 矩阵并发时会产生竞态条件。

总结

邮件验证测试不必再是那个让团队头疼、需要人工干预的不稳定环节。借助真实邮箱 API,你可以让邮件流程成为 Playwright 测试套件中的一等公民——确定性、并行安全、CI 就绪。

本文描述的模式——创建收件箱 → 触发邮件 → 轮询 API → 提取 OTP → 断言结果——适用于所有基于邮件的流程:注册验证、密码重置、Magic Link 登录、通知邮件等。

立即开始自动化邮件测试

免费注册 GridInbox,几分钟内即可通过 API 创建隔离测试收件箱。无需信用卡。

免费注册 →