# Pytest Marks

Django-specific pytest marks for test configuration and behavior control. These marks provide fine-grained control over database access, URL configuration, and template error handling.

## Capabilities

### Django Database Mark

Control database access and transaction behavior for individual tests.

```python { .api }
@pytest.mark.django_db(
    transaction: bool = False,
    reset_sequences: bool = False,
    databases: Optional[Union[Literal["__all__"], Iterable[str]]] = None,
    serialized_rollback: bool = False,
    available_apps: Optional[List[str]] = None
):
    """
    Enable database access for test with configurable behavior.
    
    Controls how the test interacts with the database, including
    transaction handling, sequence management, and database selection.
    
    Args:
        transaction: Use transactional database (allows testing transactions)
        reset_sequences: Reset database sequences after test
        databases: Database aliases to use ("__all__" or list of names)
        serialized_rollback: Use serialized rollback instead of transactions
        available_apps: Limit Django apps available during test
    """
```

Usage examples:

```python
# Basic database access
@pytest.mark.django_db
def test_model_creation():
    from myapp.models import MyModel
    obj = MyModel.objects.create(name="test")
    assert obj.pk is not None

# Transactional testing
@pytest.mark.django_db(transaction=True)
def test_transaction_behavior():
    from django.db import transaction
    from myapp.models import MyModel
    
    with transaction.atomic():
        MyModel.objects.create(name="test1")
        # Test transaction rollback, commit behavior, etc.

# Multiple databases
@pytest.mark.django_db(databases=["default", "users"])
def test_multiple_databases():
    # Test has access to both default and users databases
    pass

# All databases
@pytest.mark.django_db(databases="__all__")
def test_all_databases():
    # Test has access to all configured databases
    pass

# Reset sequences for explicit PKs
@pytest.mark.django_db(reset_sequences=True)
def test_with_explicit_pk():
    from myapp.models import MyModel
    MyModel.objects.create(id=100, name="test")
    # Sequences reset after test

# Serialized rollback
@pytest.mark.django_db(serialized_rollback=True)
def test_with_serialized_rollback():
    # Database state preserved via serialization
    pass

# Limited app availability
@pytest.mark.django_db(available_apps=["myapp", "django.contrib.auth"])
def test_with_limited_apps():
    # Only specified apps available during test
    pass
```

### URL Configuration Mark

Override Django URL configuration for specific tests.

```python { .api }
@pytest.mark.urls(module: str):
    """
    Override ROOT_URLCONF setting for test.
    
    Temporarily changes Django's URL configuration to use
    a different URLconf module for the test. Useful for
    testing with custom URL patterns or isolated routing.
    
    Args:
        module: Python module path containing URL configuration
    """
```

Usage examples:

```python
# Use custom URL configuration
@pytest.mark.urls("myapp.test_urls")
def test_custom_urls(client):
    # Test uses URL patterns from myapp.test_urls
    response = client.get("/test-url/")
    assert response.status_code == 200

# Test with minimal URLs
@pytest.mark.urls("tests.minimal_urls")
def test_minimal_routing(client):
    # Test with only essential URL patterns
    response = client.get("/health/")
    assert response.status_code == 200

# Multiple tests with same URL config
pytestmark = pytest.mark.urls("myapp.api_urls")

def test_api_endpoint_1(client):
    # Uses myapp.api_urls
    pass

def test_api_endpoint_2(client):
    # Also uses myapp.api_urls
    pass
```

### Template Error Ignoring Mark

Ignore Django template variable errors during testing.

```python { .api }
@pytest.mark.ignore_template_errors():
    """
    Ignore invalid template variable errors during test.
    
    Suppresses Django template errors for invalid/undefined
    variables. Useful when testing with incomplete template
    contexts or when template errors are not relevant to test.
    """
```

Usage examples:

```python
# Ignore template errors for test
@pytest.mark.ignore_template_errors
def test_with_incomplete_context(client):
    # Template may reference undefined variables
    response = client.get("/page-with-missing-vars/")
    assert response.status_code == 200
    # No template errors raised

# Test template rendering with missing context
@pytest.mark.ignore_template_errors
def test_template_resilience():
    from django.template import Template, Context
    
    template = Template("{{ missing_var }} {{ also_missing }}")
    result = template.render(Context({}))
    # No errors for missing variables
    assert result == " "
```

### Mark Combinations

Combine multiple marks for complex test scenarios.

```python
# Multiple marks on single test
@pytest.mark.django_db(transaction=True)
@pytest.mark.urls("myapp.transaction_urls")
@pytest.mark.ignore_template_errors
def test_complex_scenario(client):
    # Test with transactions, custom URLs, and ignored template errors
    pass

# Class-level marks
@pytest.mark.django_db
@pytest.mark.urls("myapp.api_urls")
class TestAPI:
    def test_endpoint_1(self, client):
        # Inherits both marks
        pass
    
    def test_endpoint_2(self, client):
        # Also inherits both marks
        pass

# Module-level marks
pytestmark = [
    pytest.mark.django_db,
    pytest.mark.urls("myapp.test_urls")
]

def test_function_1():
    # Uses module-level marks
    pass
```

## Mark Configuration Types

```python { .api }
from typing import Optional, Union, List, Literal, Iterable

# Database configuration types
DatabaseSelection = Optional[Union[Literal["__all__"], Iterable[str]]]
AvailableApps = Optional[List[str]]
TransactionMode = bool
SequenceReset = bool
SerializedRollback = bool

# URL configuration types
UrlModule = str  # Python module path (e.g., "myapp.urls")

# Mark parameter types
class DjangoDbMarkParams:
    transaction: bool = False
    reset_sequences: bool = False
    databases: DatabaseSelection = None
    serialized_rollback: bool = False
    available_apps: AvailableApps = None

class UrlsMarkParams:
    module: str

class IgnoreTemplateErrorsMarkParams:
    pass  # No parameters

# Internal mark validation types
from pytest import Mark

def validate_django_db_mark(mark: Mark) -> tuple[bool, bool, DatabaseSelection, bool, AvailableApps]: ...
def validate_urls_mark(mark: Mark) -> List[str]: ...
```