# Best Practices
Guidelines for writing effective, maintainable tests with aria-testing.
## Query Priority
Use queries in this order of preference:
### 1. **By Role** ⭐⭐⭐ (Highest Priority)
Find elements by their ARIA role - mirrors how screen readers interact with your app.
```python
button = get_by_role(document, "button")
heading = get_by_role(document, "heading", level=1)
link = get_by_role(document, "link", name="Home")
```
**Why prioritize role queries?**
- Tests how users with assistive technology experience your app
- Encourages semantic HTML
- Resilient to implementation changes (CSS classes, IDs, structure)
- Forces you to think about accessibility
### 2. **By Label Text** ⭐⭐⭐
Find form elements by their associated label - how users identify form fields.
```python
username = get_by_label_text(document, "Username")
email = get_by_label_text(document, "Email Address")
```
**Why prioritize label queries?**
- Matches how users identify form inputs
- Ensures labels are properly associated
- Tests accessibility of forms
- Resilient to implementation changes
### 3. **By Text** ⭐⭐
Find elements by their text content.
```python
button = get_by_text(document, "Click me")
heading = get_by_text(document, "Welcome")
```
**Why lower priority than role?**
- Text can change more frequently than roles
- Doesn't verify semantic structure
- Less specific than role + name combination
**When to use:**
- Content verification (headings, paragraphs)
- When role queries aren't specific enough
- Testing displayed text
### 4. **By Test ID** ⭐
Find elements by `data-testid` attribute - escape hatch when semantic queries fail.
```python
component = get_by_test_id(document, "user-menu")
```
**Why lowest priority?**
- Implementation detail, not user-facing
- Adds attributes solely for testing
- Doesn't encourage accessibility
- Doesn't match how users interact
**When to use:**
- Complex components without clear roles
- Dynamic content with changing text
- When semantic queries are impractical
- Testing implementation-specific behavior
### 5. **By Tag Name, ID, Class**
Direct attribute queries - use sparingly.
```python
# Tag name: useful for non-semantic elements
favicon = get_by_tag_name(document, "link", attrs={"rel": "icon"})
# ID: when element has unique ID
element = get_by_id(document, "main-content")
# Class: when other queries fail
buttons = get_all_by_class(document, "btn-primary")
```
**When to use:**
- Non-semantic HTML elements (``, ``, `