A Django test mixin that captures and displays SQL query diffs between test runs, helping to track database-related changes in your tests.
Project description
django-sql-test
Prevent SQL regressions, detect N+1 queries, and visualize query diffs in your Django tests. A test mixin that captures, snapshots, and diffs all executed SQL queries in your test output.
$ poetry run python manage.py test path.to.test.FooTest.test_bar
======================================================================
FAIL: test_bar (path.to.test.FooTest.test_bar)
...
AssertionError: 5 != 2 : 5 queries executed, 2 expected
Queries diff:
- SELECT polls_choice.id FROM polls_choice
+ SELECT polls_choice.id FROM polls_choice WHERE polls_choice.votes >= N
+ SELECT polls_question.id FROM polls_question WHERE polls_question.id = N LIMIT N
+ SELECT polls_question.id FROM polls_question WHERE polls_question.id = N LIMIT N
+ SELECT polls_question.id FROM polls_question WHERE polls_question.id = N LIMIT N
SELECT COUNT(*) AS __count FROM polls_question
Table of Contents
Requirements
- Django >= 4.0
- Python >= 3.9
Installation
pip install django-sql-test
Quickstart
In your test.py just import NumNewQueriesMixin and add it as a parent:
from django.test import TestCase
from django_sql_test import NumNewQueriesMixin
class FooTest(NumNewQueriesMixin, TestCase):
def test_bar(self):
with self.assertNumNewQueries(2):
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
What you got before adding NumNewQueriesMixin:
$ poetry run python manage.py test path.to.test.FooTest.test_bar
======================================================================
FAIL: test_bar (path.to.test.FooTest.test_bar)
...
AssertionError: 5 != 2 : 5 queries executed, 2 expected
Captured queries were:
1. SELECT "polls_choice"."id" FROM "polls_choice" WHERE "polls_choice"."votes" >= 0
2. SELECT "polls_question"."id" FROM "polls_question" WHERE "polls_question"."id" = 1 LIMIT 21
3. SELECT "polls_question"."id" FROM "polls_question" WHERE "polls_question"."id" = 1 LIMIT 21
4. SELECT "polls_question"."id" FROM "polls_question" WHERE "polls_question"."id" = 1 LIMIT 21
5. SELECT COUNT(*) AS "__count" FROM "polls_question"
What you get after adding NumNewQueriesMixin:
$ poetry run python manage.py test path.to.test.FooTest.test_bar
======================================================================
FAIL: test_bar (path.to.test.FooTest.test_bar)
...
AssertionError: 5 != 2 : 5 queries executed, 2 expected
Queries diff:
- SELECT polls_choice.id FROM polls_choice
+ SELECT polls_choice.id FROM polls_choice WHERE polls_choice.votes >= N
+ SELECT polls_question.id FROM polls_question WHERE polls_question.id = N LIMIT N
+ SELECT polls_question.id FROM polls_question WHERE polls_question.id = N LIMIT N
+ SELECT polls_question.id FROM polls_question WHERE polls_question.id = N LIMIT N
SELECT COUNT(*) AS __count FROM polls_question
Configuration
Configure via your Django settings:
| Setting | Default | Description |
|---|---|---|
SQL_TEST_GENERALIZED_DIFF |
True |
Hides SQL query parameters by replacing them with placeholders. |
SQL_TEST_DIFF_ONLY |
False |
If set to True, shows only SQL queries that were added or removed; otherwise, shows all queries. |
SQL_TEST_DIFF_NEW_COLOR |
"\033[1;32m" |
Color code for newly added SQL queries (green). |
SQL_TEST_DIFF_OLD_COLOR |
"\033[1;31m" |
Color code for removed SQL queries (red). |
SQL_TEST_DIFF_DEFAULT_COLOR |
"\033[0m" |
Base console color code for unchanged SQL queries. |
SQL_TEST_ENGINE |
"file" |
Engine used to store the last successful SQL queries. Default "file" engine stores data in the file from SQL_TEST_ENGINE_SETTINGS["filename"], or in .django_sql_test_queries at the project root if not set. You can implement a custom engine by inheriting from django_sql_test.engine.Engine, overriding its methods, and specifying its full path, e.g., SQL_TEST_ENGINE = "path.to.YourEngine". |
SQL_TEST_ENGINE_SETTINGS |
{} |
Dictionary of settings passed to the engine's constructor. For the default "file" engine, you can pass the path to the file where queries will be stored in JSON format. |
SQL_TEST_GENERALIZED_DIFF
If set to True:
Queries diff:
+ SELECT polls_choice.id FROM polls_choice WHERE polls_choice.votes >= N
If set to False:
Queries diff:
+ SELECT "polls_choice"."id" FROM "polls_choice" WHERE "polls_choice"."votes" >= 0
API Reference
NumNewQueriesMixin
| Method | Description |
|---|---|
assertNumNewQueries |
Works just like django.test.testcases.TransactionTestCase.assertNumQueries, but also prints the diff of queries compared to the last successful run, if any. |
assertNumQueries |
Acts like assertNumNewQueries. It can be used if you don’t want to replace every occurrence of assertNumQueries with assertNumNewQueries in your tests. Simply inherit from it in your test class, for example: class PaginatorsTestCase(NumNewQueriesMixin, ViewTestCase), and everything will work out of the box. |
Contributing
We welcome contributions! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/YourFeature) - Write tests and ensure coverage
- Run and pass:
poetry run isort -c --diff --settings-file pyproject.toml . poetry run black --diff --config pyproject.toml --check . poetry run python runtests.py
- Submit a pull request
License
This project is licensed under the MIT License. See LICENSE for details.
Changelog
All notable changes are documented on the Releases page.
Project details
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_sql_test-0.3.0.tar.gz.
File metadata
- Download URL: django_sql_test-0.3.0.tar.gz
- Upload date:
- Size: 5.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.1 CPython/3.13.2 Darwin/24.5.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
28d6dd56870b043ffc57da8cbd6a08a551e09203c5f47d66c6ac1950b7d36c86
|
|
| MD5 |
ad328580adb47fd49e8f32ab22080768
|
|
| BLAKE2b-256 |
0145a68301650a159a3c7d3d503bd687e2697b78c8dc0ec46b2ea1c4892685f1
|
File details
Details for the file django_sql_test-0.3.0-py3-none-any.whl.
File metadata
- Download URL: django_sql_test-0.3.0-py3-none-any.whl
- Upload date:
- Size: 7.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.1 CPython/3.13.2 Darwin/24.5.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1051eea2bc2277a84f9076343b986cf4b22451d4c4e6b2bd8e5e4c2ecd98cbd3
|
|
| MD5 |
991c627d13aeee406e16445f2a7cb7db
|
|
| BLAKE2b-256 |
33fe8b722e9690d6d0a31919e9e414ab39ab89f16a59a44b2af45cb094d1daf8
|