Skip to content

Commit f132019

Browse files
anrieblueyed
authored andcommitted
Add fixture for asserting maximum number of database queries
1 parent c0e5b6c commit f132019

File tree

4 files changed

+65
-18
lines changed

4 files changed

+65
-18
lines changed

docs/helpers.rst

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

267267

268+
``django_assert_max_num_queries``
269+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
270+
271+
This fixture allows to check for an expected maximum number of DB queries.
272+
It currently only supports the default database.
273+
274+
275+
Example
276+
"""""""
277+
278+
::
279+
280+
def test_max_queries(django_assert_max_num_queries):
281+
with django_assert_max_num_queries(3):
282+
Item.objects.create('foo')
283+
Item.objects.create('bar')
284+
285+
268286
``mailoutbox``
269287
~~~~~~~~~~~~~~
270288

pytest_django/fixtures.py

Lines changed: 31 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

@@ -17,7 +18,8 @@
1718
__all__ = ['django_db_setup', 'db', 'transactional_db', 'admin_user',
1819
'django_user_model', 'django_username_field',
1920
'client', 'admin_client', 'rf', 'settings', 'live_server',
20-
'_live_server_helper', 'django_assert_num_queries']
21+
'_live_server_helper', 'django_assert_num_queries',
22+
'django_assert_max_num_queries']
2123

2224

2325
@pytest.fixture(scope='session')
@@ -352,22 +354,34 @@ def _live_server_helper(request):
352354
request.addfinalizer(live_server._live_server_modified_settings.disable)
353355

354356

355-
@pytest.fixture(scope='function')
356-
def django_assert_num_queries(pytestconfig):
357+
@contextmanager
358+
def _assert_num_queries(config, num, exact=True):
357359
from django.db import connection
358360
from django.test.utils import CaptureQueriesContext
361+
verbose = config.getoption('verbose') > 0
362+
with CaptureQueriesContext(connection) as context:
363+
yield
364+
num_queries = len(context)
365+
failed = num != num_queries if exact else num < num_queries
366+
if failed:
367+
msg = "Expected to perform {} queries {}{}".format(
368+
num,
369+
'' if exact else 'or less ',
370+
'but {} were done'.format(num_queries)
371+
)
372+
if verbose:
373+
sqls = (q['sql'] for q in context.captured_queries)
374+
msg += '\n\nQueries:\n========\n\n%s' % '\n\n'.join(sqls)
375+
else:
376+
msg += " (add -v option to show queries)"
377+
pytest.fail(msg)
378+
359379

360-
@contextmanager
361-
def _assert_num_queries(num):
362-
with CaptureQueriesContext(connection) as context:
363-
yield
364-
if num != len(context):
365-
msg = "Expected to perform %s queries but %s were done" % (num, len(context))
366-
if pytestconfig.getoption('verbose') > 0:
367-
sqls = (q['sql'] for q in context.captured_queries)
368-
msg += '\n\nQueries:\n========\n\n%s' % '\n\n'.join(sqls)
369-
else:
370-
msg += " (add -v option to show queries)"
371-
pytest.fail(msg)
372-
373-
return _assert_num_queries
380+
@pytest.fixture(scope='function')
381+
def django_assert_num_queries(pytestconfig):
382+
return partial(_assert_num_queries, pytestconfig)
383+
384+
385+
@pytest.fixture(scope='function')
386+
def django_assert_max_num_queries(pytestconfig):
387+
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
@@ -64,8 +64,22 @@ def test_django_assert_num_queries_db(django_assert_num_queries):
6464
Item.objects.create(name='quux')
6565

6666

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

7185
with django_assert_num_queries(3):

0 commit comments

Comments
 (0)