Run Playwright Tests in Azure DevOps Pipeline: Complete Guide
Complete guide to running Playwright tests in Azure DevOps CI/CD pipelines. Covers YAML configuration, browser installation, parallel execution, test sharding, HTML report publishing, and debugging failed tests.
Playwright integrates cleanly with Azure DevOps — it produces JUnit XML output natively, captures screenshots and traces on failure, and supports parallel execution across multiple agents. This guide covers a production-ready Playwright pipeline configuration.
Basic Playwright pipeline
# azure-pipelines.yml
trigger:
branches:
include: [main]
pr:
branches:
include: [main]
pool:
vmImage: ubuntu-latest
steps:
- task: NodeTool@0
inputs:
versionSpec: '20.x'
displayName: Setup Node.js
- script: npm ci
displayName: Install npm packages
- script: npx playwright install --with-deps
displayName: Install Playwright browsers
- script: npx playwright test
displayName: Run Playwright tests
env:
BASE_URL: $(STAGING_URL)
- task: PublishTestResults@2
displayName: Publish results
inputs:
testResultsFormat: JUnit
testResultsFiles: playwright-results/results.xml
testRunTitle: Playwright — $(Build.BuildNumber)
condition: always()
- task: PublishPipelineArtifact@1
displayName: Upload HTML report
inputs:
targetPath: playwright-report
artifact: playwright-report
condition: always()playwright.config.ts for CI
import { defineConfig, devices } from '@playwright/test'
export default defineConfig({
testDir: './tests',
fullyParallel: true,
forbidOnly: !!process.env.CI, // Fail if test.only left in code
retries: process.env.CI ? 2 : 0, // Retry twice in CI
workers: process.env.CI ? 4 : undefined,
reporter: [
['junit', { outputFile: 'playwright-results/results.xml' }],
['html', { outputFolder: 'playwright-report', open: 'never' }],
['list'],
],
use: {
baseURL: process.env.BASE_URL || 'http://localhost:3000',
trace: 'on-first-retry', // Capture traces on retry
screenshot: 'only-on-failure',
video: 'on-first-retry',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
],
})Multi-stage pipeline with sharding
For large test suites, split tests across multiple agents using Playwright's built-in sharding:
trigger:
branches:
include: [main]
pool:
vmImage: ubuntu-latest
stages:
- stage: Test
jobs:
# Run 4 shards in parallel
- job: Shard1
displayName: Tests shard 1/4
steps:
- template: templates/playwright-steps.yml
parameters:
shardIndex: 1
shardTotal: 4
- job: Shard2
displayName: Tests shard 2/4
steps:
- template: templates/playwright-steps.yml
parameters:
shardIndex: 2
shardTotal: 4
- job: Shard3
displayName: Tests shard 3/4
steps:
- template: templates/playwright-steps.yml
parameters:
shardIndex: 3
shardTotal: 4
- job: Shard4
displayName: Tests shard 4/4
steps:
- template: templates/playwright-steps.yml
parameters:
shardIndex: 4
shardTotal: 4
# Merge results from all shards
- job: MergeReports
displayName: Merge and publish reports
dependsOn: [Shard1, Shard2, Shard3, Shard4]
condition: always()
steps:
- task: NodeTool@0
inputs:
versionSpec: '20.x'
- script: npm ci
- task: DownloadPipelineArtifact@2
inputs:
artifact: shard-results
targetPath: all-results
- script: npx playwright merge-reports --reporter=html all-results
displayName: Merge HTML reports
- task: PublishPipelineArtifact@1
inputs:
targetPath: playwright-report
artifact: merged-playwright-reportTemplate templates/playwright-steps.yml:
parameters:
- name: shardIndex
type: number
- name: shardTotal
type: number
steps:
- task: NodeTool@0
inputs:
versionSpec: '20.x'
- script: npm ci
- script: npx playwright install --with-deps chromium
- script: |
npx playwright test \
--shard=${{ parameters.shardIndex }}/${{ parameters.shardTotal }} \
--reporter=blob
displayName: Playwright shard ${{ parameters.shardIndex }}/${{ parameters.shardTotal }}
env:
BASE_URL: $(STAGING_URL)
- task: PublishPipelineArtifact@1
inputs:
targetPath: blob-report
artifact: shard-results
condition: always()Viewing test results and traces
After the pipeline runs:
- Click the pipeline run → Tests tab
- See all tests with pass/fail status, duration, error messages
- Click a failed test to see the failure message
- Download the
playwright-reportartifact → openindex.html - In the HTML report, click a failed test → view screenshot, video, and trace
Playwright trace viewer:
Download the trace file (.zip) from the failed test, then run:
npx playwright show-trace trace.zipThe trace viewer shows every action, network request, and DOM state — invaluable for diagnosing failures that don't reproduce locally.
Common errors and fixes
Error: Error: browserType.launch: Executable doesn't exist at /root/.cache/ms-playwright/...
Fix: Add npx playwright install --with-deps chromium before the test step. The --with-deps flag installs OS-level dependencies (libgtk, etc.) needed on Ubuntu.
Error: Tests fail with "Target page, context or browser has been closed"
Fix: Tests are timing out and Playwright force-closes the browser. Increase the timeout in playwright.config.ts or add explicit waits (await page.waitForLoadState('networkidle')).
Error: ENOENT: no such file or directory, open 'playwright-results/results.xml'
Fix: Add mkdir -p playwright-results before running tests, or configure the output directory in playwright.config.ts to match what PublishTestResults expects.
Error: Playwright tests pass in the pipeline but HTML report is empty
Fix: The reporter array in playwright.config.ts must include the HTML reporter. The open: 'never' option is important in CI — without it, Playwright tries to open a browser which fails on headless agents.
Error: Shard jobs all pass but MergeReports fails to find artifacts
Fix: All shard jobs must upload their blob reports to the same artifact name. When using DownloadPipelineArtifact@2, ensure the artifact name matches exactly what the shard jobs upload.
Stay ahead in AI-driven QA
Get practical tutorials on test automation, AI testing, and quality engineering — straight to your inbox. No spam, unsubscribe any time.
Discussion
Sign in with GitHub to comment · powered by Giscus