Create ConfigureLogging fixture

Add a fixture for controlling how logging is configured.

Blueprint oslotest-refactor-test-base-class

Change-Id: I5f3f353781a6036f21c4cdb577792bceab242ea4
This commit is contained in:
Doug Hellmann 2015-06-11 19:23:44 +00:00
parent 9e7c3e99eb
commit 5f63439ee7
5 changed files with 147 additions and 26 deletions

View File

@ -10,6 +10,13 @@ oslotest.base
.. autoclass:: oslotest.base.BaseTestCase
:members:
oslotest.log
============
.. automodule:: oslotest.log
:members:
:special-members:
oslotest.mockpatch
==================

View File

@ -15,11 +15,11 @@
"""Common utilities used in testing"""
import logging
import os
import tempfile
import fixtures
from oslotest import log
from oslotest import output
from oslotest import timeout
@ -105,20 +105,7 @@ class BaseTestCase(testtools.TestCase):
self.output_fixture = self.useFixture(output.CaptureOutput())
def _fake_logs(self):
level = None
if os.environ.get('OS_DEBUG') in _TRUE_VALUES:
level = logging.DEBUG
capture_logs = os.environ.get('OS_LOG_CAPTURE') in _TRUE_VALUES
if capture_logs:
self.logger = self.useFixture(
fixtures.FakeLogger(
format=_LOG_FORMAT,
level=level,
nuke_handlers=capture_logs,
)
)
else:
logging.basicConfig(format=_LOG_FORMAT, level=level)
self.log_fixture = self.useFixture(log.ConfigureLogging())
def create_tempfiles(self, files, ext='.conf', default_encoding='utf-8'):
"""Safely create temporary files.

66
oslotest/log.py Normal file
View File

@ -0,0 +1,66 @@
# 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.
import logging
import os
import fixtures
_TRUE_VALUES = ('True', 'true', '1', 'yes')
class ConfigureLogging(fixtures.Fixture):
"""Configure logging.
The behavior is managed through two environment variables. If
``OS_DEBUG`` is true then the logging level is set to debug. If
``OS_LOG_CAPTURE`` is true a FakeLogger is configured.
"True" values include ``True``, ``true``, ``1``, and ``yes``.
.. py:attribute:: logger
The logger fixture, if it is created.
.. py:attribute:: level
``logging.DEBUG`` if debug logging is enabled, otherwise
``None``.
:param format: The logging format string to use.
"""
DEFAULT_FORMAT = "%(levelname)8s [%(name)s] %(message)s"
"""Default log format"""
def __init__(self, format=DEFAULT_FORMAT):
super(ConfigureLogging, self).__init__()
self._format = format
self.level = None
if os.environ.get('OS_DEBUG') in _TRUE_VALUES:
self.level = logging.DEBUG
self.capture_logs = os.environ.get('OS_LOG_CAPTURE') in _TRUE_VALUES
self.logger = None
def setUp(self):
super(ConfigureLogging, self).setUp()
if self.capture_logs:
self.logger = self.useFixture(
fixtures.FakeLogger(
format=self._format,
level=self.level,
nuke_handlers=True,
)
)
else:
logging.basicConfig(format=self._format, level=self.level)

View File

@ -44,24 +44,24 @@ class TestBaseTestCase(testtools.TestCase):
self.assertEqual(fixture_mock.call_count, 1)
@mock.patch('os.environ.get')
@mock.patch.object(FakeTestCase, 'useFixture')
def test_fake_logs_default(self, fixture_mock, env_get_mock):
def test_fake_logs_default(self, env_get_mock):
# without debug and log capture
env_get_mock.side_effect = lambda value: {'OS_DEBUG': 0,
'OS_LOG_CAPTURE': 0}[value]
env_get_mock.side_effect = lambda value, default=None: {
'OS_DEBUG': 0, 'OS_LOG_CAPTURE': 0}.get(value, default)
tc = self.FakeTestCase("test_fake_test")
tc._fake_logs()
tc.setUp()
env_get_mock.assert_any_call('OS_LOG_CAPTURE')
env_get_mock.assert_any_calls('OS_DEBUG')
self.assertEqual(fixture_mock.call_count, 0)
self.assertFalse(tc.log_fixture.capture_logs)
self.assertIsNone(tc.log_fixture.logger)
@mock.patch('os.environ.get')
@mock.patch('logging.basicConfig')
def test_fake_logs_with_debug(self, basic_logger_mock, env_get_mock):
env_get_mock.side_effect = lambda value: {'OS_DEBUG': 'True',
'OS_LOG_CAPTURE': 0}[value]
env_get_mock.side_effect = lambda value, default=None: {
'OS_DEBUG': 'True', 'OS_LOG_CAPTURE': 0}.get(value, default)
tc = self.FakeTestCase("test_fake_test")
tc._fake_logs()
tc.setUp()
env_get_mock.assert_any_call('OS_LOG_CAPTURE')
env_get_mock.assert_any_calls('OS_DEBUG')
basic_logger_mock.assert_called_once_with(format=base._LOG_FORMAT,
@ -74,10 +74,10 @@ class TestBaseTestCase(testtools.TestCase):
'OS_LOG_CAPTURE': 'True'
}[value]
tc = self.FakeTestCase("test_fake_test")
tc._fake_logs()
tc.setUp()
env_get_mock.assert_any_call('OS_LOG_CAPTURE')
env_get_mock.assert_any_calls('OS_DEBUG')
self.assertEqual(fixture_mock.call_count, 1)
self.assertEqual(fixture_mock.call_count, 5)
def test_mock_patch_cleanup_on_teardown(self):
# create an object and save its reference

61
tests/unit/test_log.py Normal file
View File

@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
# Copyright 2014 Deutsche Telekom AG
#
# 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.
import logging
from six.moves import mock
import testtools
from oslotest import log
class ConfigureLoggingTestCase(testtools.TestCase):
@mock.patch('os.environ.get')
def test_fake_logs_default(self, env_get_mock):
# without debug and log capture
env_get_mock.side_effect = lambda value, default=None: {
'OS_DEBUG': 0, 'OS_LOG_CAPTURE': 0}.get(value, default)
f = log.ConfigureLogging()
f.setUp()
env_get_mock.assert_any_call('OS_LOG_CAPTURE')
env_get_mock.assert_any_calls('OS_DEBUG')
self.assertFalse(f.capture_logs)
self.assertIsNone(f.logger)
@mock.patch('os.environ.get')
@mock.patch('logging.basicConfig')
def test_fake_logs_with_debug(self, basic_logger_mock, env_get_mock):
env_get_mock.side_effect = lambda value, default=None: {
'OS_DEBUG': 'True', 'OS_LOG_CAPTURE': 0}.get(value, default)
f = log.ConfigureLogging()
f.setUp()
env_get_mock.assert_any_call('OS_LOG_CAPTURE')
env_get_mock.assert_any_calls('OS_DEBUG')
basic_logger_mock.assert_called_once_with(
format=log.ConfigureLogging.DEFAULT_FORMAT,
level=logging.DEBUG)
@mock.patch('os.environ.get')
def test_fake_logs_with_log_capture(self, env_get_mock):
env_get_mock.side_effect = lambda value: {'OS_DEBUG': 0,
'OS_LOG_CAPTURE': 'True'
}[value]
f = log.ConfigureLogging()
f.setUp()
env_get_mock.assert_any_call('OS_LOG_CAPTURE')
env_get_mock.assert_any_calls('OS_DEBUG')
self.assertIsNotNone(f.logger)