Playwright测试中page.waitForResponse偶发超时问题排查求助
Playwright测试中Media Size API偶发超时问题排查与解决
测试代码
import { expect, test } from "@playwright/test"; test.describe.configure({ mode: "serial" }); test.describe("Dashboard", () => { let sellerId: string; let userId: string; test.beforeEach(async ({ page }) => { await page.goto("https://ic.ewalls.io/"); await page.getByPlaceholder("Enter your email").click(); await page .getByPlaceholder("Enter your email") .fill("sridhar.fullstack.dev.india@gmail.com"); await page.getByPlaceholder("Enter your password").click(); await page.getByPlaceholder("Enter your password").fill("Qq1!Qq1!"); await page.getByLabel("Show password").click(); await page.getByRole("button", { name: "Sign in" }).click(); const loginResponse = await page.waitForResponse( (response) => response.url().includes("/dev/api/v1/user/getroutes") && response.status() === 200 ); const loginJsonResponse = await loginResponse.json(); sellerId = loginJsonResponse.user.sellerId; userId = loginJsonResponse.user.userId; expect(sellerId).toBeTruthy(); expect(userId).toBeTruthy(); console.log("\x1b[36m%s\x1b[0m", `SellerId: ${sellerId}`); console.log("\x1b[36m%s\x1b[0m", `UserId: ${userId}`); console.log("\x1b[34m%s\x1b[0m", "Login Passed ✓"); }); test("Media Size Test", async ({ page }) => { console.log("\x1b[36mRunning Media Size test [*]\x1b[0m"); const mediaSizeResponsePromise = page.waitForResponse( (response) => response.url().includes(`dev/api/v1/dashboard/mediasize/${sellerId}`) && response.status() === 200, { timeout: 50000 } ); const mediaSizeResponse = await mediaSizeResponsePromise; const mediaSizeResponseBody = await mediaSizeResponse.json(); console.log( "Dashboard Media Size API Response:", JSON.stringify(mediaSizeResponseBody, null, 2) ); const totalMediaSize = mediaSizeResponseBody.totalMediaSize.toFixed(3); const mediaSizeInMB = `${totalMediaSize}MB`; await page.getByRole("heading", { name: mediaSizeInMB }).click(); console.log(`Clicked on media size: ${mediaSizeInMB}`); console.log("\x1b[34m%s\x1b[0m", "Media Size checked in UI ✓"); }); });
报错信息
Running Media Size test [*] 1) [Google Chrome] › eWalls.test.ts:129:7 › Dashboard › Media Size Test ────────────────────────── TimeoutError: page.waitForResponse: Timeout 50000ms exceeded while waiting for event "response" 130 | console.log("\\x1b\[36mRunning Media Size test \[\*\]\\x1b\[0m"); 131 | > 132 | const mediaSizeResponsePromise = page.waitForResponse( > | ^ > 133 | (response) => > 134 | response.url().includes(`dev/api/v1/dashboard/mediasize/${sellerId}`) && > 135 | response.status() === 200, at /home/sridhar/Desktop/Sridhar/iris_frontend-Development/playwright/test/eWalls.test.ts:132:43 1 failed [Google Chrome] › eWalls.test.ts:129:7 › Dashboard › Media Size Test ─────────────────────────── 21 skipped 3 passed (1.7m)
原因分析
- API请求未触发:测试代码中创建
waitForResponsePromise后,没有执行导航或UI操作加载Dashboard页面,导致Media Size API根本未被调用,自然等待超时。 - URL匹配不精准:用
includes("dev/api/v1/...")匹配时缺少前缀/,可能无法匹配实际完整请求URL,或误匹配无关请求。 - 测试环境响应不稳定:生产环境正常但测试环境偶发超时,说明测试环境API服务或网络存在波动,响应延迟超过设置的50s。
- 未处理非200响应:如果API返回4xx/5xx状态码,当前匹配条件会忽略该响应,导致测试一直等待200响应而超时。
解决方案
1. 先触发API请求再等待响应
创建waitForResponse Promise后,执行触发Dashboard加载的操作,确保API被调用:
test("Media Size Test", async ({ page }) => { console.log("\x1b[36mRunning Media Size test [*]\x1b[0m"); // 导航到Dashboard页面,触发Media Size API请求 await page.goto("https://ic.ewalls.io/dashboard"); const mediaSizeResponsePromise = page.waitForResponse( (response) => response.url().includes(`/dev/api/v1/dashboard/mediasize/${sellerId}`) && response.status() === 200, { timeout: 50000 } ); const mediaSizeResponse = await mediaSizeResponsePromise; // 后续代码不变 });
若API在特定元素加载后触发,可先等待元素出现:
await page.waitForSelector('[data-testid="media-size-section"]'); // 替换为实际元素选择器
2. 优化URL匹配逻辑
用更精准的匹配方式避免误匹配:
- 增加前缀
/确保路径正确:response.url().includes(`/dev/api/v1/dashboard/mediasize/${sellerId}`) - 用正则匹配完整路径结尾:
response.url().match(new RegExp(`/dev/api/v1/dashboard/mediasize/${sellerId}$`)) - 直接匹配完整URL(域名固定时):
response.url() === `https://ic.ewalls.io/dev/api/v1/dashboard/mediasize/${sellerId}`
3. 增加重试机制
针对测试环境波动,给测试添加重试配置:
// 单个测试重试2次 test("Media Size Test", async ({ page }) => { /* ... */ }).retry(2); // 或在playwright.config.ts全局配置 export default defineConfig({ testDir: './tests', retries: 2, });
4. 排查非200响应
临时添加日志,查看所有匹配URL的响应状态:
const mediaSizeResponsePromise = page.waitForResponse( (response) => { const isTargetUrl = response.url().includes(`/dev/api/v1/dashboard/mediasize/${sellerId}`); if (isTargetUrl) { console.log(`Media Size API响应状态: ${response.status()},URL: ${response.url()}`); } return isTargetUrl && response.status() === 200; }, { timeout: 50000 } );
5. 延长超时时间(备选)
确认测试环境响应慢时,可临时加大超时:
{ timeout: 60000 } // 60秒
内容的提问来源于stack exchange,提问作者Sridhar
相关产品推荐
相关产品推荐

