A Django test utility to assert the number of queries per model.
Project description
Django Assert Model Queries
This project seeks to assist asserting the number of queries per model during testing.
Note: This does so by monkey-patching the SQLCompiler classes. It's
not something that should be relied upon in production.
Installation
pip install django-assert-model-queries
Usage
There are integrations for both pytest and Django / unittest. Both of
which use the context manager,
django_assert_model_queries.AssertModelQueries under the
hood.
The basic usage is to define a dictionary of expected queries to be evaluated at the end of the context manager's scope. If the counts differ, a helpful error message will be rendered indicating what the differences were and what all the queries were during the context.
from django_assert_model_queries import AssertModelQueries
from testapp.models import Community
with AssertModelQueries({"testapp.Community": 2}):
Community.objects.create(name="test")
Community.objects.update(name="test")
When an unexpected query runs, this AssertModelQueries will
tell you which model generated an unexpected query.
Example error
Here is an example of what you can expect from the tool:
>>> from django_assert_model_queries import AssertModelQueries
>>> from django.contrib.auth.models import User
>>> with AssertModelQueries({}):
>>> User.objects.first()
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
Cell In[1], line 3
1 from django_assert_model_queries import AssertModelQueries
2 from django.contrib.auth.models import User
----> 3 with AssertModelQueries({}):
4 User.objects.only("id").first()
File ~/site-packages/django_assert_model_queries/test.py:145, in AssertModelQueries.__exit__(self, exc_type, exc_value, traceback)
142 if exc_type is not None:
143 return
--> 145 self.handle_assertion(actual, expected)
146 self.expected_model_counts = None
File ~/site-packages/django_assert_model_queries/test.py:172, in AssertModelQueries.handle_assertion(self, actual, expected)
170 pytest.fail(self.failure_message(actual, expected))
171 else:
--> 172 assert actual == expected, self.failure_message(actual, expected)
AssertionError: {'auth.User': 1} != {}
- {'auth.User': 1}
+ {}
All queries:
SELECT "auth_user"."id" FROM "auth_user" ORDER BY "auth_user"."id" ASC LIMIT 1
Integrating with pytest
If you use pytest, you can use the fixture assert_model_queries as a short-cut.
# pytest example
import pytest
from testapp.models import Community
class TestPytestIntegration:
@pytest.mark.django_db
def test_assert_model_queries(self, assert_model_queries):
with assert_model_queries({"testapp.Community": 1}):
Community.objects.create(name="test")
with assert_model_queries({
"testapp.Community": 2,
"testapp.Chapter": 1,
"testapp.Community_topics": 1,
}):
Community.objects.all().delete()
Integrating with unittest
If you test with Django's TestCase, inherit from the mixin
ModelNumQueriesHelper to be able to utilize the
self.assertModelQueries assertion method.
# Django TestCase example
from django.test import TestCase
from django_assert_model_queries import AssertModelQueries, ModelNumQueriesHelper
from testapp.models import Community
class TestDjangoIntegration(ModelNumQueriesHelper, TestCase):
def test_assert_model_num_queries_context(self):
with AssertModelQueries({"testapp.Community": 1}):
Community.objects.create(name="test")
with AssertModelQueries({"testapp.Community": 2, "testapp.Chapter": 1, "testapp.Community_topics": 1}):
Community.objects.all().delete()
class TestDjangoHelperIntegration(ModelNumQueriesHelper, TestCase):
def test_helper(self):
with self.assertModelQueries({"testapp.Community": 1}):
Community.objects.create(name="test")
with self.assertModelQueries({"testapp.Community": 2, "testapp.Chapter": 1, "testapp.Community_topics": 1}):
Community.objects.all().delete()
Complex usages
There are a few parameters that may help in certain scenarios.
ignore: A collection of models that should be ignored. For example, maybe you want to ignoreSessionqueries if you're using a database backed session.strict=False: You can limit the count evaluation to just the models specified in theexpect_model_countscollection. Be warned, this can hide N+1 issues.
To use these, you must specify them when instantiating
AssertModelQueries.
from django_assert_model_queries import AssertModelQueries
from django.contrib.sessions.models import Session
assert_context = AssertModelQueries(ignore={Session})
with assert_context({"testapp.Community": 1}):
do_something()
assert_context = AssertModelQueries(strict=False)
with assert_context({"testapp.Community": 1}):
do_something()
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_assert_model_queries-1.1.0.tar.gz.
File metadata
- Download URL: django_assert_model_queries-1.1.0.tar.gz
- Upload date:
- Size: 21.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.1 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e9d77f03fcc6adc12175bd2b9b59bd43f2990547f4e68e53b3a647a1b5e9d935
|
|
| MD5 |
b473c37598afa4b3f693ebb2a32cab15
|
|
| BLAKE2b-256 |
ad97d493a1899a5b6087f4e8c97cbc90dcb379fa6c85ea0768da5bbf9862538e
|
File details
Details for the file django_assert_model_queries-1.1.0-py3-none-any.whl.
File metadata
- Download URL: django_assert_model_queries-1.1.0-py3-none-any.whl
- Upload date:
- Size: 8.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.1 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e09cd62780b0e808fa933200fb7cc699b9d5061cd16dba6ce666559243b7581b
|
|
| MD5 |
1b0d798b4eca66d9bc88e8e70347aa2a
|
|
| BLAKE2b-256 |
626b7b24b27182aff46a36e3469388fee09fd664b909358e2736e86b82160638
|