diff --git a/tobiko/__init__.py b/tobiko/__init__.py index 57c0ea8be..77d2939b3 100644 --- a/tobiko/__init__.py +++ b/tobiko/__init__.py @@ -16,6 +16,7 @@ from __future__ import absolute_import from tobiko.common import _asserts from tobiko.common import _exception from tobiko.common import _fixture +from tobiko.common import _logging from tobiko.common.managers import testcase as testcase_manager from tobiko.common.managers import loader as loader_manager from tobiko.common import _select @@ -45,6 +46,9 @@ list_required_fixtures = _fixture.list_required_fixtures SharedFixture = _fixture.SharedFixture FixtureManager = _fixture.FixtureManager +CaptureLogTest = _logging.CaptureLogTest +CaptureLogFixture = _logging.CaptureLogFixture + load_object = loader_manager.load_object load_module = loader_manager.load_module diff --git a/tobiko/common/_logging.py b/tobiko/common/_logging.py new file mode 100644 index 000000000..b0944a47f --- /dev/null +++ b/tobiko/common/_logging.py @@ -0,0 +1,87 @@ +# Copyright 2019 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +from __future__ import absolute_import + +import logging + +from oslo_log import log + +import testtools +from testtools import content + +from tobiko.common import _fixture + + +LOG = log.getLogger(__name__) + + +class CaptureLogFixture(_fixture.SharedFixture): + + level = None + logger = logging.root + handler = None + + def __init__(self, logger=None, level=None): + super(CaptureLogFixture, self).__init__() + if logger: + self.logger = logger + if level: + self.level = level + + def setup_fixture(self): + self.handler = handler = CaptureLogHandler(level=self.level) + self.logger.addHandler(handler) + self.addCleanup(self.logger.removeHandler, handler) + + def getDetails(self): + if self.handler: + return {'log': self.handler.content} + else: + return {} + + +class CaptureLogHandler(logging.Handler): + + def __init__(self, level=None): + if level is None: + from tobiko import config + CONF = config.CONF + if CONF.tobiko.debug: + level = logging.DEBUG + else: + level = logging.INFO + super(CaptureLogHandler, self).__init__(level) + self.records = [] + + def emit(self, record): + self.records.append(record) + + @property + def content(self): + return content.Content(content.UTF8_TEXT, self.format_all) + + def format_all(self): + for record in self.records: + yield (self.format(record) + '\n').encode() + + +class CaptureLogTest(testtools.TestCase): + + capture_log_level = logging.DEBUG + capture_log_logger = logging.root + + def setUp(self): + self.useFixture(CaptureLogFixture(level=self.capture_log_level, + logger=self.capture_log_logger)) + super(CaptureLogTest, self).setUp() diff --git a/tobiko/config.py b/tobiko/config.py index dab54e9d3..9b67a9f24 100644 --- a/tobiko/config.py +++ b/tobiko/config.py @@ -20,9 +20,12 @@ import os from oslo_config import cfg from oslo_log import log +import testtools +from testtools import monkey import tobiko + LOG = log.getLogger(__name__) CONFIG_MODULES = ['tobiko.openstack.glance.config', @@ -47,6 +50,14 @@ def _iter_config_dirs(): CONFIG_DIRS = list(_iter_config_dirs()) +LOGGING_CONF_GROUP_NAME = "logging" + +LOGGING_OPTIONS = [ + cfg.BoolOpt('capture_log', + default=True, + help="Whenever to capture LOG during test case excecution"), +] + HTTP_CONF_GROUP_NAME = "http" HTTP_OPTIONS = [ @@ -88,9 +99,15 @@ class GlobalConfig(object): CONF = GlobalConfig() +class InitConfigFixture(tobiko.SharedFixture): + + def setup_fixture(self): + init_tobiko_config() + init_environ_config() + + def init_config(): - init_tobiko_config() - init_environ_config() + tobiko.setup_fixture(InitConfigFixture) def init_tobiko_config(default_config_dirs=None, product_name='tobiko', @@ -113,6 +130,9 @@ def init_tobiko_config(default_config_dirs=None, product_name='tobiko', def register_tobiko_options(conf): + conf.register_opts( + group=cfg.OptGroup(LOGGING_CONF_GROUP_NAME), opts=LOGGING_OPTIONS) + conf.register_opts( group=cfg.OptGroup(HTTP_CONF_GROUP_NAME), opts=HTTP_OPTIONS) @@ -151,6 +171,8 @@ def setup_tobiko_config(conf): warnings_logger.logger.setLevel(log.ERROR) tobiko.setup_fixture(HttpProxyFixture) + if conf.logging.capture_log: + monkey.patch(testtools, 'TestCase', tobiko.CaptureLogTest) for module_name in CONFIG_MODULES: module = importlib.import_module(module_name) diff --git a/tobiko/tests/unit/__init__.py b/tobiko/tests/unit/__init__.py index 5d91f4799..22c7b6332 100644 --- a/tobiko/tests/unit/__init__.py +++ b/tobiko/tests/unit/__init__.py @@ -1,3 +1,4 @@ +# Copyright 2019 Red Hat # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/tobiko/tests/unit/_case.py b/tobiko/tests/unit/_case.py index 2e8069598..60f44655e 100644 --- a/tobiko/tests/unit/_case.py +++ b/tobiko/tests/unit/_case.py @@ -1,3 +1,4 @@ +# Copyright 2019 Red Hat # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/tobiko/tests/unit/_patch.py b/tobiko/tests/unit/_patch.py index ae8fa1fda..3961a66ba 100644 --- a/tobiko/tests/unit/_patch.py +++ b/tobiko/tests/unit/_patch.py @@ -1,3 +1,4 @@ +# Copyright 2019 Red Hat # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/tobiko/tests/unit/test_logging.py b/tobiko/tests/unit/test_logging.py new file mode 100644 index 000000000..4a4a4aa22 --- /dev/null +++ b/tobiko/tests/unit/test_logging.py @@ -0,0 +1,32 @@ +# Copyright (c) 2019 Red Hat +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +from __future__ import absolute_import + +from oslo_log import log + +import tobiko +from tobiko.tests import unit + + +LOG = log.getLogger(__name__) + + +class CapureLogTest(unit.TobikoUnitTest): + + def test_capture_log_content(self): + with tobiko.CaptureLogFixture() as capture: + LOG.warning('Some debug line') + content = capture.getDetails()['log'] + self.assertEqual('Some debug line\n', content.as_text())