I am using a simple unit test based test runner to test my Django application.
My application itself is configured to use a basic logger in settings.py using:
logging.basicConfig(level=logging.DEBUG)
And in my application code using:
logger = logging.getLogger(__name__)
logger.setLevel(getattr(settings, 'LOG_LEVEL', logging.DEBUG))
However, when running unittests, I'd like to disable logging so that it doesn't clutter my test result output. Is there a simple way to turn off logging in a global way, so that the application specific loggers aren't writing stuff out to the console when I run tests?
I like Hassek's custom test runner idea. It should be noted that
DjangoTestSuiteRunner
is no longer the default test runner in Django 1.6+, it has been replaced by theDiscoverRunner
. For default behaviour, the test runner should be more like:Since you are in Django, you could add these lines to your settings.py:
That way you don't have to add that line in every setUp() on your tests. :)
You could also do a couple of handy changes for your test needs this way.
There is another "nicer" or "cleaner" way to add specifics to your tests and that is making your own test runner.
Just create a class like this:
And now add to your settings.py file:
This lets you do one really handy modification that the other approach doesn't, which is to make Django just tests the applications that you want. You can do that by changing the test_labels adding this line to the test runner:
I've found that for tests within
unittest
or similar a framework, the most effective way to safely disable unwanted logging in unit tests is to enable/disable in thesetUp
/tearDown
methods of a particular test case. This lets one target specifically where logs should be disabled. You could also do this explicitly on the logger of the class you're testing.In my case I have a settings file
settings/test.py
created specifically for testing purposes, here's what it looks like:I put an environment variable
DJANGO_SETTINGS_MODULE=settings.test
to/etc/environment
.There is some pretty and clean method to suspend logging in tests with
unittest.mock.patch
method.foo.py:
tests.py:
And
python3 -m unittest tests
will produce no logging output.The other answers prevent "writing stuff out to the console" by globally setting the logging infrastructure to ignore anything. This works but I find it too blunt an approach. My approach is to perform a configuration change which does only what's needed to prevent logs to get out on the console. So I add a custom logging filter to my
settings.py
:And I configure the Django logging to use the filter:
End result: when I'm testing, nothing goes to the console, but everything else stays the same.
Why Do This?
I design code that contains logging instructions that are triggered only in specific circumstances and that should output the exact data I need for diagnosis if things go wrong. Therefore I test that they do what they are supposed to do and thus completely disabling logging is not viable for me. I don't want to find once the software is in production that what I thought would be logged is not logged.
Moreover, some test runners (Nose, for instance) will capture logs during testing and output the relevant part of the log together with a test failure. It is useful in figuring out why a test failed. If logging is completely turned off, then there's nothing that can be captured.