| Duration | 15 minutes |
| Level | Beginner |
| Type | Demo + Configuration |
Learning Objectives
After completing this lab, you will be able to:
- Understand CI/CD pipeline concepts for test automation
- Read and modify an Azure DevOps YAML pipeline
- Run functional and accessibility suites as independent matrix jobs
- Create a pipeline in Azure DevOps from an existing YAML file
- View test results and artifacts in Azure DevOps
- Decide when to run tests (push, PR, schedule)
Prerequisites
- Lab 03 completed
- An Azure DevOps organization and project
- Push access to the Azure DevOps (or mirrored GitHub) repository
[!NOTE] Choose GitHub Actions for the alternative CI lab. Azure Pipelines can also build a GitHub repository.
Exercises
Exercise 1: Review the Pipeline
Open .azuredevops/pipelines/playwright-tests.yml in VS Code. Focus on this matrix from the full pipeline:
jobs:
- job: Playwright
displayName: 'Playwright tests'
strategy:
maxParallel: 2
matrix:
Functional:
suite: 'functional'
testSuiteId: '3203'
expectedTestCount: '9'
junitPath: 'test-results/junit.xml'
reportPath: 'playwright-report'
resultsPath: 'test-results'
Accessibility:
suite: 'accessibility'
testSuiteId: '3204'
expectedTestCount: '3'
junitPath: 'test-results/accessibility/junit.xml'
reportPath: 'playwright-report/accessibility'
resultsPath: 'test-results/accessibility'
Each matrix entry runs independently on an Ubuntu agent. maxParallel: 2 allows both suites to run at once, subject to your organization’s parallel-job capacity. With one available slot, the jobs queue instead of running simultaneously.
Read the steps below the matrix in the full pipeline:
UseNode@1installs Node.js 20;npm installinstalls test dependencies.- Playwright installs Chromium and its system dependencies.
npm run test:$(suite)selects the functional or accessibility config.PLAYWRIGHT_SCREENSHOT: 'on'enables screenshots for every test, and the shared config records traces on the first retry.PowerShell@2runsscripts/publish-test-plan-results.ps1to publish$(junitPath)into a build-linked automated run in Test Plan3201. Failed tests, missing results, unmatched automation identities, or publication errors fail this step. It runs after test failures withsucceededOrFailed().PublishPipelineArtifact@1publishes suite-specific reports and raw results withcondition: succeededOrFailed(), preserving generated evidence after failures.
[!IMPORTANT] The YAML
prtrigger applies to GitHub repositories. For Azure Repos Git, configure a build validation branch policy onmainto run this pipeline for PRs. Thetriggersection runs builds for pushes tomainin either case.
Test Plan Publishing Setup
This project’s pipeline targets Plan 3201, with static suites 3203 (Functionality, nine cases) and 3204 (Accessibility, three cases). Each case must have its native automation association: exact test name, source filename, and automation ID. Each case currently has one test configuration and test point. Change the plan ID, suite IDs, and expected counts when using another project.
The publisher matches JUnit name and classname to those associations, creates a run bound to the suite’s test points and current build, records actual outcomes, attaches the original JUnit report, and completes the run. It then verifies each point’s last run and outcome. It does not change test-case workflow states or mark User Stories complete. Failed tests stay failed; skipped tests are not passed.
Native automation association alone does not update test point outcomes when using PublishTestResults@2. This pipeline replaces that task with plan-aware publishing, so each suite has one build-linked run per job attempt. Retrying a job creates another execution attempt. Do not add the old publisher alongside this step, or the build will contain duplicate result sets. Screenshots, traces, and HTML reports remain pipeline artifacts; result comments link to them.
The YAML passes $(System.AccessToken) only to the publishing step. In Azure DevOps, ensure the job’s Build Service identity can read the plan, suites, and work items and has View test runs, Create test runs, and Manage test runs permissions. For a project-scoped job token this is normally OnSIS Build Service (MngEnvMCAP675646); collection-scoped jobs use the collection Build Service identity. A 401 or 403 fails publication and requires checking token availability and these permissions. Do not substitute a PAT in source code. Only trusted pipeline code should receive this write-capable token.
Run the publisher’s isolated checks from the repository root:
pwsh -File scripts/publish-test-plan-results.Tests.ps1
These checks use mocked API responses and do not write to Azure DevOps. After publishing the YAML, verify a real CI run using the Build Service identity. Concurrent executions targeting the same test points compete for the latest outcome; a verification mismatch fails the step rather than claiming success. On-demand execution from the Test Plans UI is not configured by this publisher.
Exercise 2: Create the Pipeline in Azure DevOps
If the pipeline has not been created yet in your Azure DevOps project:
- Open your project in Azure DevOps and select Pipelines > New pipeline.
- Choose the location of your code (Azure Repos Git or GitHub).
- Select your repository.
- Choose Existing Azure Pipelines YAML file.
- Select the branch (
main) and path/.azuredevops/pipelines/playwright-tests.yml. - Review the YAML preview, then select Run to save and queue the first run.
Exercise 3: Push a Change
Make a small modification to verify the pipeline triggers correctly. Add a console.log statement to any test:
test('navigate to Ontario.ca search page', async ({ page }) => {
console.log('CI pipeline verification');
await page.goto('/search?query=driver+licence');
await expect(page).toHaveTitle(/ontario/i);
});
Commit and push from your work-item feature branch. Replace 1234 with your User Story or Bug ID, linked to a Feature and Epic, then open a PR targeting main:
git add playwright-tests/tests/ontario-search.spec.ts
git commit -m "test: verify parallel CI suites AB#1234"
git push -u origin HEAD
Exercise 4: Watch the Pipeline
- Open your project in Azure DevOps and select Pipelines.
- Find the run triggered by your PR (with the required trigger or branch policy).
- Check both Functional and Accessibility matrix jobs and their logs.
The pipeline progresses through Node.js setup, test execution, test results publishing, and artifact upload. Each step shows its own log output.
Exercise 5: View Results
After the pipeline completes:
- Check the overall status: green checkmark (passed) or red X (failed).
- Select the Tests tab to see pass/fail counts, durations, and failure details sourced from the JUnit report.
- Select Artifacts and find both suites’ outputs:
| Suite | HTML report | JUnit, screenshots, and traces |
|---|---|---|
| Functional | playwright-report-functional | test-results-functional |
| Accessibility | playwright-report-accessibility | test-results-accessibility |
Open Test Plans > Plan 3201 > Execute and inspect each static suite. Confirm the nine functional and three accessibility points have the same outcomes as the build-linked runs, with populated last-run and result links.
Exercise 6: View HTML Report
- Download and extract one of the HTML report artifacts.
- From
playwright-tests, runnpx playwright show-report <extracted-report-directory>. - Explore the interactive report: test names, durations, pass/fail status, and screenshots for every test (enabled by
PLAYWRIGHT_SCREENSHOT=onin the pipeline).
These reports match local runs with npm run test:functional and npm run test:accessibility. Each job’s report contains only its own suite.
Exercise 7: Discussion
Consider these pipeline strategies with your team:
- Branch policy: Add a build validation branch policy on
mainthat requires this pipeline to pass before a pull request can be completed. This prevents regressions from reaching the main branch. - Nightly schedule: Add a
schedulestrigger (cron: '0 2 * * *') to catch issues from external dependencies or site changes overnight. - Environment matrix: Run tests across multiple browsers (Chromium, Firefox, WebKit) using a pipeline matrix strategy to verify cross-browser compatibility.
Verification Checkpoint
Both matrix jobs finish, the Tests tab contains separate suite runs, and all four artifacts are available when tests execute. Diagnose failures from the live site using the corresponding suite’s evidence; do not assume all scans will pass.
The functional suite includes intentional @failure-demo tests for practicing failure investigation. These can make the functional job red even when normal scenarios pass; the accessibility job should still complete independently.
Summary
CI/CD pipelines ensure tests run consistently on every code change without manual intervention. The pipeline automates browser installation, test execution, and report generation in a clean environment, catching regressions before they reach production.
Next Steps
Continue with Lab 05: Accessibility Testing to explore the axe scans, diagnose violations, and practice manual checks. This optional 20-minute extension follows the one-hour core workshop.