Disabling Logging for Faster Django Unit Tests

Running unit tests is an integral part of developing with Django. Unit tests allow developers to verify that their code works as expected and catch regressions early. However, leaving logging enabled while running tests can slow things down significantly. In this post, we’ll explore some techniques for disabling logging in Django during test execution to speed things up.

Why Disable Logging for Tests?

Django comes with full-featuredLogging enabled out of the box. This logging provides valuable information when running a dev server or production application. However logging has a cost – formatting and outputting log messages takes time. When running large test suites, all of those log messages can add up to a major slow down.

For example, a test suite might make hundreds of requests to test views and APIs. The logging from all of those requests could mean seconds wasted for each test run. Therefore, disabling logging is a common optimization for keeping test suite runs fast.

Built-In Option: django.test Logging

Luckily, Django provides a simple way to disable logging in tests built right in. The django.test Logger is designed specifically for tests. By default, this logger disables all handlers, meaning nothing gets output.

To use the test logger, import and configure it in the setUp() method of your test classes:

import logging

logger = logging.getLogger('django.test')
logger.addHandler(logging.NullHandler())
logger.propagate = False

With this test logger configured, no log messages will be handled or propagated while running tests.

Disabling Specific Loggers

The django.test Logger disables allLogging globally. Sometimes you might want to only disable certain loggers, while allowing others for debugging tests.

For example, you could specifically disable the django top level logger:

import logging

django_logger = logging.getLogger('django')
django_logger.setLevel(logging.CRITICAL)

Now only critical Django logging will occur during tests. The same technique works for any other application-specific loggers as well.

Optimizing Config for Faster Tests

In addition to disabling logging, there are other test optimization techniques that can speed up test runs:

  • Use the unittest.mock library to patch slow external API calls. For example, you could mock out calls to payment gateways or social APIs.
  • Configure a separate test database or schema to prevent tests interacting with real data. The test runner will handle creating and destroying the test database between runs.
  • Minimize file I/O in tests by not touching the filesystem if possible. I/O operations, like writing to a file, can drastically slow things down.
  • Where possible, use in-memory test modes for caches and message brokers like Redis or Celery. This avoids round trips to separate processes or servers.

Wrapping Up

Logging is invaluable when diagnosing issues in production Django deployments. However, left enabled, it can bog down test suite execution speed. The built-in django.test Logger provides an easy route to disabling logging during test runs.

Additionally, optimizing your configuration to minimize external interactions can further speed up tests. Fast unit tests means faster test driven development, resulting in more agile Django projects.