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
alttext 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
| Violation | Impact | Fix |
|---|---|---|
| Missing alt text on images | Critical | Add alt="description" |
| Low color contrast | Serious | Increase contrast ratio to ≥4.5:1 |
| Form input without label | Critical | Add <label for="..."> |
| Empty button text | Critical | Add visible text or aria-label |
| Missing page language | Serious | Add <html lang="en"> |
| Duplicate ID attributes | Moderate | Make 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.
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.