Skip to content
Merged
18 changes: 18 additions & 0 deletions docs/helpers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,21 @@ Example
def test_with_specific_settings(settings):
settings.USE_TZ = True
assert settings.USE_TZ

``assert_num_queries``
~~~~~~~~~~~~~~~~~~~~~~

This fixture allows to check that expected number of queries are performed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/of queries/of DB queries/

Note that currently it only supports default database.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better:

Note that it currently only supports the default database.



Example
"""""""

::

def test_queries(assert_num_queries):
with assert_num_queries(3):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/assert_num_queries/django_assert_num_queries/

Item.objects.create('foo')
Item.objects.create('bar')
Item.objects.create('baz')
24 changes: 23 additions & 1 deletion pytest_django/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

import pytest

from contextlib import contextmanager
from django.db import connection
from django.test.utils import CaptureQueriesContext
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These imports might cause the test failures.
Try importing it in the new fixture.


from . import live_server_helper

from .django_compat import is_django_unittest
Expand All @@ -15,7 +19,7 @@
__all__ = ['django_db_setup', 'db', 'transactional_db', 'admin_user',
'django_user_model', 'django_username_field',
'client', 'admin_client', 'rf', 'settings', 'live_server',
'_live_server_helper']
'_live_server_helper', 'assert_num_queries']


@pytest.fixture(scope='session')
Expand Down Expand Up @@ -323,3 +327,21 @@ def _live_server_helper(request):
"""
if 'live_server' in request.funcargnames:
request.getfuncargvalue('transactional_db')


@pytest.fixture(scope='function')
def assert_num_queries(db, pytestconfig):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like it should not use the db fixture, but some other that makes it work with transactional_db, too.
Speaking of this: please also add a test (maybe parameterized) for transactional_db (next to db).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see now that it is nice to use the db fixture automatically - but it should also work when using transactional_db in the test (which we should handle internally already).
So, just add a test where you use the transactional_db fixture explicitly.


@contextmanager
def _assert_num_queries(num):
with CaptureQueriesContext(connection) as context:
yield
msg = "Expected to perform %s queries but %s was done" % (num, len(context))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/was/were/

if pytestconfig.getoption('verbose') > 0:
sqls = (q['sql'] for q in context.captured_queries)
msg += '\n\nQueries:\n========\n\n%s' % '\n\n'.join(sqls)
else:
msg += " (add -v option to show queries)"
assert len(context) == num, msg
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think pytest.fail() might be better here? (instead of the assert)


return _assert_num_queries
1 change: 1 addition & 0 deletions pytest_django/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from .fixtures import _live_server_helper # noqa
from .fixtures import admin_client # noqa
from .fixtures import admin_user # noqa
from .fixtures import assert_num_queries # noqa
from .fixtures import client # noqa
from .fixtures import db # noqa
from .fixtures import django_user_model # noqa
Expand Down
16 changes: 16 additions & 0 deletions tests/test_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,22 @@ def test_rf(rf):
assert isinstance(rf, RequestFactory)


@pytest.mark.django_db
def test_assert_num_queries(assert_num_queries, django_user_model):
with assert_num_queries(3):
Item.objects.create(name='foo')
Item.objects.create(name='bar')
Item.objects.create(name='baz')


@pytest.mark.django_db
def test_assert_num_queries_fails_properly(assert_num_queries, django_user_model):
with pytest.raises(AssertionError):
with assert_num_queries(3):
Item.objects.create(name='foo')
Item.objects.create(name='bar')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please test for the expected output here, using testdir.runpytest_subprocess (see other tests for examples).



class TestSettings:
"""Tests for the settings fixture, order matters"""

Expand Down