CI/CD Integration
Integrate the Playwright C# Agentic Framework into your continuous integration and deployment pipelines. This guide covers setup for popular CI/CD platforms.
GitHub Actions
Basic Workflow
Create .github/workflows/tests.yml:
name: E2E Tests
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Restore dependencies
run: dotnet restore
- name: Build solution
run: dotnet build --no-restore
- name: Install Playwright browsers
run: |
dotnet build ./Tests.E2E/Tests.E2E.csproj
bash ./Tests.E2E/bin/Debug/net9.0/playwright.sh install --with-deps chromium
- name: Run tests
run: |
dotnet test ./Tests.E2E/Tests.E2E.csproj \
--logger:"junit;LogFileName=junit.xml" \
--results-directory ./allure-results \
--no-build
continue-on-error: true
- name: Generate Allure report
if: always()
run: |
npm install -g allure-commandline
allure generate --clean ./allure-results -o ./allure-report
- name: Upload Allure report
if: always()
uses: actions/upload-artifact@v4
with:
name: allure-report
path: ./allure-report
retention-days: 30
With Healing
Add healing step after test failures:
- name: Run tests
id: tests
run: |
dotnet test ./Tests.E2E/Tests.E2E.csproj \
--logger:"junit;LogFileName=junit.xml" \
--results-directory ./allure-results
continue-on-error: true
- name: Learn selectors (if tests passed)
if: steps.tests.outcome == 'success'
run: |
dotnet run --project ./Agents/Agents.csproj -- learn \
--test ./Tests.E2E/Tests.E2E.csproj \
--out ./agents/selectors.registry.json
- name: Heal tests (if tests failed)
if: steps.tests.outcome == 'failure'
run: |
dotnet run --project ./Agents/Agents.csproj -- heal \
--test ./Tests.E2E/Tests.E2E.csproj
continue-on-error: true
- name: Re-run healed tests
if: steps.tests.outcome == 'failure'
run: |
dotnet test ./Tests.E2E/Tests.E2E.csproj \
--logger:"junit;LogFileName=junit.xml" \
--results-directory ./allure-results
Matrix Strategy (Multiple Browsers)
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
browser: [chromium, firefox, webkit]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Install Playwright browsers
run: |
dotnet build ./Tests.E2E/Tests.E2E.csproj
bash ./Tests.E2E/bin/Debug/net9.0/playwright.sh install --with-deps ${{ matrix.browser }}
- name: Run tests
env:
BROWSER: ${{ matrix.browser }}
run: |
dotnet test ./Tests.E2E/Tests.E2E.csproj \
--logger:"junit;LogFileName=junit-${{ matrix.browser }}.xml" \
--results-directory ./allure-results
Azure DevOps
Pipeline YAML
Create azure-pipelines.yml:
trigger:
branches:
include:
- main
- develop
pool:
vmImage: 'ubuntu-latest'
variables:
dotnetVersion: '9.0.x'
stages:
- stage: Test
jobs:
- job: E2ETests
steps:
- task: UseDotNet@2
displayName: 'Use .NET SDK'
inputs:
version: '$(dotnetVersion)'
- task: DotNetCoreCLI@2
displayName: 'Restore dependencies'
inputs:
command: 'restore'
- task: DotNetCoreCLI@2
displayName: 'Build solution'
inputs:
command: 'build'
- script: |
dotnet build ./Tests.E2E/Tests.E2E.csproj
bash ./Tests.E2E/bin/Debug/net9.0/playwright.sh install --with-deps chromium
displayName: 'Install Playwright browsers'
- task: DotNetCoreCLI@2
displayName: 'Run tests'
inputs:
command: 'test'
projects: '**/Tests.E2E.csproj'
arguments: '--logger:"junit;LogFileName=junit.xml" --results-directory ./allure-results'
continueOnError: true
- script: |
npm install -g allure-commandline
allure generate --clean ./allure-results -o ./allure-report
displayName: 'Generate Allure report'
- task: PublishTestResults@2
displayName: 'Publish test results'
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: '**/junit.xml'
condition: always()
- task: PublishBuildArtifacts@1
displayName: 'Publish Allure report'
inputs:
pathToPublish: './allure-report'
artifactName: 'allure-report'
condition: always()
Jenkins
Jenkinsfile
Create Jenkinsfile:
pipeline {
agent any
tools {
dotnet 'dotnet-9.0'
}
environment {
DOTNET_VERSION = '9.0.x'
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Restore') {
steps {
sh 'dotnet restore'
}
}
stage('Build') {
steps {
sh 'dotnet build --no-restore'
}
}
stage('Install Playwright') {
steps {
sh '''
dotnet build ./Tests.E2E/Tests.E2E.csproj
bash ./Tests.E2E/bin/Debug/net9.0/playwright.sh install --with-deps chromium
'''
}
}
stage('Test') {
steps {
sh '''
dotnet test ./Tests.E2E/Tests.E2E.csproj \
--logger:"junit;LogFileName=junit.xml" \
--results-directory ./allure-results
'''
}
}
stage('Report') {
steps {
sh 'allure generate --clean ./allure-results -o ./allure-report'
}
}
}
post {
always {
allure([
includeProperties: false,
jdk: '',
properties: [],
reportBuildPolicy: 'ALWAYS',
results: [[path: 'allure-results']]
])
archiveArtifacts artifacts: 'allure-report/**', fingerprint: true
}
}
}
GitLab CI
.gitlab-ci.yml
image: mcr.microsoft.com/dotnet/sdk:9.0
variables:
DOTNET_VERSION: "9.0.x"
stages:
- test
e2e-tests:
stage: test
before_script:
- dotnet restore
- dotnet build
- dotnet build ./Tests.E2E/Tests.E2E.csproj
- bash ./Tests.E2E/bin/Debug/net9.0/playwright.sh install --with-deps chromium
script:
- dotnet test ./Tests.E2E/Tests.E2E.csproj
--logger:"junit;LogFileName=junit.xml"
--results-directory ./allure-results
artifacts:
when: always
paths:
- allure-results/
- allure-report/
reports:
junit: allure-results/junit.xml
expire_in: 30 days
after_script:
- npm install -g allure-commandline || true
- allure generate --clean ./allure-results -o ./allure-report || true
CircleCI
.circleci/config.yml
version: 2.1
jobs:
test:
docker:
- image: mcr.microsoft.com/dotnet/sdk:9.0
steps:
- checkout
- run:
name: Restore dependencies
command: dotnet restore
- run:
name: Build solution
command: dotnet build
- run:
name: Install Playwright
command: |
dotnet build ./Tests.E2E/Tests.E2E.csproj
bash ./Tests.E2E/bin/Debug/net9.0/playwright.sh install --with-deps chromium
- run:
name: Run tests
command: |
dotnet test ./Tests.E2E/Tests.E2E.csproj \
--logger:"junit;LogFileName=junit.xml" \
--results-directory ./allure-results
- store_test_results:
path: ./allure-results
- store_artifacts:
path: ./allure-results
destination: test-results
workflows:
version: 2
test:
jobs:
- test
Environment Variables
Secure Configuration
Store sensitive values as secrets in your CI/CD platform:
GitHub Actions:
env:
BASE_URL: ${{ secrets.BASE_URL }}
USER_EMAIL: ${{ secrets.USER_EMAIL }}
USER_PASSWORD: ${{ secrets.USER_PASSWORD }}
Azure DevOps:
variables:
- group: 'test-credentials'
Jenkins:
environment {
BASE_URL = credentials('base-url')
USER_EMAIL = credentials('user-email')
USER_PASSWORD = credentials('user-password')
}
Best Practices
1. Cache Dependencies
GitHub Actions:
- name: Cache .NET packages
uses: actions/cache@v3
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
2. Fail Fast on Critical Tests
- name: Run critical tests first
run: |
dotnet test ./Tests.E2E/Tests.E2E.csproj \
--filter "FullyQualifiedName~@critical"
- name: Run full suite
if: success()
run: |
dotnet test ./Tests.E2E/Tests.E2E.csproj
3. Retry Flaky Tests
- name: Run tests with retry
run: |
dotnet test ./Tests.E2E/Tests.E2E.csproj \
-- NUnit.RetryFailedTests=2
4. Notify on Failure
- name: Notify on failure
if: failure()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: 'Tests failed!'
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
Troubleshooting
Playwright Browsers Not Found
Ensure browsers are installed in the CI environment:
# Add to your pipeline
dotnet build ./Tests.E2E/Tests.E2E.csproj
bash ./Tests.E2E/bin/Debug/net9.0/playwright.sh install --with-deps chromium
Timeout Issues
Increase timeouts in CI:
env:
PW_TIMEOUT_MS: 10000 # 10 seconds for CI
Memory Issues
Limit parallel workers:
dotnet test ./Tests.E2E/Tests.E2E.csproj -m:2 # Use 2 workers instead of 4