Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add django_debug_sql ini option #725

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 32 additions & 3 deletions pytest_django/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import with_statement

import logging
import os
import warnings
from contextlib import contextmanager
Expand Down Expand Up @@ -80,6 +81,27 @@ def django_db_createdb(request):
return request.config.getvalue("create_db")


def _setup_sql_debug_logging():
# Simulate what Django's DebugSQLTextTestResult does.
logger = logging.getLogger('django.db.backends')
oldlevel = logger.level
logger.setLevel(logging.DEBUG)
return oldlevel


def _restore_sql_debug_logging(request, oldlevel):
logger = logging.getLogger('django.db.backends')
if logger.level != logging.DEBUG:
request.node.warn(pytest.PytestWarning(
"Debug logging level of django.db.backends was changed (to {}). "
"SQL queries might be missing. "
"This might be caused by calling django.setup() too late/unnecessarily.".format(
logger.level
)
))
logger.setLevel(oldlevel)


@pytest.fixture(scope="session")
def django_db_setup(
request,
Expand All @@ -95,6 +117,11 @@ def django_db_setup(

setup_databases_args = {}

debug_sql = request.config.getini("django_debug_sql")
if debug_sql:
setup_databases_args["debug_sql"] = True
old_loglevel = _setup_sql_debug_logging()

if not django_db_use_migrations:
_disable_native_migrations()

Expand All @@ -108,7 +135,9 @@ def django_db_setup(
**setup_databases_args
)

def teardown_database():
yield

if not django_db_keepdb:
with django_db_blocker.unblock():
try:
teardown_databases(db_cfg, verbosity=request.config.option.verbose)
Expand All @@ -119,8 +148,8 @@ def teardown_database():
)
)

if not django_db_keepdb:
request.addfinalizer(teardown_database)
if debug_sql:
_restore_sql_debug_logging(request, old_loglevel)


def _django_db_fixture_helper(
Expand Down
6 changes: 6 additions & 0 deletions pytest_django/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ def pytest_addoption(parser):
type="bool",
default=True,
)
parser.addini(
"django_debug_sql",
"Enable logging of SQL statements, displayed with failed tests.",
type="bool",
default=False,
)
group._addoption(
"--fail-on-template-vars",
action="store_true",
Expand Down
63 changes: 63 additions & 0 deletions tests/test_db_debug.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
def test_debug_sql_setting(django_testdir):
django_testdir.create_test_module(
"""
import pytest

from .app.models import Item

@pytest.mark.django_db
def test_fail_with_db_queries():
assert Item.objects.count() == 0
assert 0, "triggered failure"
"""
)
django_testdir.makeini(
"""
[pytest]
django_debug_sql = 1
"""
)

result = django_testdir.runpytest_subprocess()
assert result.ret == 1
result.stdout.fnmatch_lines([
"*- Captured log setup -*",
"*CREATE TABLE*",
"*- Captured log call -*",
"*SELECT COUNT*",
])


def test_debug_sql_with_django_setup(django_testdir):
django_testdir.create_test_module(
"""
import pytest

from .app.models import Item

@pytest.mark.django_db
def test_fail_with_db_queries():
import django
django.setup()

assert Item.objects.count() == 0
assert 0, "triggered failure"
"""
)
django_testdir.makeini(
"""
[pytest]
django_debug_sql = 1
"""
)

result = django_testdir.runpytest_subprocess()
assert result.ret == 1
result.stdout.fnmatch_lines([
# "*- Captured stdout setup -*",
"*- Captured log setup -*",
"*CREATE TABLE*",
"*= warnings summary =*",
"*Debug logging level of django.db.backends was changed (to 0).*",
])
assert "SELECT COUNT" not in result.stdout.str()