Skip to content

Commit 36a0f5d

Browse files
committed
Add fixture for asserting maximum number of database queries
1 parent 94cccb9 commit 36a0f5d

File tree

4 files changed

+64
-18
lines changed

4 files changed

+64
-18
lines changed

docs/helpers.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,24 @@ Example
239239
Item.objects.create('baz')
240240

241241

242+
``django_assert_max_num_queries``
243+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
244+
245+
This fixture allows to check for an expected maximum number of DB queries.
246+
It currently only supports the default database.
247+
248+
249+
Example
250+
"""""""
251+
252+
::
253+
254+
def test_max_queries(django_assert_max_num_queries):
255+
with django_assert_num_queries(3):
256+
Item.objects.create('foo')
257+
Item.objects.create('bar')
258+
259+
242260
``mailoutbox``
243261
~~~~~~~~~~~~~~~~~~~~~~~~~
244262

pytest_django/fixtures.py

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from __future__ import with_statement
44

55
import os
6+
from functools import partial
67

78
import pytest
89

@@ -18,7 +19,8 @@
1819
__all__ = ['django_db_setup', 'db', 'transactional_db', 'admin_user',
1920
'django_user_model', 'django_username_field',
2021
'client', 'admin_client', 'rf', 'settings', 'live_server',
21-
'_live_server_helper', 'django_assert_num_queries']
22+
'_live_server_helper', 'django_assert_num_queries',
23+
'django_assert_max_num_queries']
2224

2325

2426
@pytest.fixture(scope='session')
@@ -336,22 +338,33 @@ def _live_server_helper(request):
336338
getfixturevalue(request, 'transactional_db')
337339

338340

339-
@pytest.fixture(scope='function')
340-
def django_assert_num_queries(pytestconfig):
341+
@contextmanager
342+
def _assert_num_queries(config, num, exact=True):
341343
from django.db import connection
342344
from django.test.utils import CaptureQueriesContext
345+
verbose = config.getoption('verbose') > 0
346+
with CaptureQueriesContext(connection) as context:
347+
yield
348+
failed = num != len(context) if exact else num < len(context)
349+
if failed:
350+
msg = "Expected to perform {} queries {}{}".format(
351+
num,
352+
'' if exact else 'or less ',
353+
'but {} were done'.format(len(context))
354+
)
355+
if verbose:
356+
sqls = (q['sql'] for q in context.captured_queries)
357+
msg += '\n\nQueries:\n========\n\n%s' % '\n\n'.join(sqls)
358+
else:
359+
msg += " (add -v option to show queries)"
360+
pytest.fail(msg)
361+
343362

344-
@contextmanager
345-
def _assert_num_queries(num):
346-
with CaptureQueriesContext(connection) as context:
347-
yield
348-
if num != len(context):
349-
msg = "Expected to perform %s queries but %s were done" % (num, len(context))
350-
if pytestconfig.getoption('verbose') > 0:
351-
sqls = (q['sql'] for q in context.captured_queries)
352-
msg += '\n\nQueries:\n========\n\n%s' % '\n\n'.join(sqls)
353-
else:
354-
msg += " (add -v option to show queries)"
355-
pytest.fail(msg)
356-
357-
return _assert_num_queries
363+
@pytest.fixture(scope='function')
364+
def django_assert_num_queries(pytestconfig):
365+
return partial(_assert_num_queries, pytestconfig)
366+
367+
368+
@pytest.fixture(scope='function')
369+
def django_assert_max_num_queries(pytestconfig):
370+
return partial(_assert_num_queries, pytestconfig, exact=False)

pytest_django/plugin.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
from .django_compat import is_django_unittest # noqa
1818
from .fixtures import django_assert_num_queries # noqa
19+
from .fixtures import django_assert_max_num_queries # noqa
1920
from .fixtures import django_db_setup # noqa
2021
from .fixtures import django_db_use_migrations # noqa
2122
from .fixtures import django_db_keepdb # noqa

tests/test_fixtures.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,22 @@ def test_django_assert_num_queries_db(django_assert_num_queries):
6262
Item.objects.create(name='quux')
6363

6464

65+
@pytest.mark.django_db
66+
def test_django_assert_max_num_queries_db(django_assert_max_num_queries):
67+
with django_assert_max_num_queries(2):
68+
Item.objects.create(name='1-foo')
69+
Item.objects.create(name='2-bar')
70+
71+
with pytest.raises(pytest.fail.Exception):
72+
with django_assert_max_num_queries(2):
73+
Item.objects.create(name='1-foo')
74+
Item.objects.create(name='2-bar')
75+
Item.objects.create(name='3-quux')
76+
77+
6578
@pytest.mark.django_db(transaction=True)
66-
def test_django_assert_num_queries_transactional_db(transactional_db, django_assert_num_queries):
79+
def test_django_assert_num_queries_transactional_db(
80+
transactional_db, django_assert_num_queries):
6781
with transaction.atomic():
6882

6983
with django_assert_num_queries(3):

0 commit comments

Comments
 (0)