Create abstract fixture manager
Allow to decople global fixture definition from test cases. Fixtures can be defined as a subclass of tobiko.Fixture class MyFixture(tobiko.Fixture): ... Tobiko will reference to it as: '<module-name>.MyFixture' where module-name is the full name of the module where the class is defined. Fixture name are accessible via 'fixture_name' class attribute. tobiko.Fixture subclass has to implement bellow methods def create_fixture(self): # mandatory ... def delete_fixture(self): # optional method ... Test cases to create a fixture should mane one of below calls: fixture = tobiko.create_fixture(<fixture-name>) fixture = tobiko.create_fixture(<fixture-class>) Existing fixtures can be find using one of below calls: fixture = tobiko.get_fixture(<fixture-name>) fixture = tobiko.get_fixture(<fixture-class>) Existing fixtures can be deleted using one of below calls: tobiko.delete_fixture(<fixture-name>) tobiko.delete_fixture(<fixture-class>) Change-Id: I5c104a732234ab2183fbfb9909cba4a445f59b60
This commit is contained in:
parent
e790cc131b
commit
487281e7a7
@ -0,0 +1,22 @@
|
|||||||
|
#
|
||||||
|
# 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.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
from tobiko.common.managers import fixture as fixture_manager
|
||||||
|
|
||||||
|
|
||||||
|
Fixture = fixture_manager.Fixture
|
||||||
|
|
||||||
|
get_fixture = fixture_manager.FIXTURES.get
|
||||||
|
create_fixture = fixture_manager.FIXTURES.create
|
||||||
|
delete_fixture = fixture_manager.FIXTURES.delete
|
97
tobiko/common/managers/fixture.py
Normal file
97
tobiko/common/managers/fixture.py
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
# Copyright 2018 Red Hat
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
|
||||||
|
import abc
|
||||||
|
import inspect
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
|
def get_fixture_name(obj):
|
||||||
|
if isinstance(obj, six.string_types):
|
||||||
|
return obj
|
||||||
|
|
||||||
|
elif (isinstance(obj, six.class_types) and
|
||||||
|
issubclass(obj, Fixture)):
|
||||||
|
return obj.fixture_name
|
||||||
|
|
||||||
|
msg = "{!r} is not a string type or a subclass of {!s}".format(
|
||||||
|
obj, Fixture)
|
||||||
|
raise TypeError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
class FixtureManager(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.fixtures = {}
|
||||||
|
|
||||||
|
def set(self, name, cls):
|
||||||
|
if not issubclass(cls, Fixture):
|
||||||
|
msg = "{!r} is not a subclass of {!s}".format(cls, Fixture)
|
||||||
|
raise TypeError(msg)
|
||||||
|
fixture = cls()
|
||||||
|
actual_fixture = self.fixtures.setdefault(name, fixture)
|
||||||
|
if actual_fixture is not fixture:
|
||||||
|
msg = "Fixture with named {!r} already registered: {!r}".format(
|
||||||
|
name, actual_fixture)
|
||||||
|
raise ValueError(msg)
|
||||||
|
return fixture
|
||||||
|
|
||||||
|
def get(self, cls_or_name):
|
||||||
|
name = get_fixture_name(cls_or_name)
|
||||||
|
fixture = self.fixtures.get(name)
|
||||||
|
if fixture is None:
|
||||||
|
raise ValueError('Invalid fixture name: {!r}'.format(name))
|
||||||
|
return fixture
|
||||||
|
|
||||||
|
def create(self, cls_or_name):
|
||||||
|
fixture = self.get(cls_or_name)
|
||||||
|
fixture.create_fixture()
|
||||||
|
return fixture
|
||||||
|
|
||||||
|
def delete(self, cls_or_name):
|
||||||
|
fixture = self.get(cls_or_name)
|
||||||
|
fixture.delete_fixture()
|
||||||
|
return fixture
|
||||||
|
|
||||||
|
|
||||||
|
FIXTURES = FixtureManager()
|
||||||
|
|
||||||
|
|
||||||
|
class FixtureMeta(abc.ABCMeta):
|
||||||
|
|
||||||
|
def __new__(cls, name, bases, members):
|
||||||
|
fixture_class = super(FixtureMeta, cls).__new__(cls, name, bases,
|
||||||
|
members)
|
||||||
|
if not inspect.isabstract(fixture_class):
|
||||||
|
fixture_name = getattr(fixture_class, 'fixture_name', None)
|
||||||
|
if fixture_name is None:
|
||||||
|
fixture_class.fixture_name = fixture_name = (
|
||||||
|
fixture_class.__module__ + '.' +
|
||||||
|
fixture_class.__name__)
|
||||||
|
FIXTURES.set(fixture_name, fixture_class)
|
||||||
|
return fixture_class
|
||||||
|
|
||||||
|
|
||||||
|
@six.add_metaclass(FixtureMeta)
|
||||||
|
class Fixture(object):
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_fixture(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_fixture(self):
|
||||||
|
pass
|
89
tobiko/tests/test_fixture.py
Normal file
89
tobiko/tests/test_fixture.py
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
# Copyright 2018 Red Hat
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import tobiko
|
||||||
|
from tobiko.tests import base
|
||||||
|
|
||||||
|
|
||||||
|
class TestFixture(tobiko.Fixture):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.created = False
|
||||||
|
self.deleted = False
|
||||||
|
|
||||||
|
reset = __init__
|
||||||
|
|
||||||
|
def create_fixture(self):
|
||||||
|
self.created = True
|
||||||
|
|
||||||
|
def delete_fixture(self):
|
||||||
|
self.deleted = True
|
||||||
|
|
||||||
|
|
||||||
|
class FixtureTypeTest(base.TobikoTest):
|
||||||
|
|
||||||
|
fixture_type = TestFixture
|
||||||
|
fixture_name = __name__ + '.' + TestFixture.__name__
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super(FixtureTypeTest, cls).setUpClass()
|
||||||
|
cls.fixture = tobiko.get_fixture(cls.fixture_name)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(FixtureTypeTest, self).setUp()
|
||||||
|
self.fixture.reset()
|
||||||
|
|
||||||
|
def test_fixture_type(self):
|
||||||
|
self.assertIsInstance(self.fixture, self.fixture_type)
|
||||||
|
|
||||||
|
def test_fixture_name(self):
|
||||||
|
self.assertEqual(self.fixture_name, self.fixture.fixture_name)
|
||||||
|
|
||||||
|
def test_get_fixture_by_name(self):
|
||||||
|
self._test_get_fixture(self.fixture_name)
|
||||||
|
|
||||||
|
def test_get_fixture_by_type(self):
|
||||||
|
self._test_get_fixture(self.fixture_type)
|
||||||
|
|
||||||
|
def _test_get_fixture(self, obj):
|
||||||
|
fixture = tobiko.get_fixture(obj)
|
||||||
|
self.assertIs(self.fixture, fixture)
|
||||||
|
self.assertFalse(fixture.created)
|
||||||
|
self.assertFalse(fixture.deleted)
|
||||||
|
|
||||||
|
def test_create_fixture_by_name(self):
|
||||||
|
self._test_create_fixture(self.fixture_name)
|
||||||
|
|
||||||
|
def test_create_fixture_by_type(self):
|
||||||
|
self._test_create_fixture(self.fixture_type)
|
||||||
|
|
||||||
|
def _test_create_fixture(self, obj):
|
||||||
|
fixture = tobiko.create_fixture(obj)
|
||||||
|
self.assertIs(self.fixture, fixture)
|
||||||
|
self.assertTrue(fixture.created)
|
||||||
|
self.assertFalse(fixture.deleted)
|
||||||
|
|
||||||
|
def test_delete_fixture_by_name(self):
|
||||||
|
self._test_delete_fixture(self.fixture_name)
|
||||||
|
|
||||||
|
def test_delete_fixture_by_type(self):
|
||||||
|
self._test_delete_fixture(self.fixture_type)
|
||||||
|
|
||||||
|
def _test_delete_fixture(self, obj=TestFixture):
|
||||||
|
fixture = tobiko.delete_fixture(obj)
|
||||||
|
self.assertIs(self.fixture, fixture)
|
||||||
|
self.assertFalse(fixture.created)
|
||||||
|
self.assertTrue(fixture.deleted)
|
4
tox.ini
4
tox.ini
@ -1,5 +1,5 @@
|
|||||||
[tox]
|
[tox]
|
||||||
envlist = pep8,pylint,py35,py36,py27
|
envlist = pep8,pylint,py35,py36,py37,py27
|
||||||
|
|
||||||
minversion = 2.0
|
minversion = 2.0
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ commands =
|
|||||||
find . -type f -name ".coverage*" -delete
|
find . -type f -name ".coverage*" -delete
|
||||||
find . -type f -name "*.pyc" -delete
|
find . -type f -name "*.pyc" -delete
|
||||||
coverage erase
|
coverage erase
|
||||||
stestr --test-path ./tobiko/tests/cmd run {posargs}
|
stestr --test-path ./tobiko/tests run --black-regex 'scenario' {posargs}
|
||||||
coverage combine
|
coverage combine
|
||||||
coverage html -d cover
|
coverage html -d cover
|
||||||
coverage xml -o cover/coverage.xml
|
coverage xml -o cover/coverage.xml
|
||||||
|
Loading…
Reference in New Issue
Block a user