Implement shared fixture base class.

Change-Id: I98919acb54bcd112bf633615391876175d819a8c
This commit is contained in:
Federico Ressi 2019-03-04 11:04:43 +01:00
parent 0d7fe979c2
commit 19a8039f11
3 changed files with 191 additions and 43 deletions

View File

@ -12,7 +12,7 @@
# under the License.
from __future__ import absolute_import
from tobiko.common.managers import fixture as fixture_manager
from tobiko.common.managers import fixture
from tobiko.common.managers import testcase as testcase_manager
from tobiko.common.managers import loader as loader_manager
@ -22,12 +22,16 @@ load_module = loader_manager.load_module
discover_testcases = testcase_manager.discover_testcases
is_fixture = fixture_manager.is_fixture
get_fixture = fixture_manager.get_fixture
get_fixture_name = fixture_manager.get_fixture_name
setup_fixture = fixture_manager.setup_fixture
cleanup_fixture = fixture_manager.cleanup_fixture
list_required_fixtures = fixture_manager.list_required_fixtures
iter_required_fixtures = fixture_manager.iter_required_fixtures
setup_required_fixtures = fixture_manager.setup_required_fixtures
cleanup_required_fixtures = fixture_manager.cleanup_required_fixtures
is_fixture = fixture.is_fixture
get_fixture = fixture.get_fixture
get_fixture_name = fixture.get_fixture_name
remove_fixture = fixture.remove_fixture
setup_fixture = fixture.setup_fixture
setup_shared_fixture = fixture.setup_shared_fixture
cleanup_fixture = fixture.cleanup_fixture
cleanup_shared_fixture = fixture.cleanup_shared_fixture
list_required_fixtures = fixture.list_required_fixtures
iter_required_fixtures = fixture.iter_required_fixtures
setup_required_fixtures = fixture.setup_required_fixtures
cleanup_required_fixtures = fixture.cleanup_required_fixtures
SharedFixture = fixture.SharedFixture

View File

@ -36,12 +36,33 @@ def get_fixture_name(obj):
return get_fixture(obj).__tobiko_fixture_name__
def remove_fixture(obj, manager=None):
manager = manager or FIXTURES
return manager.remove_fixture(obj)
def setup_fixture(obj, manager=None):
get_fixture(obj, manager=manager).setUp()
fixture = get_fixture(obj, manager=manager)
fixture.setUp()
return fixture
def setup_shared_fixture(obj, manager=None):
fixture = get_fixture(obj, manager=manager)
fixture.setup_shared_fixture()
return fixture
def cleanup_fixture(obj, manager=None):
get_fixture(obj, manager=manager).cleanUp()
fixture = get_fixture(obj, manager=manager)
fixture.cleanUp()
return fixture
def cleanup_shared_fixture(obj, manager=None):
fixture = get_fixture(obj, manager=manager)
fixture.cleanup_shared_fixture()
return fixture
def iter_required_fixtures(objects):
@ -80,15 +101,14 @@ def list_required_fixtures(objects):
def setup_required_fixtures(objects, manager=None):
manager = manager or FIXTURES
for _fixture in iter_required_fixtures(objects=objects):
manager.get_fixture(_fixture).setUp()
for name in iter_required_fixtures(objects=objects):
yield setup_fixture(name, manager=manager)
def cleanup_required_fixtures(objects, manager=None):
manager = manager or FIXTURES
for _fixture in iter_required_fixtures(objects=objects):
manager.get_fixture(_fixture).cleanUp()
for name in iter_required_fixtures(objects=objects):
yield cleanup_fixture(name, manager=manager)
def init_fixture(obj, name):
@ -168,5 +188,52 @@ class FixtureManager(object):
assert isinstance(fixture, fixtures.Fixture)
return fixture
def remove_fixture(self, obj):
name = get_object_name(obj)
return self.fixtures.pop(name, None)
FIXTURES = FixtureManager()
class SharedFixture(fixtures.Fixture):
"""Base class for fixtures intended to be shared between multiple tests
Make sure that fixture setUp method can be called more than once, but
actually executing _setUp method only the first time. This allows the
fixture to be passed to useFixture methods multiple times without caring
about if has already been used before.
Fixture set up can anyway be forced by calling 'setup_shared_fixture'
method.
Because cleanup policy in a shared fixture is different from a common
fixture, cleanUp method simply doesn't nothing.
Actual fixture cleanup is executed by calling
cleanup_shared_fixture method.
"""
_setup_executed = False
def __init__(self):
self._clear_cleanups()
def setUp(self):
"""Executes _setUp method only the first time setUp is called"""
if not self._setup_executed:
self.setup_shared_fixture()
def setup_shared_fixture(self):
"""Forces execution of _setUp method"""
super(SharedFixture, self).setUp()
self._setup_executed = True
def cleanUp(self, raise_first=True):
"""Id doesn't nothing"""
def cleanup_shared_fixture(self, raise_first=True):
"""Executes registered cleanups"""
super(SharedFixture, self).cleanUp(raise_first)
self._setup_executed = False

View File

@ -17,29 +17,47 @@ import fixtures
import mock
import tobiko
from tobiko.tests import base
from tobiko.tests import unit
class MyFixtureClass(fixtures.Fixture):
class MyFixture(fixtures.Fixture):
pass
MY_FIXTURE_NAME = __name__ + '.' + MyFixtureClass.__name__
MY_FIXTURE_NAME = __name__ + '.' + MyFixture.__name__
class FixtureTypeTest(base.TobikoTest):
class FixtureManagerTest(unit.TobikoUnitTest):
def setUp(self):
super(FixtureManagerTest, self).setUp()
tobiko.remove_fixture(MyFixture)
def test_get_fixture_by_name(self):
self._test_get_fixture(MY_FIXTURE_NAME, fixture_type=MyFixtureClass)
self._test_get_fixture(MY_FIXTURE_NAME, fixture_type=MyFixture)
def test_get_fixture_by_type(self):
self._test_get_fixture(MyFixtureClass, fixture_type=MyFixtureClass)
self._test_get_fixture(MyFixture, fixture_type=MyFixture)
def _test_get_fixture(self, obj, fixture_type):
fixture = tobiko.get_fixture(obj)
self.assertIsInstance(fixture, fixture_type)
self.assertIs(fixture, tobiko.get_fixture(obj))
def test_remove_fixture_by_name(self):
self._test_remove_fixture(MY_FIXTURE_NAME)
def test_remove_fixture_by_type(self):
self._test_remove_fixture(MyFixture)
def _test_remove_fixture(self, obj):
fixture = tobiko.get_fixture(obj)
result = tobiko.remove_fixture(obj)
self.assertIs(fixture, result)
self.assertIsNot(fixture, tobiko.get_fixture(obj))
def test_get_name(self):
fixture = tobiko.get_fixture(MY_FIXTURE_NAME)
result = tobiko.get_fixture_name(fixture)
@ -49,42 +67,42 @@ class FixtureTypeTest(base.TobikoTest):
self._test_setup_fixture(MY_FIXTURE_NAME)
def test_setup_fixture_by_type(self):
self._test_setup_fixture(MyFixtureClass)
self._test_setup_fixture(MyFixture)
def _test_setup_fixture(self, obj):
fixture = tobiko.get_fixture(obj)
fixture.setUp = setup = mock.MagicMock()
setup = self.patch('fixtures.Fixture.setUp')
tobiko.setup_fixture(obj)
result = tobiko.setup_fixture(obj)
setup.assert_called_once_with()
self.assertIs(tobiko.get_fixture(obj), result)
def test_cleanup_fixture_by_name(self):
self._test_cleanup_fixture(MY_FIXTURE_NAME)
def test_cleanup_fixture_by_type(self):
self._test_cleanup_fixture(MyFixtureClass)
self._test_cleanup_fixture(MyFixture)
def _test_cleanup_fixture(self, obj):
cleanup = mock.MagicMock()
fixture = tobiko.get_fixture(obj)
fixture.setUp()
fixture = tobiko.setup_fixture(obj)
fixture.addCleanup(cleanup)
tobiko.cleanup_fixture(obj)
result = tobiko.cleanup_fixture(obj)
cleanup.assert_called_once_with()
self.assertIs(tobiko.get_fixture(obj), result)
def test_list_required_fixtures_from_module(self):
result = tobiko.list_required_fixtures([__name__])
self.assertEqual([MY_FIXTURE_NAME], result)
self.assertEqual([MY_FIXTURE_NAME, MY_SHARED_FIXTURE_NAME], result)
def test_list_required_fixtures_from_testcase_type(self):
result = tobiko.list_required_fixtures([FixtureTypeTest])
result = tobiko.list_required_fixtures([FixtureManagerTest])
self.assertEqual([MY_FIXTURE_NAME], result)
def test_list_required_fixtures_from_fixture_type(self):
result = tobiko.list_required_fixtures([MyFixtureClass])
result = tobiko.list_required_fixtures([MyFixture])
self.assertEqual([MY_FIXTURE_NAME], result)
def test_list_required_fixtures_from_fixture_name(self):
@ -92,7 +110,7 @@ class FixtureTypeTest(base.TobikoTest):
self.assertEqual([MY_FIXTURE_NAME], result)
def test_list_required_fixtures_from_method(
self, fixture_type=MyFixtureClass):
self, fixture_type=MyFixture):
result = tobiko.list_required_fixtures([self.id()])
self.assertEqual([MY_FIXTURE_NAME], result)
self.assertIsInstance(tobiko.get_fixture(MY_FIXTURE_NAME),
@ -103,20 +121,79 @@ class FixtureTypeTest(base.TobikoTest):
result = tobiko.list_required_fixtures([fixture])
self.assertEqual([MY_FIXTURE_NAME], result)
def test_setup_required_fixtures(self, fixture_type=MyFixtureClass):
fixture = tobiko.get_fixture(fixture_type)
fixture.setUp = setup = mock.MagicMock()
def test_setup_required_fixtures(self, fixture_type=MyFixture):
setup = self.patch('fixtures.Fixture.setUp')
tobiko.setup_required_fixtures([self.id()])
result = list(tobiko.setup_required_fixtures([self.id()]))
setup.assert_called_once_with()
self.assertEqual([tobiko.get_fixture(fixture_type)], result)
def test_cleanup_required_fixtures(self, fixture_type=MyFixtureClass):
def test_cleanup_required_fixtures(self, fixture_type=MyFixture):
cleanup = mock.MagicMock()
fixture = tobiko.get_fixture(fixture_type)
fixture.setUp()
fixture = tobiko.setup_fixture(fixture_type)
fixture.addCleanup(cleanup)
tobiko.cleanup_required_fixtures([self.id()])
result = list(tobiko.cleanup_required_fixtures([self.id()]))
cleanup.assert_called_once_with()
self.assertEqual([tobiko.get_fixture(fixture_type)], result)
class MySharedFixture(tobiko.SharedFixture):
pass
MY_SHARED_FIXTURE_NAME = __name__ + '.' + MySharedFixture.__name__
class SharedFixtureTest(unit.TobikoUnitTest):
def setUp(self):
super(SharedFixtureTest, self).setUp()
tobiko.remove_fixture(MySharedFixture)
self.mock_setup = self.patch('fixtures.Fixture.setUp')
self.mock_cleanup = self.patch('fixtures.Fixture.cleanUp')
def test_initial_state(self):
self.mock_setup.assert_not_called()
self.mock_cleanup.assert_not_called()
def test_use_fixture(self):
self.addCleanup(self.mock_cleanup.assert_not_called)
fixture = tobiko.get_fixture(MySharedFixture)
self.useFixture(fixture)
self.mock_setup.assert_called_once_with()
self.useFixture(fixture)
self.mock_setup.assert_called_once_with()
def test_setup_fixture(self):
tobiko.setup_fixture(MySharedFixture)
tobiko.setup_fixture(MySharedFixture)
self.mock_setup.assert_called_once_with()
def test_cleanup_fixture(self):
tobiko.cleanup_fixture(MySharedFixture)
self.mock_cleanup.assert_not_called()
def test_setup_shared_fixture(self):
tobiko.setup_shared_fixture(MySharedFixture)
tobiko.setup_shared_fixture(MySharedFixture)
self.mock_setup.assert_has_calls([mock.call(), mock.call()])
def test_cleanup_shared_fixture(self):
tobiko.cleanup_shared_fixture(MySharedFixture)
self.mock_cleanup.assert_called_once()
def test_cleanup_shared_fixture_workflow(self):
tobiko.setup_fixture(MySharedFixture)
tobiko.setup_fixture(MySharedFixture)
self.mock_setup.assert_called_once_with()
tobiko.cleanup_shared_fixture(MySharedFixture)
self.mock_cleanup.assert_called_once()
tobiko.setup_fixture(MySharedFixture)
self.mock_setup.assert_has_calls([mock.call(), mock.call()])