Python Accessibility Testing — Core Concepts

Accessibility testing verifies that web applications work for people with disabilities — those using screen readers, keyboard-only navigation, voice control, or high-contrast displays. In many jurisdictions, accessibility compliance is a legal requirement (ADA in the US, EAA in Europe).

What Gets Tested

Automated accessibility testing checks rules from WCAG (Web Content Accessibility Guidelines):

  • Images have alt text descriptions
  • Form fields have associated labels
  • Color contrast meets minimum ratios (4.5:1 for normal text)
  • Headings follow a logical hierarchy (h1 → h2 → h3)
  • Interactive elements are keyboard-reachable
  • ARIA attributes are used correctly
  • Focus order is logical
  • Language is declared on the page

The axe-core Engine

Most Python accessibility testing tools wrap axe-core, an open-source JavaScript engine maintained by Deque Systems. It runs in the browser and checks the live DOM against hundreds of WCAG rules.

Testing with Playwright

# pip install playwright axe-playwright-python
from playwright.sync_api import sync_playwright
from axe_playwright_python.sync_playwright import Axe

def test_homepage_accessibility():
    with sync_playwright() as p:
        browser = p.chromium.launch()
        page = browser.new_page()
        page.goto("https://yourapp.com")

        axe = Axe()
        results = axe.run(page)

        violations = results.response["violations"]
        assert len(violations) == 0, format_violations(violations)

        browser.close()

def format_violations(violations):
    lines = []
    for v in violations:
        lines.append(f"\n{v['impact'].upper()}: {v['description']}")
        for node in v["nodes"][:3]:
            lines.append(f"  → {node['html'][:100]}")
    return "\n".join(lines)

Testing with Selenium

# pip install selenium axe-selenium-python
from selenium import webdriver
from axe_selenium_python import Axe

def test_login_page_accessibility():
    driver = webdriver.Chrome()
    driver.get("https://yourapp.com/login")

    axe = Axe(driver)
    axe.inject()
    results = axe.run()

    violations = results["violations"]
    assert len(violations) == 0, axe.report(results["violations"])

    driver.quit()

Common Violations and Fixes

ViolationImpactFix
Missing alt text on imagesCriticalAdd alt="description"
Low color contrastSeriousIncrease contrast ratio to ≥4.5:1
Form input without labelCriticalAdd <label for="...">
Empty button textCriticalAdd visible text or aria-label
Missing page languageSeriousAdd <html lang="en">
Duplicate ID attributesModerateMake IDs unique

Integrating Into CI/CD

# GitHub Actions example
- name: Accessibility tests
  run: |
    pip install playwright axe-playwright-python pytest
    playwright install chromium
    pytest tests/accessibility/ --tb=short

Run accessibility tests alongside your regular test suite. Treat critical and serious violations as test failures.

What Automation Can’t Catch

Automated tools catch about 30-40% of accessibility issues. They cannot verify:

  • Whether alt text is actually meaningful (“photo” vs. “Team celebrating product launch”)
  • Whether the reading order makes sense
  • Whether custom widgets are usable with a screen reader
  • Whether the user experience is genuinely good for disabled users

Manual testing with screen readers (NVDA, VoiceOver, JAWS) and keyboard-only navigation remains essential.

Common Misconception

“If it passes automated accessibility tests, it’s accessible.” Automated tools catch structural issues — missing labels, low contrast, broken ARIA. They can’t judge whether your app is actually usable with assistive technology. Think of automated tests as catching the obvious bugs; manual testing with real assistive tools catches the rest.

The one thing to remember: Python + axe-core catches the most common accessibility violations automatically in CI — but plan for manual screen reader testing to cover the 60% that automation misses.

pythonaccessibilitya11ytestingWCAGautomation

See Also

  • Python Headless Browser Testing How Python tests websites using invisible browsers that click buttons and fill forms without anyone watching — explained for beginners.
  • Ci Cd Why big apps can ship updates every day without turning your phone into a glitchy mess — CI/CD is the behind-the-scenes quality gate and delivery truck.
  • Containerization Why does software that works on your computer break on everyone else's? Containers fix that — and they're why Netflix can deploy 100 updates a day without the site going down.
  • Python 310 New Features Python 3.10 gave programmers a shape-sorting machine, friendlier error messages, and cleaner ways to say 'this or that' in type hints.
  • Python 311 New Features Python 3.11 made everything faster, error messages smarter, and let you catch several mistakes at once instead of stopping at the first one.