어떻게 Python Django에서 단위 테스트를 실행하는 동안 로깅을 비활성화 할 수 있습니까?


Answers

Django에 있기 때문에 settings.py에 다음 줄을 추가 할 수 있습니다 :

import sys
import logging

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

그런 식으로 테스트에서 모든 setUp ()에 해당 행을 추가 할 필요가 없습니다. :)

이런 식으로 테스트 요구 사항을 손쉽게 변경할 수 있습니다.

테스트에 세부 사항을 추가하는 또 다른 "좋네요"또는 "깔끔한"방법이 있으며 테스트 러너를 만들고 있습니다.

다음과 같은 클래스를 작성하십시오.

import logging

from django.test.simple import DjangoTestSuiteRunner
from django.conf import settings

class MyOwnTestRunner(DjangoTestSuiteRunner):
    def run_tests(self, test_labels, extra_tests=None, **kwargs):

        # Don't show logging messages while testing
        logging.disable(logging.CRITICAL)

        return super(MyOwnTestRunner, self).run_tests(test_labels, extra_tests, **kwargs)

이제 settings.py 파일에 추가하십시오.

TEST_RUNNER = "PATH.TO.PYFILE.MyOwnTestRunner"
#(for example, 'utils.mytest_runner.MyOwnTestRunner')

이렇게하면 다른 접근 방식과 달리 Django가 원하는 응용 프로그램 만 테스트하게 만드는 매우 편리한 수정 작업을 수행 할 수 있습니다. 이 줄을 테스트 러너에 추가하는 test_labels를 변경하면됩니다.

if not test_labels:
    test_labels = ['my_app1', 'my_app2', ...]
Question

나는 Django 응용 프로그램을 테스트하기 위해 간단한 단위 테스트 기반 테스트 러너를 사용하고 있습니다.

내 응용 프로그램 자체는 settings.py에서 다음을 사용하여 기본 로거를 사용하도록 구성됩니다.

logging.basicConfig(level=logging.DEBUG)

그리고 내 응용 프로그램 코드를 사용하여 :

logger = logging.getLogger(__name__)
logger.setLevel(getattr(settings, 'LOG_LEVEL', logging.DEBUG))

그러나 unittests를 실행할 때 로깅을 비활성화하여 테스트 결과 출력을 복잡하게하지 않도록하십시오. 글로벌 방식으로 로깅을 끌 수있는 간단한 방법이있어 테스트를 실행할 때 응용 프로그램 별 로거가 콘솔에 물건을 쓰지 않도록 할 수 있습니까?




때로는 로그를 원할 때가 있습니다. 내 settings.py 에이 코드가

import sys

if '--no-logs' in sys.argv:
    print('> Disabling logging levels of CRITICAL and below.')
    sys.argv.remove('--no-logs')
    logging.disable(logging.CRITICAL)

따라서 --no-logs 옵션을 사용하여 테스트를 실행하면 critical 로그 만 얻습니다.

$ python ./manage.py tests --no-logs
> Disabling logging levels of CRITICAL and below.

지속적인 통합 흐름에 대한 테스트 속도를 높이려면 매우 유용합니다.




글로벌 방식으로 로깅을 끌 수있는 간단한 방법이있어 테스트를 실행할 때 응용 프로그램 별 로거가 콘솔에 물건을 쓰지 않도록 할 수 있습니까?

다른 대답은 로깅 인프라를 전역 적으로 설정하여 "콘솔에 물건을 쓰는"것을 방지합니다. 이것은 효과가 있지만 너무 무딘 접근 방식을 찾습니다. 내 접근 방식은 콘솔에서 로그를 내보내는 것을 방지하는 데 필요한 구성 변경 만 수행하는 것입니다. 그래서 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

그리고 필터를 사용하기 위해 장고 로깅설정합니다 :

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,
        },
    }
}

최종 결과 : 테스트 할 때 콘솔에 아무 것도 보내지 않지만 다른 모든 것은 그대로 유지됩니다.

왜 이것을할까요?

특정 상황에서만 트리거되는 로깅 지침을 포함하는 코드를 디자인하고 일이 잘못되면 진단에 필요한 정확한 데이터를 출력해야합니다. 따라서 나는 그들이해야 할 일을 수행하는지 테스트 하여 로깅을 완전히 비활성화하는 것이 가능하지 않습니다. 일단 소프트웨어가 생산 중이 라면, 내가 기록한 내용이 기록되지 않는다고 생각 하고 싶지는 않습니다.

또한 일부 테스트 주자 (예 : Nose)는 테스트 중에 로그를 캡처하여 테스트 실패와 함께 로그의 관련 부분을 출력합니다. 테스트가 실패한 이유를 알아내는 데 유용합니다. 로깅이 완전히 꺼지면 캡처 할 수있는 것이 없습니다.




제 경우에는 테스트 목적으로 특별히 만들어진 설정 파일 settings/test.py 있습니다. 다음은 그 모습입니다.

from .base import *

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'test_db'
    }
}

PASSWORD_HASHERS = (
    'django.contrib.auth.hashers.MD5PasswordHasher',
)

LOGGING = {}

환경 변수 DJANGO_SETTINGS_MODULE=settings.test/etc/environment 넣습니다.