Merge "Make skip_checks and setup_creds safe"
diff --git a/tempest/test.py b/tempest/test.py
index ce977fa..434c58b 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -132,6 +132,7 @@
     def _reset_class(cls):
         cls.__setup_credentials_called = False
         cls.__resource_cleaup_called = False
+        cls.__skip_checks_called = False
         cls._class_cleanups = []
 
     @classmethod
@@ -146,10 +147,16 @@
         cls.teardowns = []
         # All the configuration checks that may generate a skip
         cls.skip_checks()
+        if not cls.__skip_checks_called:
+            raise RuntimeError("skip_checks for %s did not call the super's "
+                               "skip_checks" % cls.__name__)
         try:
             # Allocation of all required credentials and client managers
             cls.teardowns.append(('credentials', cls.clear_credentials))
             cls.setup_credentials()
+            if not cls.__setup_credentials_called:
+                raise RuntimeError("setup_credentials for %s did not call the "
+                                   "super's setup_credentials" % cls.__name__)
             # Shortcuts to clients
             cls.setup_clients()
             # Additional class-wide test resources
@@ -245,6 +252,7 @@
         If one is really needed it may be implemented either in the
         resource_setup or at test level.
         """
+        cls.__skip_checks_called = True
         identity_version = cls.get_identity_version()
         # setting force_tenant_isolation to True also needs admin credentials.
         if ('admin' in cls.credentials or
diff --git a/tempest/tests/test_test.py b/tempest/tests/test_test.py
index f2c28a6..42e213e 100644
--- a/tempest/tests/test_test.py
+++ b/tempest/tests/test_test.py
@@ -332,3 +332,48 @@
         found_exc = log[0][1][1]
         self.assertTrue(isinstance(found_exc, RuntimeError))
         self.assertIn(BadResourceCleanup.__name__, str(found_exc))
+
+    def test_super_skip_checks_not_invoked(self):
+
+        class BadSkipChecks(self.parent_test):
+
+            @classmethod
+            def skip_checks(cls):
+                pass
+
+        bad_class = BadSkipChecks()
+        with testtools.ExpectedException(
+                RuntimeError,
+                value_re='^.* ' + BadSkipChecks.__name__):
+            bad_class.setUpClass()
+
+    def test_super_setup_credentials_not_invoked(self):
+
+        class BadSetupCredentials(self.parent_test):
+
+            @classmethod
+            def skip_checks(cls):
+                pass
+
+        bad_class = BadSetupCredentials()
+        with testtools.ExpectedException(
+                RuntimeError,
+                value_re='^.* ' + BadSetupCredentials.__name__):
+            bad_class.setUpClass()
+
+    def test_grandparent_skip_checks_not_invoked(self):
+
+        class BadSkipChecks(self.parent_test):
+
+            @classmethod
+            def skip_checks(cls):
+                pass
+
+        class SonOfBadSkipChecks(BadSkipChecks):
+            pass
+
+        bad_class = SonOfBadSkipChecks()
+        with testtools.ExpectedException(
+                RuntimeError,
+                value_re='^.* ' + SonOfBadSkipChecks.__name__):
+            bad_class.setUpClass()