Как я должен проверить сообщение журнала при тестировании кода Python под носом?

Вот несколько инструкций, чтобы делать то, что вы хотите.

Это удалит file_to_remove:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch file_to_remove' --prune-empty -- --all

57
задан Quinn Taylor 10 July 2009 в 15:06
поделиться

4 ответа

I used to mock loggers, but in this situation I found best to use logging handlers, so I wrote this one based on the document suggested by jkp(now dead, but cached on Internet Archive)

class MockLoggingHandler(logging.Handler):
    """Mock logging handler to check for expected logs."""

    def __init__(self, *args, **kwargs):
        self.reset()
        logging.Handler.__init__(self, *args, **kwargs)

    def emit(self, record):
        self.messages[record.levelname.lower()].append(record.getMessage())

    def reset(self):
        self.messages = {
            'debug': [],
            'info': [],
            'warning': [],
            'error': [],
            'critical': [],
        }
21
ответ дан 24 November 2019 в 19:14
поделиться

Нашел один ответ с тех пор, как опубликовал это. Неплохо.

0
ответ дан 24 November 2019 в 19:14
поделиться

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

Мокинг будет продолжать работать, даже если стандартный вывод будет подавлен.

Я использовал pyMox . заглушки. Не забудьте отключить заглушки после теста.

1
ответ дан 24 November 2019 в 19:14
поделиться

В продолжение ответа Рифа я взял на себя смелость написать пример с использованием pymox . Он вводит некоторые дополнительные вспомогательные функции, которые упрощают создание заглушек для функций и методов.

import logging

# Code under test:

class Server(object):
    def __init__(self):
        self._payload_count = 0
    def do_costly_work(self, payload):
        # resource intensive logic elided...
        pass
    def process(self, payload):
        self.do_costly_work(payload)
        self._payload_count += 1
        logging.info("processed payload: %s", payload)
        logging.debug("payloads served: %d", self._payload_count)

# Here are some helper functions
# that are useful if you do a lot
# of pymox-y work.

import mox
import inspect
import contextlib
import unittest

def stub_all(self, *targets):
    for target in targets:
        if inspect.isfunction(target):
            module = inspect.getmodule(target)
            self.StubOutWithMock(module, target.__name__)
        elif inspect.ismethod(target):
            self.StubOutWithMock(target.im_self or target.im_class, target.__name__)
        else:
            raise NotImplementedError("I don't know how to stub %s" % repr(target))
# Monkey-patch Mox class with our helper 'StubAll' method.
# Yucky pymox naming convention observed.
setattr(mox.Mox, 'StubAll', stub_all)

@contextlib.contextmanager
def mocking():
    mocks = mox.Mox()
    try:
        yield mocks
    finally:
        mocks.UnsetStubs() # Important!
    mocks.VerifyAll()

# The test case example:

class ServerTests(unittest.TestCase):
    def test_logging(self):
        s = Server()
        with mocking() as m:
            m.StubAll(s.do_costly_work, logging.info, logging.debug)
            # expectations
            s.do_costly_work(mox.IgnoreArg()) # don't care, we test logging here.
            logging.info("processed payload: %s", 'hello')
            logging.debug("payloads served: %d", 1)
            # verified execution
            m.ReplayAll()
            s.process('hello')

if __name__ == '__main__':
    unittest.main()
3
ответ дан 24 November 2019 в 19:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: