Skip to main content

Accessibility-focused DOM testing library for tdom

Project description

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 exists
  • get_all_by_*: When multiple elements MUST exist
  • query_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

📚 See full documentation →

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 | Y unions, 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

  1. Reuse containers - Query the same DOM multiple times to benefit from caching
  2. Use appropriate queries - query_all_* gets full caching benefits
  3. 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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aria_testing-0.1.2.tar.gz (22.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aria_testing-0.1.2-py3-none-any.whl (28.7 kB view details)

Uploaded Python 3

File details

Details for the file aria_testing-0.1.2.tar.gz.

File metadata

  • Download URL: aria_testing-0.1.2.tar.gz
  • Upload date:
  • Size: 22.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.5

File hashes

Hashes for aria_testing-0.1.2.tar.gz
Algorithm Hash digest
SHA256 63714931ce5cb278b9808c7bb0a1d0a186ca96fa92d55a953655068e48910d2f
MD5 82343fdc74de3d1a450c81f39f4a4f6e
BLAKE2b-256 5d718f86fe4fbdabffb5d7858a72782e41b81d627ccba8ab6c5acdf70906bf88

See more details on using hashes here.

File details

Details for the file aria_testing-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for aria_testing-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 1745351eb0c87f8d1b3acdcfa0cabe7c7ceee11be05d71a784cfb41a1fe870bd
MD5 1c68543f99bda4e8206bc6ba6bf264a0
BLAKE2b-256 1f7a9957519dfff1e7d7d7a2b71ef1988984cb97f9ec02a66d5bed0772afdb15

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page