[devtools] set .config in setUpClass instead of using a cache in a classproperty
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 20 May 2016 17:05:39 +0200
changeset 11270 a9dc97b87ced
parent 11269 73ac69970047
child 11271 fd177546bbea
[devtools] set .config in setUpClass instead of using a cache in a classproperty This is much clearer and avoid problem with py.test introspection that triggered creation and caching of the configuration before actual test execution. This caused pb in unittest_postgres.PostgresStatementTimeoutTC where configuration was built before module's setup, hence source configuration was missing information about where to find the pg cluster.
cubicweb/devtools/testlib.py
cubicweb/server/test/unittest_ldapsource.py
cubicweb/server/test/unittest_postgres.py
cubicweb/web/test/unittest_application.py
--- a/cubicweb/devtools/testlib.py	Fri May 20 12:01:42 2016 +0200
+++ b/cubicweb/devtools/testlib.py	Fri May 20 17:05:39 2016 +0200
@@ -313,6 +313,15 @@
     # anonymous is logged by default in cubicweb test cases
     anonymous_allowed = True
 
+    @classmethod
+    def setUpClass(cls):
+        test_module_file = sys.modules[cls.__module__].__file__
+        assert 'config' not in cls.__dict__, (
+            '%s has a config class attribute before entering setUpClass. '
+            'Let CubicWebTC.setUpClass instantiate it and modify it afterwards.' % cls)
+        cls.config = cls.configcls(cls.appid, test_module_file)
+        cls.config.mode = 'test'
+
     def __init__(self, *args, **kwargs):
         self._admin_session = None
         self.repo = None
@@ -365,24 +374,6 @@
 
     # config management ########################################################
 
-    @classproperty
-    def config(cls):
-        """return the configuration object
-
-        Configuration is cached on the test class.
-        """
-        if cls is CubicWebTC:
-            # Prevent direct use of CubicWebTC directly to avoid database
-            # caching issues
-            return None
-        try:
-            return cls.__dict__['_config']
-        except KeyError:
-            test_module_file = sys.modules[cls.__module__].__file__
-            config = cls._config = cls.configcls(cls.appid, test_module_file)
-            config.mode = 'test'
-            return config
-
     @classmethod  # XXX could be turned into a regular method
     def init_config(cls, config):
         """configuration initialization hooks.
@@ -441,6 +432,9 @@
     # default test setup and teardown #########################################
 
     def setUp(self):
+        assert hasattr(self, 'config'), (
+            'It seems that CubicWebTC.setUpClass has not been called. '
+            'Missing super() call in %s?' % self.setUpClass)
         # monkey patch send mail operation so emails are sent synchronously
         self._patch_SendMailOp()
         previous_failure = self.__class__.__dict__.get('_repo_init_failed')
--- a/cubicweb/server/test/unittest_ldapsource.py	Fri May 20 12:01:42 2016 +0200
+++ b/cubicweb/server/test/unittest_ldapsource.py	Fri May 20 17:05:39 2016 +0200
@@ -108,6 +108,10 @@
             sys.stdout.write(stdout)
             sys.stderr.write(stderr)
         config.info('DONE')
+    try:
+        shutil.rmtree(cls._tmpdir)
+    except:
+        pass
 
 
 class LDAPFeedTestBase(CubicWebTC):
@@ -116,6 +120,15 @@
 
     @classmethod
     def setUpClass(cls):
+        super(LDAPFeedTestBase, cls).setUpClass()
+        cls.init_slapd()
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.terminate_slapd()
+
+    @classmethod
+    def init_slapd(cls):
         for path in ('/usr/sbin/slapd',
                      '/usr/sbin/slapadd',
                      '/usr/bin/ldapmodify'):
@@ -126,12 +139,8 @@
         cls._tmpdir = create_slapd_configuration(cls)
 
     @classmethod
-    def tearDownClass(cls):
+    def terminate_slapd(cls):
         terminate_slapd(cls)
-        try:
-            shutil.rmtree(cls._tmpdir)
-        except:
-            pass
 
     @classmethod
     def pre_setup_database(cls, cnx, config):
@@ -461,8 +470,8 @@
 
         finally:
             # back to normal ldap setup
-            self.tearDownClass()
-            self.setUpClass()
+            self.terminate_slapd()
+            self.init_slapd()
 
     def test_group_member_deleted(self):
         with self.repo.internal_cnx() as cnx:
@@ -485,8 +494,8 @@
                 self.assertEqual(len(rset), 0, rset.rows)
         finally:
             # back to normal ldap setup
-            self.tearDownClass()
-            self.setUpClass()
+            self.terminate_slapd()
+            self.init_slapd()
 
 
 if __name__ == '__main__':
--- a/cubicweb/server/test/unittest_postgres.py	Fri May 20 12:01:42 2016 +0200
+++ b/cubicweb/server/test/unittest_postgres.py	Fri May 20 17:05:39 2016 +0200
@@ -153,6 +153,7 @@
 
     @classmethod
     def setUpClass(cls):
+        super(PostgresStatementTimeoutTC, cls).setUpClass()
         cls.orig_connect_hooks = lgdb.SQL_CONNECT_HOOKS['postgres'][:]
 
     @classmethod
--- a/cubicweb/web/test/unittest_application.py	Fri May 20 12:01:42 2016 +0200
+++ b/cubicweb/web/test/unittest_application.py	Fri May 20 17:05:39 2016 +0200
@@ -146,14 +146,10 @@
 
 class ApplicationTC(CubicWebTC):
 
-    @classproperty
-    def config(cls):
-        try:
-            return cls.__dict__['_config']
-        except KeyError:
-            config = super(ApplicationTC, cls).config
-            config.global_set_option('allow-email-login', True)
-            return config
+    @classmethod
+    def setUpClass(cls):
+        super(ApplicationTC, cls).setUpClass()
+        cls.config.global_set_option('allow-email-login', True)
 
     def test_cnx_user_groups_sync(self):
         with self.admin_access.client_cnx() as cnx: