Extra logging functionality for Flask applications
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

151 lines
4.5 KiB

# -*- coding: utf-8 -*-
"""Unit tests for Flask-Logging-Extras
"""
import logging
from logging.config import dictConfig
import sys
from unittest import TestCase
from flask import Flask, Blueprint, current_app
import flask_logging_extras
class ListHandler(logging.StreamHandler):
def __init__(self, *args, **kwargs):
super(ListHandler, self).__init__(*args, **kwargs)
self.logs = []
def emit(self, record):
try:
msg = self.format(record)
except (KeyError, IndexError) as exc:
msg = (exc.__class__.__name__, str(exc))
self.logs.append(msg)
def configure_loggers(extra_var):
dictConfig({
'version': 1,
'disable_existing_loggers': True,
'formatters': {
'selftest': {
'class': 'flask_logging_extras.FlaskExtraLoggerFormatter',
'format': '%(message)s %({extra_var})s'.format(extra_var=extra_var),
},
},
'handlers': {
'selftest': {
'class': 'test_logger_keywords.ListHandler',
'formatter': 'selftest',
},
},
'loggers': {
'selftest': {
'handlers': ['selftest'],
'level': 'INFO',
},
},
})
formatter = flask_logging_extras.FlaskExtraLoggerFormatter(
fmt='%(message)s %({extra_var})s'.format(extra_var=extra_var))
logger = logging.getLogger('selftest')
handlers = [handler for handler in logger.handlers if isinstance(handler, ListHandler)]
handler = handlers[0]
# TODO: Why doesn’t this happen automatically in Python 2.7?
handler.setFormatter(formatter)
return logger, handler
class LoggerKeywordsTestCase(TestCase):
def setUp(self):
self.logger, self.handler = configure_loggers('extra_keyword')
self.app = Flask('test_app')
self.app.config['FLASK_LOGGING_EXTRAS_KEYWORDS'] = {
'extra_keyword': 'placeholder',
}
# Make sure we don’t try to log the current blueprint for this test case
self.app.config['FLASK_LOGGING_EXTRAS_BLUEPRINT'] = (None, '', '')
def test_keywords_no_app_ctx(self):
"""With the current formatter, the last log line must be a just the message
"""
self.logger.info('message')
self.assertIn(('KeyError', "'extra_keyword'"), self.handler.logs)
def test_keywords_app_ctx_assign_value(self):
"""If we don’t register 'extra_keyword' in the app config, we get a
# KeyError. We set logging.raiseExceptions to False here; the
# reason is that this doesn’t mean an actual exception is raised,
# but our TestingStreamHandler does that for us (which we need for
# testing purposes)
"""
with self.app.app_context():
self.logger.info('message', extra=dict(extra_keyword='test'))
self.assertIn('message test', self.handler.logs)
def test_keywords_app_ctx_no_value(self):
"""If we don’t provide a value for a registered extra keyword, the
# string "<unset>" will be assigned.
"""
with self.app.app_context():
self.logger.info('message')
self.assertIn('message placeholder', self.handler.logs)
class LoggerBlueprintTestCase(TestCase):
def setUp(self):
# Register our logger class
app = Flask('test_app')
self.app = app
app.config['FLASK_LOGGING_EXTRAS_BLUEPRINT'] = ('bp', '<app>', '<norequest>')
configure_loggers('bp')
self.logger = logging.getLogger('selftest')
handlers = [handler for handler in self.logger.handlers if isinstance(handler, ListHandler)]
self.handler = handlers[0]
bp = Blueprint('test_blueprint', 'test_bp')
@app.route('/app')
def route_1():
self.logger.info('Message')
return ''
@bp.route('/blueprint')
def route_2():
self.logger.info('Message')
return ''
app.register_blueprint(bp)
self.client = app.test_client()
def test_blueprint_log_no_blueprint(self):
self.client.get('/app')
self.assertIn('Message <app>', self.handler.logs)
def test_blueprint_log_blueprint(self):
self.client.get('/blueprint')
self.assertIn('Message test_blueprint', self.handler.logs)
def test_blueprint_log_no_request(self):
with self.app.app_context():
self.logger.info('Message')
self.assertIn('Message <norequest>', self.handler.logs)