فهرست منبع

Added automatic test case generation for provider implementations.
Renamed tests folder to test according to standard.

nuwan_ag 10 سال پیش
والد
کامیت
b6103b0c32
4فایلهای تغییر یافته به همراه130 افزوده شده و 39 حذف شده
  1. 35 0
      test/__init__.py
  2. 70 0
      test/helpers.py
  3. 25 0
      test/testprovidersecurityservice.py
  4. 0 39
      tests/TestProviderSecurityService.py

+ 35 - 0
test/__init__.py

@@ -0,0 +1,35 @@
+"""
+Tests the functionality of each provider implementation against registered test cases.
+These tests require that provider credentials are set as environment variables, as required for
+each provider.
+
+Since the tests exercise the cloudbridge interfaces, and there are multiple implementations of these
+interfaces, for m interfaces and n implementation, exercising all interfaces means that m*n test case
+classes are needed. Otherwise, the standard test runners such as unittest and nose2 do not correctly
+pick up the tests.
+
+To avoid an explosion of repetitive test cases, the ProviderTestCaseGenerator class will
+automatically generate a new Python class for each combination of test and provider. The
+load_tests protocol (https://docs.python.org/2/library/unittest.html#load-tests-protocol)
+is used to aid test discovery.
+
+Use ``python -m unittest tests`` to run these unit tests. (alternatively, use ``nose2 tests``)
+
+All test cases need to be registered below, and available providers will be discovered through
+the ProviderFactory. Test Cases must not inherit from unittest.TestCase, to avoid confusing
+unittest and nose2's automatic discovery.
+(The test generator will automatically add unittest.TestCase as a base class to each combination)
+"""
+
+from helpers import ProviderTestCaseGenerator
+from testprovidersecurityservice import ProviderSecurityServiceTestCase
+
+PROVIDER_TESTS = [ProviderSecurityServiceTestCase]
+
+
+def load_tests(loader=None, tests=None, pattern=None):
+    """
+    This function is required to aid the load_tests protocol
+    (https://docs.python.org/2/library/unittest.html#load-tests-protocol)
+    """
+    return ProviderTestCaseGenerator(PROVIDER_TESTS).generate_tests()

+ 70 - 0
test/helpers.py

@@ -0,0 +1,70 @@
+import unittest
+from cloudbridge.providers.factory import CloudProviderFactory
+
+
+class ProviderTestBase(object):
+
+    """
+    A dummy base class for Test Cases. Does not inherit from unittest.TestCase
+    to avoid confusing test discovery by unittest and nose2. unittest.TestCase
+    is injected as a base class by the generator, so calling the unittest constructor
+    works correctly.
+    """
+
+    def __init__(self, methodName, provider):
+        unittest.TestCase.__init__(self, methodName=methodName)
+        self.provider = provider
+
+
+class ProviderTestCaseGenerator():
+
+    """
+    Generates test cases for all provider - testcase combinations.
+    Detailed docs at test/__init__.py
+    """
+
+    def __init__(self, test_classes):
+        self.all_test_classes = test_classes
+
+    def create_provider_instance(self, provider_class):
+        """
+        Instantiate a default provider instance. All required connection settings
+        are expected to be set as environment variables.
+        """
+        return provider_class({})
+
+    def generate_test_suite_for_provider_testcase(self, provider_class, testcase_class):
+        """
+        Generate and return a suite of tests for a specific provider class and testcase
+        combination
+        """
+        testloader = unittest.TestLoader()
+        testnames = testloader.getTestCaseNames(testcase_class)
+        suite = unittest.TestSuite()
+        for name in testnames:
+            generated_cls = type(
+                "test" + provider_class.__name__ + str(testcase_class.__name__), (testcase_class, unittest.TestCase), {})
+            suite.addTest(
+                generated_cls(name, self.create_provider_instance(provider_class)))
+        return suite
+
+    def generate_test_suite_for_provider(self, provider_class):
+        """
+        Generate and return a suite of all available tests for a given provider class
+        """
+        suite = unittest.TestSuite()
+        suites = map(lambda test_class: self.generate_test_suite_for_provider_testcase(
+            provider_class, test_class), self.all_test_classes)
+        map(suite.addTest, suites)
+        return suite
+
+    def generate_tests(self):
+        """
+        Generate and return a suite of tests for all provider and test class combinations
+        """
+        factory = CloudProviderFactory()
+        provider_classes = factory.get_all_provider_classes()
+        suite = unittest.TestSuite()
+        suites = map(self.generate_test_suite_for_provider, provider_classes)
+        map(suite.addTest, suites)
+        return suite

+ 25 - 0
test/testprovidersecurityservice.py

@@ -0,0 +1,25 @@
+import unittest
+from cloudbridge.providers.factory import CloudProviderFactory
+from cloudbridge.providers.factory import ProviderList
+from cloudbridge.providers import interfaces
+from helpers import ProviderTestBase
+
+
+class ProviderSecurityServiceTestCase(ProviderTestBase):
+
+    def __init__(self, methodName, provider):
+        super(ProviderSecurityServiceTestCase, self).__init__(
+            methodName=methodName, provider=provider)
+
+    def test_list_key_pairs(self):
+        key_pairs = self.provider.security.list_key_pairs()
+        # Assume there's always one keypair at least
+        self.assertIsInstance(key_pairs[0], interfaces.KeyPair)
+        self.assertIsNotNone(key_pairs[0].name)
+
+    def test_crud_security_groups(self):
+        #groups = self.provider.security.create_security_group()
+        groups = self.provider.security.list_security_groups()
+        # Assume there's always one keypair at least
+#         self.assertIsInstance(groups[0], interfaces.KeyPair)
+#         self.assertIsNotNone(key_pairs[0].name)

+ 0 - 39
tests/TestProviderSecurityService.py

@@ -1,39 +0,0 @@
-"""
-Test the functionality of the CloudBridge API.
-
-These tests require working credentials exported as environment variables for
-supported cloud infrastructure.
-
-Use ``nosetests`` to run these unit tests.
-"""
-import unittest
-from cloudbridge.providers.factory import CloudProviderFactory
-from cloudbridge.providers.factory import ProviderList
-from cloudbridge.providers import interfaces
-
-
-class TestProviderSecurityService_EC2(unittest.TestCase):
-
-    def setUp(self):
-        config = {}
-        self.provider = CloudProviderFactory().create_provider(
-            ProviderList.EC2, config)
-
-    def test_list_key_pairs(self):
-        key_pairs = self.provider.security.list_key_pairs()
-        # Assume there's always one keypair at least
-        assert(isinstance(key_pairs[0], interfaces.KeyPair))
-
-
-class TestProviderSecurityService_OS(unittest.TestCase):
-
-    def setUp(self):
-        config = {}
-        self.provider = CloudProviderFactory().create_provider(
-            ProviderList.OPENSTACK, config)
-
-    def test_list_key_pairs(self):
-        key_pairs = self.provider.security.list_key_pairs()
-        # Assume there's always one keypair at least
-        self.assertIsInstance(key_pairs[0], interfaces.KeyPair)
-        self.assertIsNotNone(key_pairs[0].name)