0
# Query Testing
1
2
Fixtures for asserting and controlling database query counts during testing. These fixtures help identify performance issues and ensure optimal database usage patterns.
3
4
## Capabilities
5
6
### Exact Query Count Assertion
7
8
Assert the exact number of database queries executed during test operations.
9
10
```python { .api }
11
def django_assert_num_queries(pytestconfig: pytest.Config) -> DjangoAssertNumQueries:
12
"""
13
Fixture for asserting exact database query counts.
14
15
Returns a context manager that captures and asserts the exact number
16
of database queries executed within its context. Useful for performance
17
testing and ensuring optimal query patterns.
18
19
Returns:
20
DjangoAssertNumQueries: Query count assertion context manager
21
"""
22
23
class DjangoAssertNumQueries:
24
"""Context manager for asserting exact database query counts."""
25
26
def __call__(
27
self,
28
num: int,
29
connection: Any | None = None,
30
info: str | None = None,
31
*,
32
using: str | None = None,
33
) -> ContextManager[None]:
34
"""
35
Create context manager for exact/maximum query count assertion.
36
37
Args:
38
num: Expected exact/maximum number of database queries
39
connection: Database connection to monitor (overrides using)
40
info: Additional info to include in assertion error messages
41
using: Database alias to monitor (default: "default")
42
43
Returns:
44
ContextManager: Context manager that asserts query count
45
"""
46
```
47
48
Usage example:
49
```python
50
def test_query_count(django_assert_num_queries):
51
from myapp.models import MyModel
52
53
# Assert exactly 1 query (the INSERT)
54
with django_assert_num_queries(1):
55
MyModel.objects.create(name="test")
56
57
# Assert exactly 2 queries (SELECT and UPDATE)
58
with django_assert_num_queries(2):
59
obj = MyModel.objects.get(name="test")
60
obj.name = "updated"
61
obj.save()
62
```
63
64
### Maximum Query Count Assertion
65
66
Assert the maximum number of database queries executed during test operations.
67
68
```python { .api }
69
def django_assert_max_num_queries(pytestconfig: pytest.Config) -> DjangoAssertNumQueries:
70
"""
71
Fixture for asserting maximum database query counts.
72
73
Returns a context manager that captures database queries and asserts
74
that the count does not exceed the specified maximum. Useful for
75
performance regression testing.
76
77
Returns:
78
DjangoAssertNumQueries: Maximum query count assertion context manager
79
"""
80
81
```
82
83
Usage example:
84
```python
85
def test_max_query_count(django_assert_max_num_queries):
86
from myapp.models import MyModel, RelatedModel
87
88
# Ensure operation uses at most 3 queries
89
with django_assert_max_num_queries(3):
90
# This should be optimized to avoid N+1 queries
91
for obj in MyModel.objects.select_related('related'):
92
print(obj.related.name)
93
94
# Performance regression test
95
with django_assert_max_num_queries(5):
96
# Complex operation that should stay under 5 queries
97
result = MyModel.objects.filter(active=True).prefetch_related('tags')
98
for obj in result:
99
obj.tags.all()
100
```
101
102
## Query Testing Types
103
104
```python { .api }
105
from typing import ContextManager, List, Optional
106
from django.db import connection
107
108
# Query assertion context managers
109
class DjangoAssertNumQueries:
110
"""Context manager for exact query count assertions."""
111
112
def __call__(self, num: int, using: str = "default") -> ContextManager[None]:
113
"""
114
Assert exact number of queries.
115
116
Args:
117
num: Expected exact number of queries
118
using: Database alias to monitor (default: "default")
119
120
Returns:
121
ContextManager that captures and asserts query count
122
"""
123
124
125
# Query information types
126
class QueryInfo:
127
"""Information about executed database query."""
128
sql: str
129
time: float
130
131
# Database connection query capture
132
class ConnectionQueryCapture:
133
"""Capture queries from database connection."""
134
queries: List[QueryInfo]
135
initial_queries: int
136
final_queries: int
137
executed_queries: List[QueryInfo]
138
```