diff --git a/docs/source/fixtures.rst b/docs/source/fixtures.rst index ba51a56..03c4d5c 100644 --- a/docs/source/fixtures.rst +++ b/docs/source/fixtures.rst @@ -31,3 +31,9 @@ If a fixture raises ``unittest.case.SkipTest`` during This makes it possible to skip the tests if some optional configuration (such as a particular type of database) is not available. + +If an exception is raised while a fixture is being used, information +about the exception will be stored on the fixture so that the +``stop_fixture`` method can decide if the exception should change how +the fixture should clean up. The exception information can be found on +``exc_type``, ``exc_value`` and ``traceback`` method attributes. diff --git a/gabbi/fixture.py b/gabbi/fixture.py index 340002e..e69a392 100644 --- a/gabbi/fixture.py +++ b/gabbi/fixture.py @@ -42,10 +42,18 @@ class GabbiFixture(object): Otherwise exception handling will not work properly. """ + def __init__(self): + self.exc_type = None + self.exc_value = None + self.traceback = None + def __enter__(self): self.start_fixture() def __exit__(self, exc_type, value, traceback): + self.exc_type = exc_type + self.exc_value = value + self.traceback = traceback self.stop_fixture() def start_fixture(self): diff --git a/gabbi/tests/__init__.py b/gabbi/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gabbi/tests/test_fixtures.py b/gabbi/tests/test_fixtures.py new file mode 100644 index 0000000..14ec9b0 --- /dev/null +++ b/gabbi/tests/test_fixtures.py @@ -0,0 +1,47 @@ +""" +Use mocks to confirm that fixtures operate as context managers. +""" + +import mock +import testtools + +from gabbi import fixture + + +class FakeFixture(fixture.GabbiFixture): + + def __init__(self, mock): + super(FakeFixture, self).__init__() + self.mock = mock + + def start_fixture(self): + self.mock.start() + + def stop_fixture(self): + if self.exc_type: + self.mock.handle(self.exc_type) + self.mock.stop() + + +class FixtureTest(testtools.TestCase): + + def setUp(self): + super(FixtureTest, self).setUp() + self.magic = mock.MagicMock(['start', 'stop', 'handle']) + + def test_fixture_starts_and_stop(self): + with FakeFixture(self.magic): + pass + self.magic.start.assert_called_once_with() + self.magic.stop.assert_called_once_with() + + def test_fixture_informs_on_exception(self): + """Test that the stop fixture is passed exception info.""" + try: + with FakeFixture(self.magic): + raise ValueError() + except ValueError: + pass + self.magic.start.assert_called_once_with() + self.magic.stop.assert_called_once_with() + self.magic.handle.assert_called_once_with(ValueError) diff --git a/test-requirements.txt b/test-requirements.txt index e86c9fc..68fc076 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,3 +1,4 @@ +mock tox testrepository coverage