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 caching and early-exit strategies
- 🔒 Type-safe - Full type annotations with strict type checking
- 🧪 Well-tested - 144 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 |
|---|---|---|---|
get_by_* |
Single element | ❌ Raises error | ❌ Raises error |
query_by_* |
Element or None | ✅ Returns None | ❌ Raises error |
get_all_by_* |
List of elements | ❌ Raises error | ✅ Returns all |
query_all_by_* |
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 conditionals - PEP 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 highly optimized for speed with multiple performance strategies:
Optimization Techniques
- Two-level caching - Element list and role computation caching
- 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) instead of O(n) for class queries
Benchmark Results
Measured on December 10, 2024 - Apple M-series CPU, Python 3.14
Test Suite Performance:
- 154 tests complete in 0.08 seconds ⚡
Query Performance (200-element DOM, 100 iterations per query):
| Query Type | Without Caching | With Caching | Speedup |
|---|---|---|---|
| Role queries | 4.3μs | 1.8μs | 2.4x faster |
| Text queries | 13.6μs | 11.2μs | 1.2x faster |
| Class queries | 3.2μs | 0.7μs | 4.3x faster |
| Tag queries | 3.5μs | 3.1μs | 1.1x faster |
| Average | 5.8μs | 3.7μs | 1.55x faster |
Cache Efficiency:
- Element list cache: 99.8% hit rate
- Role cache: 99.5% hit rate
Run benchmarks yourself:
just benchmark # General performance
just benchmark-cache # Caching comparison
Performance Tips
- Reuse containers - Query the same DOM multiple times to benefit from caching
- Use appropriate queries -
query_all_*gets full caching benefits - Let caching work - Caches auto-clear between pytest tests
See CACHING_IMPLEMENTATION.md for detailed performance analysis.
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
Metadata
Release files for aria-testing 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aria_testing-0.1.2.tar.gz | 22.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aria_testing-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 51.0 kB
Release files / aria_testing-0.1.2.tar.gz
| Download URL | aria_testing-0.1.2.tar.gz |
|---|---|
| Size | 22.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
63714931ce5cb278b9808c7bb0a1d0a186ca96fa92d55a953655068e48910d2f
|
|
BLAKE2b-256 checksum How to use checksums |
5d718f86fe4fbdabffb5d7858a72782e41b81d627ccba8ab6c5acdf70906bf88
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.5
|
Release files / aria_testing-0.1.2-py3-none-any.whl
| Download URL | aria_testing-0.1.2-py3-none-any.whl |
|---|---|
| Size | 28.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1745351eb0c87f8d1b3acdcfa0cabe7c7ceee11be05d71a784cfb41a1fe870bd
|
|
BLAKE2b-256 checksum How to use checksums |
1f7a9957519dfff1e7d7d7a2b71ef1988984cb97f9ec02a66d5bed0772afdb15
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.5
|