setUpClass/tearDownClass full chain
Ensure the setUpClass/tearDownClass methods calls the super properly.
The setUpClass call tested at setUp time, the tearDownClass at exit
time.
super calling issues are also fixed.
Implements blueprint stop-leaking
Closes-Bug: #1212071
Change-Id: I266efe0cd363b330b1511e7e983dab9f62778848
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 15e28fd..acf0275 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -36,6 +36,7 @@
@classmethod
def setUpClass(cls):
+ super(BaseComputeTest, cls).setUpClass()
if not cls.config.service_available.nova:
skip_msg = ("%s skipped as nova is not available" % cls.__name__)
raise cls.skipException(skip_msg)
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index 9f7b24b..d98fb71 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/test_endpoints.py
@@ -53,6 +53,7 @@
cls.client.delete_endpoint(e['id'])
for s in cls.service_ids:
cls.identity_client.delete_service(s)
+ super(EndPointsTestJSON, cls).tearDownClass()
@attr(type='gate')
def test_list_endpoints(self):
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 1237ce4..bfb5372 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -25,6 +25,7 @@
@classmethod
def setUpClass(cls):
+ super(BaseIdentityAdminTest, cls).setUpClass()
os = clients.AdminManager(interface=cls._interface)
cls.client = os.identity_client
cls.token_client = os.token_client
@@ -45,6 +46,7 @@
@classmethod
def tearDownClass(cls):
cls.data.teardown_all()
+ super(BaseIdentityAdminTest, cls).tearDownClass()
def disable_user(self, user_name):
user = self.get_user_by_name(user_name)
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 4e61495..4f54a15 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -29,6 +29,7 @@
@classmethod
def setUpClass(cls):
+ super(BaseImageTest, cls).setUpClass()
cls.created_images = []
cls._interface = 'json'
cls.isolated_creds = isolated_creds.IsolatedCreds(cls.__name__)
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index d3fa763..2a3b3f7 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -47,6 +47,7 @@
@classmethod
def setUpClass(cls):
+ super(BaseNetworkTest, cls).setUpClass()
os = clients.Manager()
cls.network_cfg = os.config.network
if not cls.config.service_available.neutron:
@@ -64,6 +65,7 @@
cls.client.delete_subnet(subnet['id'])
for network in cls.networks:
cls.client.delete_network(network['id'])
+ super(BaseNetworkTest, cls).tearDownClass()
@classmethod
def create_network(cls, network_name=None):
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index 5a1fb5a..820328c 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -26,6 +26,7 @@
@classmethod
def setUpClass(cls):
+ super(BaseObjectTest, cls).setUpClass()
if not cls.config.service_available.swift:
skip_msg = ("%s skipped as swift is not available" % cls.__name__)
raise cls.skipException(skip_msg)
diff --git a/tempest/api/object_storage/test_container_services.py b/tempest/api/object_storage/test_container_services.py
index 8b9fc8c..eaaed39 100644
--- a/tempest/api/object_storage/test_container_services.py
+++ b/tempest/api/object_storage/test_container_services.py
@@ -31,6 +31,7 @@
@classmethod
def tearDownClass(cls):
cls.delete_containers(cls.containers)
+ super(ContainerTest, cls).tearDownClass()
@attr(type='smoke')
def test_create_container(self):
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index 5de4df0..d18c2ad 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -50,6 +50,7 @@
def tearDownClass(cls):
for client in cls.clients.values():
cls.delete_containers(cls.containers, client[0], client[1])
+ super(ContainerSyncTest, cls).tearDownClass()
@testtools.skip('Until Bug #1093743 is resolved.')
@attr(type='gate')
diff --git a/tempest/api/object_storage/test_object_expiry.py b/tempest/api/object_storage/test_object_expiry.py
index b546cec..8703480 100644
--- a/tempest/api/object_storage/test_object_expiry.py
+++ b/tempest/api/object_storage/test_object_expiry.py
@@ -41,6 +41,7 @@
NotFound exception and also non empty container cannot be deleted.
"""
cls.delete_containers([cls.container_name])
+ super(ObjectExpiryTest, cls).tearDownClass()
@testtools.skip('Until Bug #1069849 is resolved.')
@attr(type='gate')
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index c8d9965..c599562 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -47,6 +47,7 @@
cls.delete_containers(cls.containers)
# delete the user setup created
cls.data.teardown_all()
+ super(ObjectTest, cls).tearDownClass()
@attr(type='smoke')
def test_create_object(self):
diff --git a/tempest/api/object_storage/test_object_version.py b/tempest/api/object_storage/test_object_version.py
index cda3e4f..2b93c32 100644
--- a/tempest/api/object_storage/test_object_version.py
+++ b/tempest/api/object_storage/test_object_version.py
@@ -29,6 +29,7 @@
@classmethod
def tearDownClass(cls):
cls.delete_containers(cls.containers)
+ super(ContainerTest, cls).tearDownClass()
def assertContainer(self, container, count, byte, versioned):
resp, _ = self.container_client.list_container_metadata(container)
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index d06d942..745dd87 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -28,7 +28,7 @@
@classmethod
def setUpClass(cls):
-
+ super(BaseOrchestrationTest, cls).setUpClass()
os = clients.OrchestrationManager()
cls.orchestration_cfg = os.config.orchestration
if not os.config.service_available.heat:
@@ -107,6 +107,7 @@
def tearDownClass(cls):
cls.clear_stacks()
cls.clear_keypairs()
+ super(BaseOrchestrationTest, cls).tearDownClass()
def wait_for(self, condition):
"""Repeatedly calls condition() until a timeout."""
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 52ab5b7..7781647 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -31,6 +31,7 @@
@classmethod
def setUpClass(cls):
+ super(BaseVolumeTest, cls).setUpClass()
cls.isolated_creds = isolated_creds.IsolatedCreds(cls.__name__)
if not cls.config.service_available.cinder:
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 4447da0..d0f0127 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -150,6 +150,7 @@
@classmethod
def setUpClass(cls):
+ super(OfficialClientTest, cls).setUpClass()
cls.isolated_creds = isolated_creds.IsolatedCreds(
__name__, tempest_client=False)
if cls.config.compute.allow_tenant_isolation:
diff --git a/tempest/test.py b/tempest/test.py
index 0cd0b08..7787790 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -15,6 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import atexit
import os
import time
@@ -91,6 +92,17 @@
LOG.info("Overriding skipException to nose SkipTest")
testtools.TestCase.skipException = nose.plugins.skip.SkipTest
+at_exit_set = set()
+
+
+def validate_tearDownClass():
+ if at_exit_set:
+ raise RuntimeError("tearDownClass does not calls the super's"
+ "tearDownClass in these classes: "
+ + str(at_exit_set))
+
+atexit.register(validate_tearDownClass)
+
class BaseTestCase(testtools.TestCase,
testtools.testcase.WithAttributes,
@@ -98,29 +110,43 @@
config = config.TempestConfig()
+ setUpClassCalled = False
+
@classmethod
def setUpClass(cls):
if hasattr(super(BaseTestCase, cls), 'setUpClass'):
super(BaseTestCase, cls).setUpClass()
+ cls.setUpClassCalled = True
- def setUp(cls):
- super(BaseTestCase, cls).setUp()
+ @classmethod
+ def tearDownClass(cls):
+ at_exit_set.remove(cls)
+ if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
+ super(BaseTestCase, cls).tearDownClass()
+
+ def setUp(self):
+ super(BaseTestCase, self).setUp()
+ if not self.setUpClassCalled:
+ raise RuntimeError("setUpClass does not calls the super's"
+ "setUpClass in the "
+ + self.__class__.__name__)
+ at_exit_set.add(self.__class__)
test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
try:
test_timeout = int(test_timeout)
except ValueError:
test_timeout = 0
if test_timeout > 0:
- cls.useFixture(fixtures.Timeout(test_timeout, gentle=True))
+ self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
os.environ.get('OS_STDOUT_CAPTURE') == '1'):
- stdout = cls.useFixture(fixtures.StringStream('stdout')).stream
- cls.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
+ stdout = self.useFixture(fixtures.StringStream('stdout')).stream
+ self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
os.environ.get('OS_STDERR_CAPTURE') == '1'):
- stderr = cls.useFixture(fixtures.StringStream('stderr')).stream
- cls.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
+ stderr = self.useFixture(fixtures.StringStream('stderr')).stream
+ self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
@classmethod
def _get_identity_admin_client(cls):
diff --git a/tempest/thirdparty/boto/test.py b/tempest/thirdparty/boto/test.py
index 8812a10..e0c9f06 100644
--- a/tempest/thirdparty/boto/test.py
+++ b/tempest/thirdparty/boto/test.py
@@ -197,6 +197,7 @@
@classmethod
def setUpClass(cls):
+ super(BotoTestCase, cls).setUpClass()
# The trash contains cleanup functions and paramaters in tuples
# (function, *args, **kwargs)
cls._resource_trash_bin = {}
@@ -261,6 +262,10 @@
LOG.exception(exc)
finally:
del cls._resource_trash_bin[key]
+ super(BotoTestCase, cls).tearDownClass()
+ # NOTE(afazekas): let the super called even on exceptions
+ # The real exceptions already logged, if the super throws another,
+ # does not causes hidden issues
if fail_count:
raise exceptions.TearDownException(num=fail_count)