Silence application logs in Django tests

Suppress noisy Python logs for selected tests, restore the previous state, and keep log assertions working.

Best practices
Illustration of monitoring and troubleshooting application behavior

logging.disable(logging.CRITICAL) suppresses records at CRITICAL and below through Python's logging API. It is a process-wide setting, so scope it carefully and restore the previous threshold. It does not suppress print, direct stream writes, or the test runner's ordinary assertion report.

Scope suppression to a test

import logging
from django.test import SimpleTestCase

class QuietTests(SimpleTestCase):
    def setUp(self):
        super().setUp()
        previous = logging.root.manager.disable
        self.addCleanup(logging.disable, previous)
        logging.disable(logging.CRITICAL)

    def test_something(self):
        self.assertEqual(2 + 2, 4)

Cleanup restores the original global threshold even when the test fails. Custom logging levels above CRITICAL are outside this suppression range. Other tests or threads in the same process also see the setting while it is active.

Use explicit test settings for a suite

A check such as this recognizes the usual manage.py test argument layout:

import logging
import sys

if len(sys.argv) > 1 and sys.argv[1] == 'test':
    logging.disable(logging.CRITICAL)

It does not reliably cover pytest, IDE runners, or every management-command invocation. An explicit test settings module or runner setup makes suite-wide behavior easier to reason about. Avoid a hidden production setting that depends on a fragile command-line guess.

Filter just the noisy logger

To suppress database logs on a particular console handler, define a filter:

# project/logging_filters.py
import logging

class ExcludeDatabaseLogs(logging.Filter):
    def filter(self, record):
        name = record.name
        return not (
            name == 'django.db.backends'
            or name.startswith('django.db.backends.')
        )

Register it in the test logging configuration:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'no_sql': {'()': 'project.logging_filters.ExcludeDatabaseLogs'},
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'filters': ['no_sql'],
        },
    },
    'root': {'handlers': ['console'], 'level': 'INFO'},
}

Merge this deliberately with your test settings. Only records reaching this handler are filtered; another handler attached to a Django logger can still emit them. Check handler attachment and propagation if output is duplicated.

Re-enable logging for assertions

Global suppression does affect assertLogs; changing a logger's level inside that context does not bypass logging.disable. Restore logging temporarily:

previous = logging.root.manager.disable
try:
    logging.disable(logging.NOTSET)
    with self.assertLogs('myapp', level='INFO') as captured:
        logging.getLogger('myapp').info('Expected event')
finally:
    logging.disable(previous)

Keep this inside a test method. Django's normal test runner uses DEBUG=False, but it does not universally silence application logging. SQL output also depends on debug-cursor and test-runner options. Configure the specific noise you want to remove while retaining diagnostics that explain failures.

References: Python logging, assertLogs, and Django logging.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting