Rev 49: Allows new local test servers to implemented incrementally. in http://bazaar.launchpad.net/%7Evila/bzr/local-test-server

Vincent Ladeuil v.ladeuil+lp at free.fr
Mon Feb 9 11:03:16 GMT 2009


At http://bazaar.launchpad.net/%7Evila/bzr/local-test-server

------------------------------------------------------------
revno: 49
revision-id: v.ladeuil+lp at free.fr-20090209110313-1iy63hc7j8ceov8i
parent: v.ladeuil+lp at free.fr-20081001125107-i9rbq4xbhlgahwt8
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: local-test-server
timestamp: Mon 2009-02-09 12:03:13 +0100
message:
  Allows new local test servers to implemented incrementally.
  
  * tests/test_utils.py:
  (TestConfig, TestLocalTestServer): Splitted from TestLocalServer
  so that scenarios can be built incrementally.
  (ServerAdapter): Deleted.
  (full_scenarios, filter_scenarios_defining): Are enough to replace
  ServerAdapter and all its uses while providing a finer control on
  what attributes are provided.
  (TestFilterScenariosDefining): Associated tests.
  
  * tests/test_test_server.py:
  (load_tests): Get rid of the ServerAdapter.
  (TestFeature, TestTestServer): Use the more precise
  test_utils.TestLocalTestServer.
  
  * tests/test_server.py:
  (load_tests):  Get rid of the ServerAdapter.
  
  * tests/test_config.py:
  (load_tests): Get rid of the ServerAdapter.
  (TestConfig, TestConfigApache2): Use the more precise
  test_utils.TestConfig.
  
  * tests/__init__.py:
  (load_tests): Add test_utils.
-------------- next part --------------
=== modified file 'tests/__init__.py'
--- a/tests/__init__.py	2008-05-30 07:57:14 +0000
+++ b/tests/__init__.py	2009-02-09 11:03:13 +0000
@@ -16,6 +16,7 @@
 
 def load_tests(basic_tests, module, loader):
     testmod_names = [
+        'test_utils',
         'test_commands',
         'test_config',
         'test_server',

=== modified file 'tests/test_config.py'
--- a/tests/test_config.py	2008-06-24 20:06:35 +0000
+++ b/tests/test_config.py	2009-02-09 11:03:13 +0000
@@ -35,17 +35,20 @@
 
 
 def load_tests(standard_tests, module, loader):
-    # one for each server
-    s_adapter = test_utils.ServerAdapter()
-    s_classes = (TestConfig)
-    is_testing_for_servers = tests.condition_isinstance(s_classes)
-
     result = loader.suiteClass()
-    for test_class in tests.iter_suite_tests(standard_tests):
-        if is_testing_for_servers(test_class):
-            result.addTests(s_adapter.adapt(test_class))
-        else:
-            result.addTest(test_class)
+    remaining_tests = standard_tests
+    # one for each server config
+    c_tests, remaining_tests = tests.split_suite_by_condition(
+        remaining_tests, tests.condition_isinstance((TestConfig)))
+    adapter = tests.TestScenarioApplier()
+    adapter.scenarios = test_utils.filter_scenarios_defining(
+        ['_server_name',
+         '_config_class',
+         ])
+    tests.adapt_tests(c_tests, adapter, result)
+
+    # No parametrization for the remaining tests
+    result.addTests(remaining_tests)
 
     return result
 
@@ -75,7 +78,7 @@
         self.failUnlessExists(self._abspath('baz'))
 
 
-class TestConfig(tests.TestCaseInTempDir, test_utils.TestLocalServer,
+class TestConfig(tests.TestCaseInTempDir, test_utils.TestConfig,
                  TestConfigMixin):
 
     def _expand(self, template):
@@ -113,7 +116,7 @@
         self._check_conf_path(conf, 'data_dir', 'data')
 
 
-class TestConfigApache2(tests.TestCaseInTempDir, test_utils.TestLocalServer,
+class TestConfigApache2(tests.TestCaseInTempDir, test_utils.TestConfig,
                         TestConfigMixin):
 
     _server_name = 'apache2'

=== modified file 'tests/test_server.py'
--- a/tests/test_server.py	2008-06-26 15:35:37 +0000
+++ b/tests/test_server.py	2009-02-09 11:03:13 +0000
@@ -34,17 +34,21 @@
 
 
 def load_tests(standard_tests, module, loader):
+    result = loader.suiteClass()
+    remaining_tests = standard_tests
     # one for each server
-    s_adapter = test_utils.ServerAdapter()
-    s_classes = (TestServer,)
-    is_testing_for_servers = tests.condition_isinstance(s_classes)
+    s_tests, remaining_tests = tests.split_suite_by_condition(
+        remaining_tests, tests.condition_isinstance((TestServer)))
+    adapter = tests.TestScenarioApplier()
+    adapter.scenarios = test_utils.filter_scenarios_defining(
+        ['_server_name',
+         '_config_class',
+         '_server_class',
+         ])
+    tests.adapt_tests(s_tests, adapter, result)
 
-    result = loader.suiteClass()
-    for test_class in tests.iter_suite_tests(standard_tests):
-        if is_testing_for_servers(test_class):
-            result.addTests(s_adapter.adapt(test_class))
-        else:
-            result.addTest(test_class)
+    # No parametrization for the remaining tests
+    result.addTests(remaining_tests)
 
     return result
 

=== modified file 'tests/test_test_server.py'
--- a/tests/test_test_server.py	2008-06-24 20:06:35 +0000
+++ b/tests/test_test_server.py	2009-02-09 11:03:13 +0000
@@ -35,22 +35,30 @@
 
 
 def load_tests(standard_tests, module, loader):
-    # one for each server
-    s_adapter = test_utils.ServerAdapter()
-    s_classes = (TestFeature, TestTestServer)
-    is_testing_for_servers = tests.condition_isinstance(s_classes)
-
     result = loader.suiteClass()
-    for test_class in tests.iter_suite_tests(standard_tests):
-        if is_testing_for_servers(test_class):
-            result.addTests(s_adapter.adapt(test_class))
-        else:
-            result.addTest(test_class)
+    remaining_tests = standard_tests
+    # one for each test server
+    ts_tests, remaining_tests = tests.split_suite_by_condition(
+        remaining_tests, tests.condition_isinstance(
+            (TestFeature,
+             TestTestServer)))
+    adapter = tests.TestScenarioApplier()
+    adapter.scenarios = test_utils.filter_scenarios_defining(
+        ['_server_name',
+         '_config_class',
+         '_server_class',
+         '_server_feature_class',
+         '_test_server_class',
+         ])
+    tests.adapt_tests(ts_tests, adapter, result)
+
+    # No parametrization for the remaining tests
+    result.addTests(remaining_tests)
 
     return result
 
 
-class TestFeature(tests.TestCaseInTempDir, test_utils.TestLocalServer):
+class TestFeature(tests.TestCaseInTempDir, test_utils.TestLocalTestServer):
 
     def test_server_feature_not_available(self):
         feature = self._get_server_feature()
@@ -63,7 +71,7 @@
         self.assertTrue(feature.available())
 
 
-class TestTestServer(tests.TestCaseInTempDir, test_utils.TestLocalServer):
+class TestTestServer(tests.TestCaseInTempDir, test_utils.TestLocalTestServer):
 
     def test_server_setup_and_teardown(self):
         ts = self._get_test_server()

=== modified file 'tests/test_utils.py'
--- a/tests/test_utils.py	2008-10-01 12:51:07 +0000
+++ b/tests/test_utils.py	2009-02-09 11:03:13 +0000
@@ -26,20 +26,17 @@
     )
 
 
-class TestLocalServer(object):
-    """Common basis for testing local test servers.
+class TestConfig(object):
+    """Common basis for testing local test server configurations.
 
-    This class provides some helpers to get access to testable configs, servers
-    and test servers.
+    
+    This class provides some helpers to get access to testable configs.
     """
 
     # The following must be set either by the daughter class or some
-    # TestScenarioApplier.
+    # scenario.
     _server_name = None
     _config_class = None
-    _server_class = None
-    _server_feature_class = None
-    _test_server_class = None
 
     def _get_config(self, *args, **kwargs):
         # provides a _base_dir so that all the server files are built into the
@@ -48,6 +45,17 @@
         kwargs['_base_dir'] = self.test_base_dir
         return self._config_class(*args,**kwargs)
 
+
+class TestLocalServer(TestConfig):
+    """Common basis for testing local servers.
+
+    This class provides some helpers to get access to testable configs and
+    servers.
+    """
+    # The following must be set either by the daughter class or some
+    # scenario.
+    _server_class = None
+
     def _get_server(self):
         klass = self._server_class
         if klass._server_command_name is not None:
@@ -59,6 +67,19 @@
                 raise tests.UnavailableFeature(klass)
         return klass(server._get_available_port(), self._get_config())
 
+
+class TestLocalTestServer(TestLocalServer):
+    """Common basis for testing local test servers.
+
+    This class provides some helpers to get access to testable configs, servers
+    and test servers (and their associated test features).
+    """
+
+    # The following must be set either by the daughter class or some
+    # scenario.
+    _server_feature_class = None
+    _test_server_class = None
+
     def _get_server_feature(self):
         feature = self._server_feature_class()
         # Override default server with a testing one
@@ -69,68 +90,111 @@
         return self._test_server_class(_server=self._get_server())
 
 
-class ServerAdapter(tests.TestScenarioApplier):
-    """Generate the same test for each server."""
+def full_scenarios():
+    """Returns the full scenarios to test local test servers.
 
-    def __init__(self):
-        server_scenarios = [
-            ('apache2', dict(
-                    _server_name='apache2',
-                    _config_class=config.Apache2,
-                    _server_class=server.Apache2,
-                    _server_feature_class=test_server.Apache2Feature,
-                    _test_server_class=test_server.Apache2,
-                    )),
-            ('apache2-dav', dict(
-                    _server_name='apache2-dav',
-                    _config_class=config.Apache2DAV,
-                    _server_class=server.Apache2DAV,
-                    _server_feature_class=test_server.Apache2DAVFeature,
-                    _test_server_class=test_server.Apache2DAV,
-                    )),
-            ('apache2-svn', dict(
-                    _server_name='apache2-svn',
-                    _config_class=config.Apache2SVN,
-                    _server_class=server.Apache2SVN,
-                    _server_feature_class=test_server.Apache2SVNFeature,
-                    _test_server_class=test_server.Apache2SVN,
-                    )),
-            ('cherokee', dict(
-                    _server_name='cherokee',
-                    _config_class=config.Cherokee,
-                    _server_class=server.Cherokee,
-                    _server_feature_class=test_server.CherokeeFeature,
-                    _test_server_class=test_server.Cherokee,
-                    )),
-            ('lighttpd', dict(
-                    _server_name='lighttpd',
-                    _config_class=config.Lighttpd,
-                    _server_class=server.Lighttpd,
-                    _server_feature_class=test_server.LighttpdFeature,
-                    _test_server_class=test_server.Lighttpd,
-                    )),
-            ('lighttpd-dav', dict(
-                    _server_name='lighttpd-dav',
-                    _config_class=config.LighttpdDAV,
-                    _server_class=server.LighttpdDAV,
-                    _server_feature_class=test_server.LighttpdDAVFeature,
-                    _test_server_class=test_server.LighttpdDAV,
-                    )),
-#            ('vsftpd', dict(
-#                    _server_name='vsftpd',
-#                    _config_class=config.Vsftpd,
-#                    _server_class=server.Vsftpd,
-#                    _server_feature_class=test_server.VsftpdFeature,
-#                    _test_server_class=test_server.Vsftpd,
-#                    )),
-#            ('proftpd', dict(
-#                    _server_name='proftpd',
-#                    _config_class=config.Proftpd,
-#                    _server_class=server.Proftpd,
-#                    _server_feature_class=test_server.ProftpdFeature,
+    Used with filter_scenarios_defining, it allows a local test server to be
+    defined in a single place while each category of tests can require only
+    part of the attributes. This helps implement new local test servers
+    incrementally (i.e. start by testing/creating the config, then the server
+    and finally the test server without providing all classes upfront).
+    """
+    scenarios = [
+        ('apache2', dict(
+                _server_name='apache2',
+                _config_class=config.Apache2,
+                _server_class=server.Apache2,
+                _server_feature_class=test_server.Apache2Feature,
+                _test_server_class=test_server.Apache2,
+                )),
+        ('apache2-dav', dict(
+                _server_name='apache2-dav',
+                _config_class=config.Apache2DAV,
+                _server_class=server.Apache2DAV,
+                _server_feature_class=test_server.Apache2DAVFeature,
+                _test_server_class=test_server.Apache2DAV,
+                )),
+        ('apache2-svn', dict(
+                _server_name='apache2-svn',
+                _config_class=config.Apache2SVN,
+                _server_class=server.Apache2SVN,
+                _server_feature_class=test_server.Apache2SVNFeature,
+                _test_server_class=test_server.Apache2SVN,
+                )),
+        ('cherokee', dict(
+                _server_name='cherokee',
+                _config_class=config.Cherokee,
+                _server_class=server.Cherokee,
+                _server_feature_class=test_server.CherokeeFeature,
+                _test_server_class=test_server.Cherokee,
+                )),
+        ('lighttpd', dict(
+                _server_name='lighttpd',
+                _config_class=config.Lighttpd,
+                _server_class=server.Lighttpd,
+                _server_feature_class=test_server.LighttpdFeature,
+                _test_server_class=test_server.Lighttpd,
+                )),
+        ('lighttpd-dav', dict(
+                _server_name='lighttpd-dav',
+                _config_class=config.LighttpdDAV,
+                _server_class=server.LighttpdDAV,
+                _server_feature_class=test_server.LighttpdDAVFeature,
+                _test_server_class=test_server.LighttpdDAV,
+                )),
+#        ('vsftpd', dict(
+#                _server_name='vsftpd',
+#                _config_class=config.Vsftpd,
+#                _server_class=server.Vsftpd,
+#                _server_feature_class=test_server.VsftpdFeature,
+#                _test_server_class=test_server.Vsftpd,
+#                )),
+#        ('proftpd', dict(
+#                _server_name='proftpd',
+#                _config_class=config.Proftpd,
+#                _server_class=server.Proftpd,
+#                _server_feature_class=test_server.ProftpdFeature,
 #                    _test_server_class=test_server.Proftpd,
-#                    )),
-            ]
-        self.scenarios = server_scenarios
-
-
+#                )),
+        ]
+    return scenarios
+
+
+def filter_scenarios_defining(wanted, _scenarios=full_scenarios()):
+    """Filters the scenarios returning dicts with only the desired attributes.
+
+    :param wanted: The key names to extract from the scenarios dict.
+
+    :param _scenarios: The scenarios to filter from (intended for tests only).
+
+    :return: The scenarios whose dicts contains the required attributes.
+    """
+    result = []
+    for name, d in _scenarios:
+        reduced = {}
+        missing_keys = False
+        for k in wanted:
+            try:
+                reduced[k] = d[k]
+            except KeyError:
+                missing_keys = True
+        if not missing_keys:
+            # if the scenario dict doesn't contain all required attributes, it
+            # is not included.
+            result.append((name, reduced))
+    return result
+
+
+class TestFilterScenariosDefining(tests.TestCase):
+
+    def test_filter_one_attribute_missing(self):
+        scenarios = [('foo', dict(name='foo')),
+                     ('bar', dict(name='bar', check=True))]
+        s = filter_scenarios_defining(['check', 'name'], scenarios)
+        self.assertEquals([('bar', dict(name='bar', check=True))], s)
+
+    def test_filter_all_attributes_present(self):
+        scenarios = [('foo', dict(name='foo', check=False)),
+                     ('bar', dict(name='bar', check=True))]
+        s = filter_scenarios_defining(['check', 'name'], scenarios)
+        self.assertEquals(scenarios, s)



More information about the bazaar-commits mailing list