From 9e7c3e99eb61328a85a3250860b49d7f73b8f7bd Mon Sep 17 00:00:00 2001 From: Doug Hellmann Date: Thu, 11 Jun 2015 18:46:29 +0000 Subject: [PATCH] Create CaptureOutput fixture Add a fixture for controlling whether or not stdout and stderr are captured as the test runs. Blueprint oslotest-refactor-test-base-class Change-Id: Ifa8d991c1a8e3ec643e5350d09fcb3895ac8378e --- doc/source/api.rst | 6 +++++ oslotest/base.py | 8 ++---- oslotest/output.py | 55 +++++++++++++++++++++++++++++++++++++++ tests/unit/test_base.py | 16 ++++++++++++ tests/unit/test_output.py | 43 ++++++++++++++++++++++++++++++ 5 files changed, 122 insertions(+), 6 deletions(-) create mode 100644 oslotest/output.py create mode 100644 tests/unit/test_output.py diff --git a/doc/source/api.rst b/doc/source/api.rst index 8fabfff..c9e9572 100644 --- a/doc/source/api.rst +++ b/doc/source/api.rst @@ -23,6 +23,12 @@ oslotest.moxstubout .. automodule:: oslotest.moxstubout :members: +oslotest.output +=================== + +.. automodule:: oslotest.output + :members: + oslotest.timeout ================ diff --git a/oslotest/base.py b/oslotest/base.py index 8ed270c..13e3add 100644 --- a/oslotest/base.py +++ b/oslotest/base.py @@ -20,6 +20,7 @@ import os import tempfile import fixtures +from oslotest import output from oslotest import timeout import six @@ -101,12 +102,7 @@ class BaseTestCase(testtools.TestCase): self.useFixture(timeout.Timeout()) def _fake_output(self): - if os.environ.get('OS_STDOUT_CAPTURE') in _TRUE_VALUES: - stdout = self.useFixture(fixtures.StringStream('stdout')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) - if os.environ.get('OS_STDERR_CAPTURE') in _TRUE_VALUES: - stderr = self.useFixture(fixtures.StringStream('stderr')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) + self.output_fixture = self.useFixture(output.CaptureOutput()) def _fake_logs(self): level = None diff --git a/oslotest/output.py b/oslotest/output.py new file mode 100644 index 0000000..2ba8e13 --- /dev/null +++ b/oslotest/output.py @@ -0,0 +1,55 @@ +# 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 os + +import fixtures + +_TRUE_VALUES = ('True', 'true', '1', 'yes') + + +class CaptureOutput(fixtures.Fixture): + """Optionally capture the output streams. + + The behavior is managed through two environment variables. If + ``OS_STDOUT_CAPTURE`` is true then stdout is captured and if + ``OS_STDERR_CAPTURE`` is true then stderr is captured. + + "True" values include ``True``, ``true``, ``1``, and ``yes``. + + .. py:attribute:: stdout + + The ``stream`` attribute from a :class:`StringStream` instance + replacing stdout. + + .. py:attribute:: stderr + + The ``stream`` attribute from a :class:`StringStream` instance + replacing stderr. + + """ + + def __init__(self): + super(CaptureOutput, self).__init__() + self.stdout = None + self.stderr = None + + def setUp(self): + super(CaptureOutput, self).setUp() + if os.environ.get('OS_STDOUT_CAPTURE') in _TRUE_VALUES: + self._stdout_fixture = fixtures.StringStream('stdout') + self.stdout = self.useFixture(self._stdout_fixture).stream + self.useFixture(fixtures.MonkeyPatch('sys.stdout', self.stdout)) + if os.environ.get('OS_STDERR_CAPTURE') in _TRUE_VALUES: + self._stderr_fixture = fixtures.StringStream('stderr') + self.stderr = self.useFixture(self._stderr_fixture).stream + self.useFixture(fixtures.MonkeyPatch('sys.stderr', self.stderr)) diff --git a/tests/unit/test_base.py b/tests/unit/test_base.py index 96f83fd..2d12067 100644 --- a/tests/unit/test_base.py +++ b/tests/unit/test_base.py @@ -99,6 +99,22 @@ class TestBaseTestCase(testtools.TestCase): # check that mock patches are cleaned up self.assertEqual(obj.value, obj.backup) + @mock.patch('os.environ') + def test_capture_output_disabled(self, mock_env): + mock_env.get.return_value = '' + tc = self.FakeTestCase("test_fake_test") + tc.setUp() + self.assertIs(None, tc.output_fixture.stdout) + self.assertIs(None, tc.output_fixture.stderr) + + @mock.patch('os.environ') + def test_enabled(self, mock_env): + mock_env.get.return_value = 'True' + tc = self.FakeTestCase("test_fake_test") + tc.setUp() + self.assertIsNot(None, tc.output_fixture.stdout) + self.assertIsNot(None, tc.output_fixture.stderr) + class TestManualMock(base.BaseTestCase): diff --git a/tests/unit/test_output.py b/tests/unit/test_output.py new file mode 100644 index 0000000..918c27f --- /dev/null +++ b/tests/unit/test_output.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- + +# 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 sys + +from oslotest import output + +import mock +import testtools + + +class CaptureOutputTest(testtools.TestCase): + + @mock.patch('os.environ') + def test_disabled(self, mock_env): + mock_env.get.return_value = '' + f = output.CaptureOutput() + f.setUp() + self.assertIs(None, f.stdout) + self.assertIs(None, f.stderr) + self.assertIsNot(sys.stdout, f.stdout) + self.assertIsNot(sys.stderr, f.stderr) + + @mock.patch('os.environ') + def test_enabled(self, mock_env): + mock_env.get.return_value = 'True' + f = output.CaptureOutput() + f.setUp() + self.assertIsNot(None, f.stdout) + self.assertIsNot(None, f.stderr) + self.assertIs(sys.stdout, f.stdout) + self.assertIs(sys.stderr, f.stderr)