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