我正在实现一种特定的日志记录格式,它将由另一个服务解析,用于日志记录/监控/警报目的。因此,日志记录格式需要非常具体。
我需要测试我的应用程序是否确实使用了我想要的格式。然而,无论出于何种原因,pytest
都在使用自己的格式,而忽略了我的格式。
下面的可复制示例:
# logtest.py
##### LOGGING CONFIGURATiON
import logging
LOG_CONFIG_FORMAT = '%(asctime)s {%(process)d-%(thread)d} %(levelname)s
%(name)s@%(lineno)d my_field_1=%(my_field_1)s my_field_2=%(my_field_2)s my_field_3=
%(my_field_3)s: %(message)s '
logging.basicConfig(level="DEBUG", format=LOG_CONFIG_FORMAT)
def get_logger(logger_name: str):
logger = logging.getLogger(logger_name)
adapter = logging.LoggerAdapter(logger, {
'my_field_2': None,
'my_field_1': None,
'my_field_3': None
})
return adapter
##### APPLICATION CODE
logger = get_logger(__name__)
def my_func():
for i in range(3):
if i > 1:
logger.extra = {
'my_field_2': 'BOOM!!!',
'my_field_1': 'BUST!!!',
'my_field_3': 'CRASH!!!'
}
logger.debug(i)
##### EXECUTE APPLICATION FUNCTION
my_func()
##### TESTING CODE
import unittest
class TestCase(unittest.TestCase):
def test_log(self):
with self.assertLogs(level="DEBUG") as cm:
my_func()
print(cm.output)
self.assertIn('my_field_1', cm.output[0])
如果我执行python logtest.py
,我会得到正确的格式。如果我执行pytest logtest.py
,我会得到pytest
自己的格式。
不关心pytest
的控制台输出,我如何测试应用程序日志的格式是否符合我的要求?
如果您只想测试格式化,则不需要使用basicConfig()
和assertLogs()
,而是可以使用以下方法:
import logging
import unittest
import sys
class TestHandler(logging.Handler):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.messages = []
def handle(self, record):
self.messages.append(self.format(record))
LOG_CONFIG_FORMAT = '%(asctime)s {%(process)d-%(thread)d} %(levelname)s
%(name)s@%(lineno)d my_field_1=%(my_field_1)s my_field_2=%(my_field_2)s my_field_3=
%(my_field_3)s: %(message)s '
formatter = logging.Formatter(LOG_CONFIG_FORMAT)
handler = TestHandler()
handler.setFormatter(formatter)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)
adapter = logging.LoggerAdapter(logger, {
'my_field_2': 'f2',
'my_field_1': 'f1',
'my_field_3': 'f3'
})
class TestCase(unittest.TestCase):
def test_formatting(self):
adapter.debug('Hello')
last = handler.messages[-1]
self.assertIn('my_field_1=f1 my_field_2=f2 my_field_3=f3: Hello ', last)
if __name__ == '__main__':
sys.exit(unittest.main())
您可以根据自己的具体需要调整上面的示例。您可以使用logging.handlers.MemoryHandler
来代替TestHandler
,然后询问缓冲记录中的特定条件。在这种情况下,由于您只是在测试格式化的输出,我使用了上面的方法来说明这一点。