Implement shared fixture base class.
Change-Id: I98919acb54bcd112bf633615391876175d819a8c
This commit is contained in:
parent
0d7fe979c2
commit
19a8039f11
|
@ -12,7 +12,7 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
from __future__ import absolute_import
|
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 testcase as testcase_manager
|
||||||
from tobiko.common.managers import loader as loader_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
|
discover_testcases = testcase_manager.discover_testcases
|
||||||
|
|
||||||
is_fixture = fixture_manager.is_fixture
|
is_fixture = fixture.is_fixture
|
||||||
get_fixture = fixture_manager.get_fixture
|
get_fixture = fixture.get_fixture
|
||||||
get_fixture_name = fixture_manager.get_fixture_name
|
get_fixture_name = fixture.get_fixture_name
|
||||||
setup_fixture = fixture_manager.setup_fixture
|
remove_fixture = fixture.remove_fixture
|
||||||
cleanup_fixture = fixture_manager.cleanup_fixture
|
setup_fixture = fixture.setup_fixture
|
||||||
list_required_fixtures = fixture_manager.list_required_fixtures
|
setup_shared_fixture = fixture.setup_shared_fixture
|
||||||
iter_required_fixtures = fixture_manager.iter_required_fixtures
|
cleanup_fixture = fixture.cleanup_fixture
|
||||||
setup_required_fixtures = fixture_manager.setup_required_fixtures
|
cleanup_shared_fixture = fixture.cleanup_shared_fixture
|
||||||
cleanup_required_fixtures = fixture_manager.cleanup_required_fixtures
|
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
|
||||||
|
|
|
@ -36,12 +36,33 @@ def get_fixture_name(obj):
|
||||||
return get_fixture(obj).__tobiko_fixture_name__
|
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):
|
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):
|
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):
|
def iter_required_fixtures(objects):
|
||||||
|
@ -80,15 +101,14 @@ def list_required_fixtures(objects):
|
||||||
|
|
||||||
|
|
||||||
def setup_required_fixtures(objects, manager=None):
|
def setup_required_fixtures(objects, manager=None):
|
||||||
manager = manager or FIXTURES
|
for name in iter_required_fixtures(objects=objects):
|
||||||
for _fixture in iter_required_fixtures(objects=objects):
|
yield setup_fixture(name, manager=manager)
|
||||||
manager.get_fixture(_fixture).setUp()
|
|
||||||
|
|
||||||
|
|
||||||
def cleanup_required_fixtures(objects, manager=None):
|
def cleanup_required_fixtures(objects, manager=None):
|
||||||
manager = manager or FIXTURES
|
manager = manager or FIXTURES
|
||||||
for _fixture in iter_required_fixtures(objects=objects):
|
for name in iter_required_fixtures(objects=objects):
|
||||||
manager.get_fixture(_fixture).cleanUp()
|
yield cleanup_fixture(name, manager=manager)
|
||||||
|
|
||||||
|
|
||||||
def init_fixture(obj, name):
|
def init_fixture(obj, name):
|
||||||
|
@ -168,5 +188,52 @@ class FixtureManager(object):
|
||||||
assert isinstance(fixture, fixtures.Fixture)
|
assert isinstance(fixture, fixtures.Fixture)
|
||||||
return fixture
|
return fixture
|
||||||
|
|
||||||
|
def remove_fixture(self, obj):
|
||||||
|
name = get_object_name(obj)
|
||||||
|
return self.fixtures.pop(name, None)
|
||||||
|
|
||||||
|
|
||||||
FIXTURES = FixtureManager()
|
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
|
||||||
|
|
|
@ -17,29 +17,47 @@ import fixtures
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
import tobiko
|
import tobiko
|
||||||
from tobiko.tests import base
|
from tobiko.tests import unit
|
||||||
|
|
||||||
|
|
||||||
class MyFixtureClass(fixtures.Fixture):
|
class MyFixture(fixtures.Fixture):
|
||||||
pass
|
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):
|
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):
|
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):
|
def _test_get_fixture(self, obj, fixture_type):
|
||||||
fixture = tobiko.get_fixture(obj)
|
fixture = tobiko.get_fixture(obj)
|
||||||
self.assertIsInstance(fixture, fixture_type)
|
self.assertIsInstance(fixture, fixture_type)
|
||||||
self.assertIs(fixture, tobiko.get_fixture(obj))
|
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):
|
def test_get_name(self):
|
||||||
fixture = tobiko.get_fixture(MY_FIXTURE_NAME)
|
fixture = tobiko.get_fixture(MY_FIXTURE_NAME)
|
||||||
result = tobiko.get_fixture_name(fixture)
|
result = tobiko.get_fixture_name(fixture)
|
||||||
|
@ -49,42 +67,42 @@ class FixtureTypeTest(base.TobikoTest):
|
||||||
self._test_setup_fixture(MY_FIXTURE_NAME)
|
self._test_setup_fixture(MY_FIXTURE_NAME)
|
||||||
|
|
||||||
def test_setup_fixture_by_type(self):
|
def test_setup_fixture_by_type(self):
|
||||||
self._test_setup_fixture(MyFixtureClass)
|
self._test_setup_fixture(MyFixture)
|
||||||
|
|
||||||
def _test_setup_fixture(self, obj):
|
def _test_setup_fixture(self, obj):
|
||||||
fixture = tobiko.get_fixture(obj)
|
setup = self.patch('fixtures.Fixture.setUp')
|
||||||
fixture.setUp = setup = mock.MagicMock()
|
|
||||||
|
|
||||||
tobiko.setup_fixture(obj)
|
result = tobiko.setup_fixture(obj)
|
||||||
|
|
||||||
setup.assert_called_once_with()
|
setup.assert_called_once_with()
|
||||||
|
self.assertIs(tobiko.get_fixture(obj), result)
|
||||||
|
|
||||||
def test_cleanup_fixture_by_name(self):
|
def test_cleanup_fixture_by_name(self):
|
||||||
self._test_cleanup_fixture(MY_FIXTURE_NAME)
|
self._test_cleanup_fixture(MY_FIXTURE_NAME)
|
||||||
|
|
||||||
def test_cleanup_fixture_by_type(self):
|
def test_cleanup_fixture_by_type(self):
|
||||||
self._test_cleanup_fixture(MyFixtureClass)
|
self._test_cleanup_fixture(MyFixture)
|
||||||
|
|
||||||
def _test_cleanup_fixture(self, obj):
|
def _test_cleanup_fixture(self, obj):
|
||||||
cleanup = mock.MagicMock()
|
cleanup = mock.MagicMock()
|
||||||
fixture = tobiko.get_fixture(obj)
|
fixture = tobiko.setup_fixture(obj)
|
||||||
fixture.setUp()
|
|
||||||
fixture.addCleanup(cleanup)
|
fixture.addCleanup(cleanup)
|
||||||
|
|
||||||
tobiko.cleanup_fixture(obj)
|
result = tobiko.cleanup_fixture(obj)
|
||||||
|
|
||||||
cleanup.assert_called_once_with()
|
cleanup.assert_called_once_with()
|
||||||
|
self.assertIs(tobiko.get_fixture(obj), result)
|
||||||
|
|
||||||
def test_list_required_fixtures_from_module(self):
|
def test_list_required_fixtures_from_module(self):
|
||||||
result = tobiko.list_required_fixtures([__name__])
|
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):
|
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)
|
self.assertEqual([MY_FIXTURE_NAME], result)
|
||||||
|
|
||||||
def test_list_required_fixtures_from_fixture_type(self):
|
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)
|
self.assertEqual([MY_FIXTURE_NAME], result)
|
||||||
|
|
||||||
def test_list_required_fixtures_from_fixture_name(self):
|
def test_list_required_fixtures_from_fixture_name(self):
|
||||||
|
@ -92,7 +110,7 @@ class FixtureTypeTest(base.TobikoTest):
|
||||||
self.assertEqual([MY_FIXTURE_NAME], result)
|
self.assertEqual([MY_FIXTURE_NAME], result)
|
||||||
|
|
||||||
def test_list_required_fixtures_from_method(
|
def test_list_required_fixtures_from_method(
|
||||||
self, fixture_type=MyFixtureClass):
|
self, fixture_type=MyFixture):
|
||||||
result = tobiko.list_required_fixtures([self.id()])
|
result = tobiko.list_required_fixtures([self.id()])
|
||||||
self.assertEqual([MY_FIXTURE_NAME], result)
|
self.assertEqual([MY_FIXTURE_NAME], result)
|
||||||
self.assertIsInstance(tobiko.get_fixture(MY_FIXTURE_NAME),
|
self.assertIsInstance(tobiko.get_fixture(MY_FIXTURE_NAME),
|
||||||
|
@ -103,20 +121,79 @@ class FixtureTypeTest(base.TobikoTest):
|
||||||
result = tobiko.list_required_fixtures([fixture])
|
result = tobiko.list_required_fixtures([fixture])
|
||||||
self.assertEqual([MY_FIXTURE_NAME], result)
|
self.assertEqual([MY_FIXTURE_NAME], result)
|
||||||
|
|
||||||
def test_setup_required_fixtures(self, fixture_type=MyFixtureClass):
|
def test_setup_required_fixtures(self, fixture_type=MyFixture):
|
||||||
fixture = tobiko.get_fixture(fixture_type)
|
setup = self.patch('fixtures.Fixture.setUp')
|
||||||
fixture.setUp = setup = mock.MagicMock()
|
|
||||||
|
|
||||||
tobiko.setup_required_fixtures([self.id()])
|
result = list(tobiko.setup_required_fixtures([self.id()]))
|
||||||
|
|
||||||
setup.assert_called_once_with()
|
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()
|
cleanup = mock.MagicMock()
|
||||||
fixture = tobiko.get_fixture(fixture_type)
|
fixture = tobiko.setup_fixture(fixture_type)
|
||||||
fixture.setUp()
|
|
||||||
fixture.addCleanup(cleanup)
|
fixture.addCleanup(cleanup)
|
||||||
|
|
||||||
tobiko.cleanup_required_fixtures([self.id()])
|
result = list(tobiko.cleanup_required_fixtures([self.id()]))
|
||||||
|
|
||||||
cleanup.assert_called_once_with()
|
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()])
|
||||||
|
|
Loading…
Reference in New Issue