Playwright测试本地正常但Azure DevOps流水线批量执行失败求助
问题分析
本地执行npx playwright test时所有测试正常,但在Azure DevOps流水线批量执行时,仅少数测试通过,其余出现net::ERR_CONNECTION_RESET/NS_ERROR_NET_RESET连接重置错误,单个测试文件执行无异常。核心问题大概率是批量执行时的高频请求触发了目标服务或Azure网络的限流/防爬机制,或是登录逻辑中的等待策略不够健壮,导致网络请求未完成就继续执行后续操作。
解决方案
1. 优化登录逻辑,添加重试与健壮等待
当前登录逻辑的时序控制和异常处理不足,修改登录代码如下:
import { Page, expect } from '@playwright/test'; export class login { private page: Page; constructor(page: Page) { this.page = page; } async loginToAppWithAllLicenses() { // 给goto加重试和更长超时,处理连接波动 await this.page.goto('https://mywebsite.com', { waitUntil: 'networkidle', timeout: 120000, retry: 2 }); // 先断言元素可见再操作,避免提前点击 await expect(this.page.locator('div[role="button"]:has-text("Email")')).toBeVisible({ timeout: 30000 }); await Promise.all([ this.page.waitForNavigation({ waitUntil: 'networkidle' }), this.page.locator('div[role="button"]:has-text("Email")').click(), ]); await expect(this.page.locator('[placeholder="Email Address"]')).toBeVisible(); await this.page.locator('[placeholder="Email Address"]').fill('email here..'); await expect(this.page.locator('[placeholder="Password"]')).toBeVisible(); await this.page.locator('[placeholder="Password"]').fill('password here..'); await expect(this.page.locator('button:has-text("Sign in")')).toBeVisible(); await Promise.all([ this.page.waitForNavigation({ waitUntil: 'networkidle' }), this.page.click('button:has-text("Sign in")'), ]); await expect(this.page.locator('.b-number-cell')).toBeVisible(); await Promise.all([ this.page.waitForNavigation({ waitUntil: 'networkidle' }), this.page.click('.b-number-cell'), ]); } }
2. 给测试添加间隔延迟
批量执行时高频请求容易触发限流,在beforeEach中加入固定延迟降低请求频率:
test.beforeEach(async ({ page }, testInfo) => { console.log(`beforeEach initiated, running ${testInfo.title}`); // 3秒间隔,避免请求过于密集 await page.waitForTimeout(3000); const lg = new login(page); await lg.loginToAppWithAllLicenses(); });
3. 调整Playwright配置增强稳定性
修改playwright.config.ts,优化超时、并行和调试设置:
import type { PlaywrightTestConfig } from '@playwright/test'; import { devices } from '@playwright/test'; const config: PlaywrightTestConfig = { testDir: './tests', timeout: 120 * 1000, // 延长全局超时 expect: { timeout: 10000 // 延长断言超时 }, fullyParallel: false, // 强制关闭并行 forbidOnly: !!process.env.CI, retries: 2, // 增加重试次数 workers: 1, // 固定单worker执行 reporter: 'html', use: { actionTimeout: 30000, // 设置操作超时 screenshot: 'only-on-failure', trace: 'retain-on-failure', // 失败时保留trace方便排查 viewport: { width: 1920, height: 1080 }, }, projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'], launchOptions: { args: ['--no-sandbox'] // 规避Chrome沙箱可能导致的网络问题 }, }, }, ], outputDir: 'test-results/', }; export default config;
4. 优化流水线脚本
修改azure-pipelines.yml,添加缓存并明确环境变量:
trigger: - tests/playwright pool: vmImage: 'windows-latest' steps: - script: echo Running azure-pipelines.yml... displayName: 'Run a one-line script' - task: NodeTool@0 inputs: versionSpec: '16.x' displayName: 'nodetool 16.x' - task: Cache@2 inputs: key: 'npm | "$(Agent.OS)" | package-lock.json' restoreKeys: | npm | "$(Agent.OS)" path: node_modules displayName: 'Cache npm dependencies' - task: Npm@1 inputs: command: 'ci' - task: CmdLine@2 inputs: script: 'npx playwright install --with-deps chromium' displayName: 'Install Playwright Chromium with dependencies' - task: CmdLine@2 inputs: script: 'set CI=true && npx playwright test' displayName: 'Run Playwright tests'
5. 排查网络限制
如果以上方案无效,需确认:
- 目标应用是否对Azure DevOps的IP段有访问限制
- 流水线是否配置了代理,导致连接中断
- 查看目标应用服务器日志,是否有针对Azure IP的限流记录
内容的提问来源于stack exchange,提问作者ttqa
相关产品推荐
相关产品推荐

