How can I disable logging while running unit tests in Python Django?

后端 未结 15 777
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-07 09:50

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:

<
15条回答
  •  时光取名叫无心
    2020-12-07 10:26

    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?

    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:

    from logging import Filter
    
    class NotInTestingFilter(Filter):
    
        def filter(self, record):
            # Although I normally just put this class in the settings.py
            # file, I have my reasons to load settings here. In many
            # cases, you could skip the import and just read the setting
            # from the local symbol space.
            from django.conf import settings
    
            # TESTING_MODE is some settings variable that tells my code
            # whether the code is running in a testing environment or
            # not. Any test runner I use will load the Django code in a
            # way that makes it True.
            return not settings.TESTING_MODE
    

    And I configure the Django logging to use the filter:

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'filters': {
            'testing': {
                '()': NotInTestingFilter
            }
        },
        'formatters': {
            'verbose': {
                'format': ('%(levelname)s %(asctime)s %(module)s '
                           '%(process)d %(thread)d %(message)s')
            },
        },
        'handlers': {
            'console': {
                'level': 'DEBUG',
                'class': 'logging.StreamHandler',
                'filters': ['testing'],
                'formatter': 'verbose'
            },
        },
        'loggers': {
            'foo': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': True,
            },
        }
    }
    

    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.

提交回复
热议问题