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.