Как проверить, зарегистрировано ли какое-либо сообщение журнала в тестовом примере Django?

Я хочу убедиться, что определенное условие в моем коде вызывает запись журнала в журнал django. Как мне это сделать с помощью модульной системы тестирования Django?

Есть ли место, где я могу проверять зарегистрированные сообщения, аналогично тому, как я могу проверять отправленные письма? Мой модульный тест расширяет django.test.TestCase .

3 Solutions collect form web for “Как проверить, зарегистрировано ли какое-либо сообщение журнала в тестовом примере Django?”

Использование модуля mock для издевательств модуля регистрации или объекта журнала. Когда вы это сделаете, проверьте аргументы, с которыми вызывается функция ведения журнала.

Например, если код выглядит следующим образом:

 import logging logger = logging.getLogger('my_logger') logger.error("Your log message here") 

это будет выглядеть так:

 from unittest.mock import patch # For python 2.x use from mock import patch @patch('this.is.my.module.logger') def test_check_logging_message(self, mock_logger): mock_logger.error.assert_called_with("Your log message here") 

Обычный способ издевательства над объектом регистрации (см. Ответ великолепного главы Симеона Виссера) немного сложнее в том, что он требует, чтобы тест исказил журнал во всех местах, где это было сделано. Это неудобно, если ведение журнала происходит из нескольких модулей или в коде, который у вас нет. Если модуль регистрирует данные из имени изменений, он нарушит ваши тесты.

В великолепный пакет testfixtures входят инструменты для добавления обработчика регистрации, который захватывает все созданные сообщения журнала, независимо от того, откуда они происходят. Захваченные сообщения позже могут быть опрошены в ходе теста. В простейшей форме:

Предполагая, что код-под-тест, который регистрирует:

 import logging logger = logging.getLogger() logger.info('a message') logger.error('an error') 

Тест для этого был бы следующим:

 from testfixtures import LogCapture with LogCapture() as l: call_code_under_test() l.check( ('root', 'INFO', 'a message'), ('root', 'ERROR', 'an error'), ) 

Слово «корень» указывает, что ведение журнала было отправлено через журнал, созданный с помощью logging.getLogger() (т.е. без аргументов). Если вы передадите аргумент arg для getLogger ( __name__ является обычным), этот arg будет использоваться вместо «root» ».

Тест не волнует, какой модуль создал журнал. Это может быть подмодуль, называемый нашим кодом для проверки, включая сторонний код.

Тест подтверждает фактическое сообщение журнала, которое было сгенерировано, в отличие от техники издевательств, которая утверждает о переданных аргументах. Они будут отличаться, если вызов logging.info использует строки формата «% s» с дополнительными аргументами, которые вы не раскрываете сами (например, используйте logging.info('total=%s', len(items)) вместо logging.info('total=%s' % len(items)) , что вам нужно. Это не лишняя работа и позволяет гипотетическим будущим службам агрегирования журналов, таким как «Sentry», работать правильно – они могут видеть, что «total = 12» и «total = total = 43 "- это два экземпляра одного и того же сообщения журнала. Именно поэтому pylint предупреждает о последней форме вызова logging.info .)

LogCapture включает средства фильтрации журналов и т. П. Его родительский пакет testfixtures, написанный Крисом Уизерсом, еще одним великолепным парнем, включает в себя множество других полезных инструментов тестирования. Документация находится здесь: http://pythonhosted.org/testfixtures/logging.html

Если вы используете тестовые классы, вы можете использовать следующее решение:

 import logger from django.test import TestCase class MyTest(TestCase): @classmethod def setUpClass(cls): super(MyTest, cls).setUpClass() cls.logging_error = logging.error logging.error = cls._error_log @classmethod def tearDownClass(cls): super(MyTest, cls).tearDownClass() logging.error = cls.logging_error @classmethod def _error_log(cls, msg): cls.logger = msg def test_logger(self): self.assertIn('Message', self.logger) 

Этот метод заменяет функцию error модуля logging вашим пользовательским методом только для целей тестирования и ставит stdout в переменную cls.logger , доступную в каждом тестовом случае, вызывая self.logger . В конце он возвращает изменения, помещая функцию error из модуля logging обратно.

  • Хорошая практика повторного использования модульного теста для различных функций в Python
  • Приложите нос @attr к названию теста
  • Длинное определение объекта внутри модульного теста Python
  • Python unittest: to mock.patch () или просто заменить метод с помощью Mock?
  • Python Unit Тестирование функции цикла
  • Рамка носа Python: как остановить выполнение при первом сбое
  • Патч-объект Python с side_effect
  • Как вы проверяете функцию, которая извлекает данные с помощью urllib2?
  • Python - лучший язык программирования в мире.