Framework for resource safe class level fixtures
Modify BaseTestCase, add resource_setup and resource_cleanup
methods, invoked by setUpClass and tearDownClass respectively.
Partially-implements bp:resource-cleanup
Change-Id: I5f025b4f76d6d85fbefbada9475daf784425037a
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 66043d3..6e35a31 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -94,13 +94,6 @@
cls.network_client = cls.manager.network_client
@classmethod
- def tearDownClass(cls):
- # Isolated creds also manages network resources, which should
- # be cleaned up at the end of the test case
- cls.isolated_creds.clear_isolated_creds()
- super(ScenarioTest, cls).tearDownClass()
-
- @classmethod
def _get_credentials(cls, get_creds, ctype):
if CONF.compute.allow_tenant_isolation:
creds = get_creds()
@@ -1015,11 +1008,6 @@
cls.ceilometer_client = cls.manager.ceilometer_client
@classmethod
- def tearDownClass(cls):
- cls.isolated_creds.clear_isolated_creds()
- super(OfficialClientTest, cls).tearDownClass()
-
- @classmethod
def _get_credentials(cls, get_creds, ctype):
if CONF.compute.allow_tenant_isolation:
creds = get_creds()
diff --git a/tempest/test.py b/tempest/test.py
index d2b32d4..4a22b1b 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -69,6 +69,9 @@
def safe_setup(f):
"""A decorator used to wrap the setUpClass for cleaning up resources
when setUpClass failed.
+
+ Deprecated, see:
+ http://specs.openstack.org/openstack/qa-specs/specs/resource-cleanup.html
"""
@functools.wraps(f)
def decorator(cls):
@@ -279,15 +282,51 @@
@classmethod
def setUpClass(cls):
+ # It should never be overridden by descendants
if hasattr(super(BaseTestCase, cls), 'setUpClass'):
super(BaseTestCase, cls).setUpClass()
cls.setUpClassCalled = True
+ # No test resource is allocated until here
+ try:
+ # TODO(andreaf) Split-up resource_setup in stages:
+ # skip checks, pre-hook, credentials, clients, resources, post-hook
+ cls.resource_setup()
+ except Exception:
+ etype, value, trace = sys.exc_info()
+ LOG.info("%s in resource setup. Invoking tearDownClass." % etype)
+ # Catch any exception in tearDown so we can re-raise the original
+ # exception at the end
+ try:
+ cls.tearDownClass()
+ except Exception as te:
+ LOG.exception("tearDownClass failed: %s" % te)
+ try:
+ raise etype(value), None, trace
+ finally:
+ del trace # for avoiding circular refs
@classmethod
def tearDownClass(cls):
at_exit_set.discard(cls)
+ # It should never be overridden by descendants
if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
super(BaseTestCase, cls).tearDownClass()
+ try:
+ cls.resource_cleanup()
+ finally:
+ cls.clear_isolated_creds()
+
+ @classmethod
+ def resource_setup(cls):
+ """Class level setup steps for test cases.
+ Recommended order: skip checks, credentials, clients, resources.
+ """
+ pass
+
+ @classmethod
+ def resource_cleanup(cls):
+ """Class level resource cleanup for test cases. """
+ pass
def setUp(self):
super(BaseTestCase, self).setUp()
@@ -355,7 +394,7 @@
"""
Clears isolated creds if set
"""
- if getattr(cls, 'isolated_creds'):
+ if hasattr(cls, 'isolated_creds'):
cls.isolated_creds.clear_isolated_creds()
@classmethod