Prepare skip_checks as stable interface

Fix docstring and add unit tests.

Change-Id: I97c468936465e4677591a77b98aa8296e528ed3b
diff --git a/tempest/test.py b/tempest/test.py
index 434c58b..7d95bcf 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -245,12 +245,35 @@
         """Class level skip checks.
 
         Subclasses verify in here all conditions that might prevent the
-        execution of the entire test class.
-        Checks implemented here may not make use API calls, and should rely on
-        configuration alone.
-        In general skip checks that require an API call are discouraged.
-        If one is really needed it may be implemented either in the
-        resource_setup or at test level.
+        execution of the entire test class. Skipping here prevents any other
+        class fixture from being executed i.e. no credentials or other
+        resource allocation will happen.
+
+        Tests defined in the test class will no longer appear in test results.
+        The `setUpClass` for the entire test class will be marked as SKIPPED
+        instead.
+
+        At this stage no test credentials are available, so skip checks
+        should rely on configuration alone. This is deliberate since skips
+        based on the result of an API call are discouraged.
+
+        The following checks are implemented in `test.py` already:
+        - check that alt credentials are available when requested by the test
+        - check that admin credentials are available when requested by the test
+        - check that the identity version specified by the test is marked as
+          enabled in the configuration
+
+        Overriders of skip_checks must always invoke skip_check on `super`
+        first.
+
+        Example::
+
+            @classmethod
+            def skip_checks(cls):
+                super(Example, cls).skip_checks()
+                if not CONF.service_available.my_service:
+                    skip_msg = ("%s skipped as my_service is not available")
+                    raise cls.skipException(skip_msg % cls.__name__)
         """
         cls.__skip_checks_called = True
         identity_version = cls.get_identity_version()
diff --git a/tempest/tests/test_test.py b/tempest/tests/test_test.py
index 42e213e..ead0bd8 100644
--- a/tempest/tests/test_test.py
+++ b/tempest/tests/test_test.py
@@ -377,3 +377,52 @@
                 RuntimeError,
                 value_re='^.* ' + SonOfBadSkipChecks.__name__):
             bad_class.setUpClass()
+
+    @mock.patch('tempest.common.credentials_factory.is_admin_available',
+                autospec=True, return_value=True)
+    def test_skip_checks_admin(self, mock_iaa):
+        identity_version = 'identity_version'
+
+        class NeedAdmin(self.parent_test):
+            credentials = ['admin']
+
+            @classmethod
+            def get_identity_version(cls):
+                return identity_version
+
+        NeedAdmin().skip_checks()
+        mock_iaa.assert_called_once_with('identity_version')
+
+    @mock.patch('tempest.common.credentials_factory.is_admin_available',
+                autospec=True, return_value=False)
+    def test_skip_checks_admin_not_available(self, mock_iaa):
+        identity_version = 'identity_version'
+
+        class NeedAdmin(self.parent_test):
+            credentials = ['admin']
+
+            @classmethod
+            def get_identity_version(cls):
+                return identity_version
+
+        with testtools.ExpectedException(testtools.testcase.TestSkipped):
+            NeedAdmin().skip_checks()
+        mock_iaa.assert_called_once_with('identity_version')
+
+    def test_skip_checks_identity_v2_not_available(self):
+        cfg.CONF.set_default('api_v2', False, 'identity-feature-enabled')
+
+        class NeedV2(self.parent_test):
+            identity_version = 'v2'
+
+        with testtools.ExpectedException(testtools.testcase.TestSkipped):
+            NeedV2().skip_checks()
+
+    def test_skip_checks_identity_v3_not_available(self):
+        cfg.CONF.set_default('api_v3', False, 'identity-feature-enabled')
+
+        class NeedV3(self.parent_test):
+            identity_version = 'v3'
+
+        with testtools.ExpectedException(testtools.testcase.TestSkipped):
+            NeedV3().skip_checks()