How to Add Accessibility Testing to Your CI/CD Pipeline
TABLE OF CONTENTS
- What You'll Learn
- Prerequisites
- Step 1: Choose Your Testing Approach
- Step 2: Set Up GitHub Actions (Bouncer)
- Step 3: Set Up GitHub Actions (Open Source)
- Step 4: Configure Testing Scope
- Step 5: Handle Test Failures
- Step 6: Transition from Advisory to Blocking
- Step 7: Monitor and Improve
- Common Issues and Solutions
- Next Steps
- Frequently Asked Questions
- Related Resources
Adding accessibility testing to your CI/CD pipeline prevents WCAG violations from reaching production. This tutorial walks through implementation step by step—from choosing your testing approach to configuring GitHub Actions to handling failures effectively. Development teams using CI/CD accessibility integration catch issues when fixes cost minutes instead of thousands of dollars in lawsuit settlements.
The shift-left approach catches violations during development, before users encounter barriers or plaintiff attorneys document violations.
What You'll Learn
This tutorial covers everything needed for CI/CD accessibility integration.
- Choosing between testing approaches
- Setting up GitHub Actions workflows
- Configuring TestParty Bouncer
- Using open source alternatives
- Handling test failures effectively
- Transitioning from advisory to blocking mode
Prerequisites
Before starting, ensure you have:
- A GitHub repository with your web project
- Node.js installed (for build processes)
- Basic familiarity with GitHub Actions
- Repository admin access (for secrets and workflow configuration)
Step 1: Choose Your Testing Approach
Multiple approaches exist for CI/CD accessibility testing. Your choice depends on your needs and resources.
Option A: TestParty Bouncer (Recommended)
TestParty's Bouncer provides integrated CI/CD accessibility testing with expert remediation support.
Best for: Teams wanting complete accessibility coverage without building custom solutions.
Includes:
- GitHub-native integration with PR comments
- Expert context for violations (not just error codes)
- Connection to Spotlight production scanning
- Access to professional remediation
- <1% of customers sued track record
Option B: Open Source Tools
Tools like axe-core, Pa11y, and Lighthouse provide free accessibility testing.
Best for: Teams with accessibility expertise who can implement fixes internally.
Includes:
- Detection capability (70-80% of WCAG)
- Configurable rules and thresholds
- No subscription cost
Does not include:
- Remediation (your team fixes everything)
- Expert guidance
- Production monitoring integration
Decision Matrix
+---------------------------+-------------------+----------------------------+
| Need | Bouncer | Open Source |
+---------------------------+-------------------+----------------------------+
| Detection only | âś“ | âś“ |
+---------------------------+-------------------+----------------------------+
| Expert remediation | âś“ | âś— |
+---------------------------+-------------------+----------------------------+
| PR integration | âś“ | Requires setup |
+---------------------------+-------------------+----------------------------+
| Production monitoring | âś“ (Spotlight) | Separate tool |
+---------------------------+-------------------+----------------------------+
| Ongoing cost | Subscription | Free (+ internal time) |
+---------------------------+-------------------+----------------------------+Step 2: Set Up GitHub Actions (Bouncer)
If using TestParty Bouncer, follow these steps.
2A: Connect Your Repository
- Sign in to TestParty at testparty.ai
- Navigate to Integrations → GitHub
- Authorize TestParty's GitHub App
- Select repositories to connect
This grants TestParty access to create PR comments and workflow integration.
2B: Generate API Key
- In TestParty dashboard, go to Settings → API
- Generate a new API key
- Copy the key (you won't see it again)
2C: Add Secret to GitHub
- In your GitHub repository, go to Settings → Secrets → Actions
- Click "New repository secret"
- Name: `TESTPARTYAPIKEY`
- Value: Paste your API key
- Click "Add secret"
2D: Create Workflow File
Create `.github/workflows/accessibility.yml`:
name: Accessibility Testing
on:
pull_request:
branches: [main, develop]
jobs:
bouncer:
name: TestParty Bouncer
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Start server
run: npm run start &
- name: Wait for server
run: npx wait-on http://localhost:3000
- name: Run Bouncer
uses: testparty/bouncer-action@v1
with:
api-key: ${{ secrets.TESTPARTY_API_KEY }}
url: http://localhost:30002E: Commit and Test
- Commit the workflow file to a new branch
- Open a pull request
- Watch the Bouncer check run
- Review results in PR comments
Step 3: Set Up GitHub Actions (Open Source)
If using open source tools, follow these steps.
3A: Install Testing Dependencies
Add axe-core and Playwright (for browser automation) to your project:
npm install --save-dev @axe-core/playwright playwright3B: Create Test File
Create `tests/accessibility.spec.js`:
const { test, expect } = require('@playwright/test');
const AxeBuilder = require('@axe-core/playwright').default;
test.describe('Accessibility', () => {
test('homepage has no violations', async ({ page }) => {
await page.goto('/');
const results = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
.analyze();
expect(results.violations).toEqual([]);
});
test('product page has no violations', async ({ page }) => {
await page.goto('/products/example');
const results = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
.analyze();
expect(results.violations).toEqual([]);
});
// Add tests for other critical pages
});3C: Add Test Script
In `package.json`, add:
{
"scripts": {
"test:a11y": "playwright test tests/accessibility.spec.js"
}
}3D: Create Workflow File
Create `.github/workflows/accessibility.yml`:
name: Accessibility Testing
on:
pull_request:
branches: [main, develop]
jobs:
accessibility:
name: Accessibility Checks
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install Playwright browsers
run: npx playwright install --with-deps chromium
- name: Build project
run: npm run build
- name: Start server
run: npm run start &
- name: Wait for server
run: npx wait-on http://localhost:3000
- name: Run accessibility tests
run: npm run test:a11y3E: Commit and Test
- Commit dependencies, test file, and workflow
- Open a pull request
- Watch the accessibility check run
- Review any failures in the Actions log
Step 4: Configure Testing Scope
Decide what pages to test in CI/CD.
Critical Path Testing
Test the most important user journeys rather than every page.
For e-commerce sites, critical paths typically include homepage, product listing page, product detail page, cart, checkout flow, account pages, and search results.
const criticalPaths = [
'/',
'/products',
'/products/example-product',
'/cart',
'/checkout',
'/account',
'/search?q=test'
];
criticalPaths.forEach(path => {
test(`${path} has no violations`, async ({ page }) => {
await page.goto(path);
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
});Component Testing
For faster feedback, test components in isolation.
test('Button component is accessible', async ({ page }) => {
// Render component in isolation
await page.goto('/storybook/button');
const results = await new AxeBuilder({ page })
.include('.button-component')
.analyze();
expect(results.violations).toEqual([]);
});Viewport Testing
Test multiple viewports to catch mobile-specific issues.
const viewports = [
{ width: 1280, height: 720, name: 'desktop' },
{ width: 768, height: 1024, name: 'tablet' },
{ width: 375, height: 667, name: 'mobile' }
];
viewports.forEach(viewport => {
test(`homepage accessible at ${viewport.name}`, async ({ page }) => {
await page.setViewportSize({
width: viewport.width,
height: viewport.height
});
await page.goto('/');
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
});Step 5: Handle Test Failures
Effective CI/CD accessibility requires clear failure handling.
Understanding Failure Output
When tests fail, you'll see output like:
Violations found:
- color-contrast (critical): 2 occurrences
Elements must have sufficient color contrast
Elements:
- #header-text (contrast ratio: 3.2:1, expected 4.5:1)
- .footer-link (contrast ratio: 2.8:1, expected 4.5:1)
- label (serious): 1 occurrence
Form elements must have labels
Elements:
- input#email-subscribeEach violation includes the rule violated, severity, number of occurrences, and specific elements.
Fixing Violations
For each violation, determine if it's a new issue introduced by the PR, an existing issue exposed by new tests, or a false positive (rare but possible).
New issues should be fixed before merge. Existing issues may be acceptable to document and address separately. False positives can be suppressed with rule configuration.
Suppressing False Positives
If you encounter false positives, suppress specific rules:
const results = await new AxeBuilder({ page })
.disableRules(['specific-false-positive-rule'])
.analyze();Use suppression sparingly—most "false positives" are real issues worth fixing.
Step 6: Transition from Advisory to Blocking
Start in advisory mode during adoption, then transition to blocking.
Advisory Mode (Starting Point)
In advisory mode, tests run and report results but don't block merge.
jobs:
accessibility:
runs-on: ubuntu-latest
continue-on-error: true # Don't fail the workflow
steps:
- name: Run accessibility tests
run: npm run test:a11yUse advisory mode when:
- First adopting CI/CD accessibility
- Clearing backlog of existing violations
- Training team on accessibility requirements
Blocking Mode (Target State)
In blocking mode, accessibility failures prevent merge.
jobs:
accessibility:
runs-on: ubuntu-latest
# No continue-on-error, failures block merge
steps:
- name: Run accessibility tests
run: npm run test:a11yUse blocking mode when:
- Existing violations are cleared
- Team understands what triggers failures
- You're ready to maintain standards going forward
Transition Process
- Enable advisory mode and monitor for 2-4 weeks
- Track violations and address existing issues
- Train team on common violations and fixes
- Announce transition date
- Enable blocking mode
- Maintain standards going forward
Step 7: Monitor and Improve
CI/CD accessibility is ongoing, not one-time setup.
Track Trends
Monitor metrics over time: violations per PR (should decrease), false positive rate (should be low), fix time (should decrease as team learns), and rule coverage (should expand).
Expand Coverage
Start with critical paths, then expand to all public pages, authenticated user flows, admin interfaces, and error states.
Integrate with Production Monitoring
CI/CD catches issues during development. Production monitoring catches issues from content changes and edge cases CI/CD missed.
TestParty's Spotlight provides daily production scanning. Other tools require separate production monitoring setup.
Update Dependencies
Keep accessibility testing tools updated. New versions catch more issues and reduce false positives.
npm update @axe-core/playwright playwrightCommon Issues and Solutions
Troubleshooting common CI/CD accessibility problems.
Server Not Ready
Symptom: Tests fail with connection errors.
Solution: Ensure server is fully started before tests run.
- name: Start server
run: npm run start &
- name: Wait for server
run: npx wait-on http://localhost:3000 --timeout 60000Tests Too Slow
Symptom: CI/CD pipeline times out or is excessively slow.
Solution:
- Test fewer pages in CI/CD
- Run comprehensive tests nightly instead of per-PR
- Use component testing for fast feedback
Inconsistent Results
Symptom: Tests pass locally but fail in CI (or vice versa).
Solution:
- Ensure CI and local environments match
- Check for timing-dependent issues
- Use consistent browser versions
Too Many Violations
Symptom: First run shows hundreds of violations.
Solution:
- Start with advisory mode
- Prioritize critical violations
- Address violations in batches
- Consider TestParty for expert remediation help
Next Steps
After implementing CI/CD accessibility testing:
- Clear existing violations using TestParty remediation or internal resources
- Enable blocking mode once baseline is clean
- Add production monitoring with Spotlight or equivalent
- Schedule periodic manual audits for non-automatable criteria
- Train team on accessibility fundamentals
Frequently Asked Questions
How do I add accessibility testing to my CI/CD pipeline?
Add accessibility testing to CI/CD by creating a GitHub Actions workflow that runs automated checks on pull requests. Use TestParty Bouncer for integrated testing with expert support, or open source tools like axe-core with Playwright for detection-only testing. Configure the workflow to build your project, start a server, and run accessibility checks before allowing merge.
Should accessibility tests block PRs from merging?
Eventually, yes—blocking mode prevents regressions. Start with advisory mode during adoption to clear existing violations without blocking development. Transition to blocking mode once existing issues are addressed and the team understands accessibility requirements. Most teams transition within 2-4 weeks of initial setup.
What's the difference between Bouncer and axe-core?
Both provide automated accessibility detection. Axe-core is an open source library—you build the testing infrastructure and implement fixes yourself. TestParty Bouncer is an integrated solution including GitHub-native PR comments, expert remediation access, connection to production monitoring (Spotlight), and a zero-lawsuit customer track record. Bouncer is a complete solution; axe-core is a building block.
How many pages should CI/CD test?
Test critical user paths rather than every page—homepage, product pages, cart, checkout, and account flows for e-commerce. Component-level tests provide fast feedback. Reserve comprehensive full-site testing for nightly runs or production monitoring. Balance coverage against CI/CD execution time.
What percentage of violations can CI/CD testing catch?
CI/CD accessibility testing catches 70-80% of WCAG violations—the objective, measurable criteria. The remaining 20-30% requires human judgment (alt text quality, content clarity, cognitive accessibility). CI/CD testing is essential but not sufficient alone—combine with periodic manual audits for complete coverage.
How do I fix violations found in CI/CD?
For simple violations (missing alt text, color contrast), developers can fix directly. For complex violations or high volume, TestParty's expert remediation team creates source code fixes delivered via PRs. Open source tools provide detection only—all fixes require your team's implementation.
Related Resources
For more CI/CD accessibility information:
- CI/CD Accessibility Integration — Overview
- GitHub Accessibility CI/CD — GitHub-specific guide
- Automated Accessibility Testing — Testing fundamentals
- Best Accessibility Tool with CI/CD Integration — Tool comparison
Like all TestParty blog posts, this content was created through human-AI collaboration—what we call our cyborg approach. The information provided is for educational purposes only and reflects our research at the time of writing. We recommend doing your own due diligence and speaking directly with accessibility vendors to determine the best solution for your specific needs.
Stay informed
Accessibility insights delivered
straight to your inbox.


Automate the software work for accessibility compliance, end-to-end.
Empowering businesses with seamless digital accessibility solutions—simple, inclusive, effective.
Book a Demo