Playwright 邮件测试:端到端教程
本教程演示如何用 Playwright 端到端地测试一条真实的邮件流程——不打桩、不 mock。我们为每个用例开一个一次性收件箱,驱动注册流程,再通过 API 读取验证邮件并提取验证码。它建立在一次性邮箱 API 之上,也是开发者邮件测试指南的一部分。
思路
每个用例开一个收件箱(不是每个套件一个——共用会把残留状态的问题又招回来)。在浏览器里触发流程,轮询收件箱 API 拿到邮件,用一个简单的匹配提取验证码,再把它输回页面。
一个可复用的 fixture
把这些收件箱调用包进一个 Playwright fixture,每个测试就会自动拿到一个全新地址,而测试本体只关注行为、不关心传输细节:
// inbox.ts — talks to your MoeMail-style API
export async function createInbox() {
const res = await fetch(API + '/emails/generate', {
method: 'POST',
headers: { 'X-API-Key': process.env.MAIL_KEY },
})
return res.json() // { id, address }
}
export async function waitForMessage(id, timeoutMs) {
const deadline = Date.now() + (timeoutMs || 30000)
while (Date.now() < deadline) {
const res = await fetch(API + '/emails/' + id + '/messages', {
headers: { 'X-API-Key': process.env.MAIL_KEY },
})
const list = await res.json()
if (list.messages && list.messages.length) return list.messages[0]
await new Promise(r => setTimeout(r, 1500))
}
throw new Error('no email arrived in time')
}
测试本体
import { test, expect } from '@playwright/test'
import { createInbox, waitForMessage } from './inbox'
test('verifies signup email', async ({ page }) => {
const inbox = await createInbox()
await page.goto('/signup')
await page.getByLabel('Email').fill(inbox.address)
await page.getByRole('button', { name: 'Sign up' }).click()
const msg = await waitForMessage(inbox.id, 30000)
const code = msg.text.match(/[0-9]{6}/)[0]
await page.getByLabel('Verification code').fill(code)
await expect(page.getByText('Welcome')).toBeVisible()
})
注意 Date.now() 给轮询循环兜了底,而那个匹配抓的是一个六位验证码;如果你要的是链接,就改成匹配 URL,再对它调 page.goto()。
让它更不容易抖
能用 Webhook 就别用轮询,以削减延迟;给每次运行一个唯一地址,让并行测试永不撞车;并把 CI 超时设得紧一点。同一套配方也适用于 OTP 与 2FA 登录,同一个 fixture 在 Cypress 和 Selenium 里照样能用。
动手开始
从个人资料里取一个 API 密钥,读一读 OpenAPI 文档,把上面的 fixture 丢进你的测试套件。还不熟悉这套思路?先从开发者邮件测试看起。