summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS15
-rw-r--r--README15
-rw-r--r--lib/fixtures/__init__.py4
-rw-r--r--lib/fixtures/_fixtures/__init__.py2
-rw-r--r--lib/fixtures/_fixtures/detailstream.py43
-rw-r--r--lib/fixtures/_fixtures/logger.py13
-rw-r--r--lib/fixtures/tests/_fixtures/__init__.py1
-rw-r--r--lib/fixtures/tests/_fixtures/test_detailstream.py54
-rwxr-xr-xsetup.py3
9 files changed, 138 insertions, 12 deletions
diff --git a/NEWS b/NEWS
index e132091..4f82b24 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,18 @@ fixtures release notes
NEXT
~~~~
+CHANGES
+-------
+
+* ``FakeLogger`` has been split out into a ``LogHandler`` fixture that can
+ inject arbitrary handlers, giving more flexability. (Jonathan Lange)
+
+0.3.10
+~~~~~~
+
+New ``DetailStream`` fixture to add file-like object content to testtools
+details, cleanup logic factored out into a CallMany class.
+
CHANGES:
* Add ``join`` method to ``TempDir`` to more readily get paths relative
@@ -14,6 +26,9 @@ CHANGES:
* Factor out new ``CallMany`` class to isolate the cleanup logic.
(Robert Collins)
+* New ``DetailStream`` fixture to add file-like object content to testtools
+ details. This allows for easy capture of sys.stdout and sys.stderr for
+ example. (Clark Boylan)
0.3.9
~~~~~
diff --git a/README b/README
index be3a589..074a5cc 100644
--- a/README
+++ b/README
@@ -28,7 +28,7 @@ Dependencies
* Python 2.4+
This is the base language fixtures is written in and for.
-* testtools <https://launchpad.net/testtools> 0.9.12 or newer.
+* testtools <https://launchpad.net/testtools> 0.9.22 or newer.
testtools provides helpful glue functions for the details API used to report
information about a fixture (whether its used in a testing or production
environment).
@@ -266,6 +266,19 @@ In addition to the Fixture, FunctionFixture and MethodFixture classes fixtures
includes a number of precanned fixtures. The API docs for fixtures will list
the complete set of these, should the dcs be out of date or not to hand.
+DetailStream
+++++++++++++
+
+Trivial adapter to make a StringIO (though it may in future auto-spill to disk
+for large content) and expose that as a detail object, for automatic inclusion
+in test failure descriptions. Very useful in combination with MonkeyPatch.
+
+ >>> fixture = fixtures.DetailStream('stdout')
+ >>> fixture.setUp()
+ >>> with fixtures.MonkeyPatch('sys.stdout', fixture.stream):
+ ... pass
+ >>> fixture.cleanUp()
+
EnvironmentVariable
+++++++++++++++++++
diff --git a/lib/fixtures/__init__.py b/lib/fixtures/__init__.py
index 5863c52..1390ac8 100644
--- a/lib/fixtures/__init__.py
+++ b/lib/fixtures/__init__.py
@@ -36,9 +36,10 @@ Most users will want to look at TestWithFixtures and Fixture, to start with.
# established at this point, and setup.py will use a version of next-$(revno).
# If the releaselevel is 'final', then the tarball will be major.minor.micro.
# Otherwise it is major.minor.micro~$(revno).
-__version__ = (0, 3, 9, 'final', 0)
+__version__ = (0, 3, 10, 'final', 0)
__all__ = [
+ 'DetailStream',
'EnvironmentVariable',
'EnvironmentVariableFixture',
'FakeLogger',
@@ -68,6 +69,7 @@ from fixtures.fixture import (
MethodFixture,
)
from fixtures._fixtures import (
+ DetailStream,
EnvironmentVariable,
EnvironmentVariableFixture,
FakeLogger,
diff --git a/lib/fixtures/_fixtures/__init__.py b/lib/fixtures/_fixtures/__init__.py
index b61b010..e113e1e 100644
--- a/lib/fixtures/_fixtures/__init__.py
+++ b/lib/fixtures/_fixtures/__init__.py
@@ -17,6 +17,7 @@
"""Included fixtures."""
__all__ = [
+ 'DetailStream',
'EnvironmentVariable',
'EnvironmentVariableFixture',
'FakeLogger',
@@ -36,6 +37,7 @@ __all__ = [
]
+from fixtures._fixtures.detailstream import DetailStream
from fixtures._fixtures.environ import (
EnvironmentVariable,
EnvironmentVariableFixture,
diff --git a/lib/fixtures/_fixtures/detailstream.py b/lib/fixtures/_fixtures/detailstream.py
new file mode 100644
index 0000000..779ef18
--- /dev/null
+++ b/lib/fixtures/_fixtures/detailstream.py
@@ -0,0 +1,43 @@
+# fixtures: Fixtures with cleanups for testing and convenience.
+#
+# Copyright (c) 2012, Robert Collins <robertc@robertcollins.net>
+#
+# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
+# license at the users choice. A copy of both licenses are available in the
+# project source as Apache-2.0 and BSD. You may not use this file except in
+# compliance with one of these two licences.
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# license you chose for the specific language governing permissions and
+# limitations under that license.
+
+__all__ = [
+ 'DetailStream'
+ ]
+
+from cStringIO import StringIO
+
+from fixtures import Fixture
+import testtools
+
+
+class DetailStream(Fixture):
+ """Provide a file-like object and expose it as a detail.
+
+ :attr stream: The file-like object.
+ """
+
+ def __init__(self, detail_name):
+ """Create a DetailStream.
+
+ :param detail_name: Use this as the name of the stream.
+ """
+ self._detail_name = detail_name
+
+ def setUp(self):
+ super(DetailStream, self).setUp()
+ self.stream = StringIO()
+ self.addDetail(self._detail_name,
+ testtools.content.content_from_stream(self.stream, seek_offset=0))
diff --git a/lib/fixtures/_fixtures/logger.py b/lib/fixtures/_fixtures/logger.py
index 660e736..0beb170 100644
--- a/lib/fixtures/_fixtures/logger.py
+++ b/lib/fixtures/_fixtures/logger.py
@@ -14,12 +14,9 @@
# limitations under that license.
from logging import StreamHandler, getLogger, INFO, Formatter
-from cStringIO import StringIO
-
-from testtools.content import Content
-from testtools.content_type import UTF8_TEXT
from fixtures import Fixture
+from fixtures._fixtures.detailstream import DetailStream
__all__ = [
'FakeLogger',
@@ -55,8 +52,8 @@ class LogHandler(Fixture):
logger.setLevel(self._level)
if self._nuke_handlers:
for handler in reversed(logger.handlers):
- logger.removeHandler(handler)
self.addCleanup(logger.addHandler, handler)
+ logger.removeHandler(handler)
try:
logger.addHandler(self.handler)
finally:
@@ -91,10 +88,8 @@ class FakeLogger(Fixture):
def setUp(self):
super(FakeLogger, self).setUp()
- output = StringIO()
- self.addDetail(
- u"pythonlogging:'%s'" % self._name,
- Content(UTF8_TEXT, lambda: [output.getvalue()]))
+ name = u"pythonlogging:'%s'" % self._name
+ output = self.useFixture(DetailStream(name)).stream
self._output = output
handler = StreamHandler(output)
if self._format:
diff --git a/lib/fixtures/tests/_fixtures/__init__.py b/lib/fixtures/tests/_fixtures/__init__.py
index d8e0979..38987b9 100644
--- a/lib/fixtures/tests/_fixtures/__init__.py
+++ b/lib/fixtures/tests/_fixtures/__init__.py
@@ -15,6 +15,7 @@
def load_tests(loader, standard_tests, pattern):
test_modules = [
+ 'detailstream',
'environ',
'logger',
'monkeypatch',
diff --git a/lib/fixtures/tests/_fixtures/test_detailstream.py b/lib/fixtures/tests/_fixtures/test_detailstream.py
new file mode 100644
index 0000000..9df351d
--- /dev/null
+++ b/lib/fixtures/tests/_fixtures/test_detailstream.py
@@ -0,0 +1,54 @@
+# fixtures: Fixtures with cleanups for testing and convenience.
+#
+# Copyright (c) 2012, Robert Collins <robertc@robertcollins.net>
+#
+# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
+# license at the users choice. A copy of both licenses are available in the
+# project source as Apache-2.0 and BSD. You may not use this file except in
+# compliance with one of these two licences.
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# license you chose for the specific language governing permissions and
+# limitations under that license.
+
+from testtools import TestCase
+
+from fixtures import DetailStream
+
+
+class DetailStreamTest(TestCase):
+
+ def test_empty_detail_stream(self):
+ detail_name = 'test'
+ fixture = DetailStream(detail_name)
+ with fixture:
+ content = fixture.getDetails()[detail_name]
+ self.assertEqual("", content.as_text())
+
+ def test_stream_content_in_details(self):
+ detail_name = 'test'
+ fixture = DetailStream(detail_name)
+ with fixture:
+ stream = fixture.stream
+ content = fixture.getDetails()[detail_name]
+ # Output after getDetails is called is included.
+ stream.write("testing 1 2 3")
+ self.assertEqual("testing 1 2 3", content.as_text())
+
+ def test_stream_content_reset(self):
+ detail_name = 'test'
+ fixture = DetailStream(detail_name)
+ with fixture:
+ stream = fixture.stream
+ content = fixture.getDetails()[detail_name]
+ stream.write("testing 1 2 3")
+ with fixture:
+ # The old content object returns the old usage
+ self.assertEqual("testing 1 2 3", content.as_text())
+ content = fixture.getDetails()[detail_name]
+ # A new fixture returns the new output:
+ stream = fixture.stream
+ stream.write("1 2 3 testing")
+ self.assertEqual("1 2 3 testing", content.as_text())
diff --git a/setup.py b/setup.py
index 86f64f4..cfe9031 100755
--- a/setup.py
+++ b/setup.py
@@ -6,8 +6,9 @@ import os.path
description = file(os.path.join(os.path.dirname(__file__), 'README'), 'rb').read()
setup(name="fixtures",
- version="0.3.9",
+ version="0.3.10",
description="Fixtures, reusable state for writing clean tests and more.",
+ keywords="fixture fixtures unittest contextmanager",
long_description=description,
maintainer="Robert Collins",
maintainer_email="robertc@robertcollins.net",