aria-testing¶
Accessibility-focused DOM testing library for tdom, built with modern Python 3.14+.
📚 Full Documentation | 📦 * PyPI Package* | 🐙 * GitHub Repository*
Overview¶
aria-testing is a Python DOM testing library that provides accessibility-focused query functions for tdom. It follows
the DOM Testing Library philosophy: “The more your tests resemble the way your software is used, the more confidence
they can give you.”
Features¶
✨ Modern Python 3.14+ - Uses structural pattern matching, PEP 695 generics, and modern type hints
🎯 Accessibility-first - Query by role, label text, and semantic attributes
⚡ High performance - Optimized traversal with early-exit strategies
🔒 Type-safe - Full type annotations with strict type checking
🧪 Well-tested - 179 tests, 100% passing, comprehensive coverage
Installation¶
uv add --dev aria-testing
Quick Start¶
from tdom.processor import html
from aria_testing import get_by_role, get_by_text, get_by_label_text
# Create a tdom structure
document = html(t"""<div>
<h1>Welcome</h1>
<nav>
<a href="/home">Home</a>
</nav>
<form>
<label>Email
<input type="email" />
</label>
<button>Submit</button>
</form>
</div>""")
# Find elements using accessibility patterns
heading = get_by_role(document, "heading", level=1)
nav = get_by_role(document, "navigation")
link = get_by_role(document, "link", name="Home")
email_input = get_by_label_text(document, "Email")
button = get_by_text(document, "Submit")
Query Types¶
Queries are prioritized by accessibility best practices:
1. By Role ⭐ (Most Recommended)¶
Find elements by their ARIA role - mirrors how screen readers interact with your app.
button = get_by_role(document, "button")
heading = get_by_role(document, "heading", level=1)
link = get_by_role(document, "link", name="Home")
2. By Label Text ⭐¶
Find form elements by their associated label - how users identify form fields.
username = get_by_label_text(document, "Username")
email = get_by_label_text(document, "Email Address")
3. By Text¶
Find elements by their text content.
button = get_by_text(document, "Click me")
heading = get_by_text(document, "Welcome")
4. By Test ID¶
Find elements by data-testid attribute - useful when semantic queries aren’t possible.
component = get_by_test_id(document, "user-menu")
5. By Tag Name¶
Find elements by HTML tag name - use sparingly, prefer semantic queries.
all_links = get_all_by_tag_name(document, "a")
6. By ID & By Class¶
Find elements by HTML attributes - available but less recommended.
element = get_by_id(document, "main-content")
buttons = get_all_by_class(document, "btn-primary")
Query Variants¶
Each query type comes in four variants for different use cases:
Variant |
Returns |
Not Found |
Multiple Found |
|---|---|---|---|
|
Single element |
❌ Raises error |
❌ Raises error |
|
Element or None |
✅ Returns None |
❌ Raises error |
|
List of elements |
❌ Raises error |
✅ Returns all |
|
List (possibly empty) |
✅ Returns |
✅ Returns all |
When to Use Each¶
get_by_*: When element MUST exist and be unique (most common)query_by_*: When checking if element existsget_all_by_*: When multiple elements MUST existquery_all_by_*: When finding zero or more elements
Assertion Helpers¶
Frozen dataclass-based assertion helpers for deferred execution in dynamic systems. Create assertions up front, apply them later when the DOM is available.
from aria_testing import GetByRole, GetAllByRole
# Define assertion early (no DOM needed yet)
assert_button = GetByRole(role="button").text_content("Save")
# Apply later when container becomes available
def verify_component(container):
assert_button(container) # Raises AssertionError if fails
Use Cases:
Component testing frameworks that render components dynamically
Story-based testing where assertions are defined separately from execution
Test fixtures that verify DOM structure after setup
Reusable assertion sets applied across multiple test scenarios
Key Features:
Immutable frozen dataclasses
Fluent API:
.not_(),.text_content(),.with_attribute()List operations:
.count(),.nth()Type-safe with full IDE support
Modern Python Features¶
Built with cutting-edge Python 3.14+ features:
Structural pattern matching (
match/case) for clean conditionalsPEP 695 generic functions for type-safe query factories
Modern type hints (
X | Yunions, built-in generics)Keyword-only arguments for clear, readable APIs
Walrus operator (
:=) for concise, performant code
Performance¶
aria-testing is optimized for speed with multiple performance strategies:
Query Performance (200-element DOM on Python 3.14t free-threaded):
Average query time: 3.99μs ⚡ (21% faster than regular Python!)
Role queries: 2.85μs
Text queries: 12.18μs
Class/tag queries: 2.34μs
Test Suite:
179 tests complete in 0.78 seconds (parallel mode)
Average: 4.4ms per test
Free-Threading Advantage: Python 3.14t (no-GIL) is 21% faster than regular Python 3.14, even in single-threaded code, due to reduced GIL overhead and optimized reference counting for interned strings.
Key Optimizations¶
Early-exit strategies - Stops searching after finding matches
Iterative traversal - Non-recursive DOM traversal for large trees
String interning - Fast identity-based comparisons for common roles
Set-based class matching - O(1) class lookups
Free-threading compatible - Full Python 3.14+ free-threading support (PEP 703)
Thread Safety & Concurrency¶
aria-testing is fully thread-safe and designed for Python 3.14’s free-threaded (no-GIL) interpreter:
✅ No shared mutable state - All operations use function-local variables
✅ Immutable data structures - Module constants use MappingProxyType
✅ No locking required - Lock-free design for maximum performance
✅ Parallel test execution - Works with pytest-xdist and concurrent.futures
The library was designed from the ground up for concurrent execution. Previous caching mechanisms were intentionally removed to ensure race-condition-free operation in multi-threaded environments.
Run benchmarks yourself:
just benchmark # Performance benchmark
just profile-queries # Detailed profiling
Requirements¶
Python 3.14+
tdom
Documentation¶
📚 Read the full documentation on GitHub Pages →
The documentation includes:
Complete API reference for all query functions
Detailed guides on accessibility testing patterns
Performance optimization techniques
Type safety and modern Python features
Advanced usage examples and best practices
License¶
MIT
Documentation Guide¶
This documentation is organized into focused sections for different needs:
Getting Started¶
Start here if you’re new to aria-testing:
README (above) - Quick start and overview
Query Reference - All query types and their usage
Assertion Helpers - Deferred execution for dynamic testing systems
Practical Guides¶
Learn by example:
Examples - Real-world testing patterns and use cases
Best Practices - Guidelines for writing effective, accessible tests
Reference¶
Complete API documentation:
API Reference - Full function signatures, parameters, and return types
Advanced Topics¶
Deep dives for advanced users and contributors:
Architecture - System design, query factory pattern, role mapping
Benchmarks - Performance measurements, optimization strategies
Contributing - Development setup, code standards, how to contribute
Quick Links¶
Philosophy¶
aria-testing follows the DOM Testing Library philosophy:
“The more your tests resemble the way your software is used, the more confidence they can give you.”
This means:
✅ Query by role (how screen readers see your app)
✅ Query by label text (how users identify form fields)
✅ Query by text (what users see)
❌ Avoid querying by test IDs, CSS classes, or implementation details
Project Info¶
License: MIT
Python: 3.14+
Dependencies: tdom