[Checkins] SVN: zope.component/branches/sylvain-zcmltestlayer/src/zope/component/test Intermediate checkin, so we have a ZCMLFileLayer and ZCMLStringLayer.

Martijn Faassen faassen at startifact.com
Thu Jan 21 10:05:17 EST 2010


Log message for revision 108357:
  Intermediate checkin, so we have a ZCMLFileLayer and ZCMLStringLayer.
  Tests are coming next.
  

Changed:
  U   zope.component/branches/sylvain-zcmltestlayer/src/zope/component/testlayer.py
  A   zope.component/branches/sylvain-zcmltestlayer/src/zope/component/testlayer.txt
  U   zope.component/branches/sylvain-zcmltestlayer/src/zope/component/tests.py

-=-
Modified: zope.component/branches/sylvain-zcmltestlayer/src/zope/component/testlayer.py
===================================================================
--- zope.component/branches/sylvain-zcmltestlayer/src/zope/component/testlayer.py	2010-01-21 15:03:40 UTC (rev 108356)
+++ zope.component/branches/sylvain-zcmltestlayer/src/zope/component/testlayer.py	2010-01-21 15:05:17 UTC (rev 108357)
@@ -16,29 +16,106 @@
 
 from zope.configuration import xmlconfig, config
 from zope.testing.cleanup import cleanUp
+from zope.component.hooks import setHooks
 
-class ZCMLLayer(object):
-    """Base layer in order to load a ZCML configuration.
+class LayerBase(object):
+    """Sane layer base class.
+
+    zope.testing implements an advanced mechanism so that layer setUp,
+    tearDown, testSetUp and testTearDown code gets called in the right
+    order. These methods are supposed to be @classmethods and should
+    not use super() as the test runner is supposed to take care of that.
+
+    In practice, this mechanism turns out not to be useful and
+    overcomplicated.  It becomes difficult to pass information into
+    layers (such as a ZCML file to load), because the only way to pass
+    in information is to subclass, and subclassing these layers leads
+    to a range of interactions that is hard to reason about.
+
+    We'd rather just use Python and the super mechanism, as we know how
+    to reason about that. This base class is a hack to make this
+    possible.
+
+    The hack requires us to set __bases__, __module__ and
+    __name__. This fools zope.testing into thinking that this layer
+    instance is a class it can work with.
+    
+    It'd be better if zope.testing just called a minimal API and
+    didn't try to be fancy. Fancy layer inheritance mechanisms can
+    then be implemented elsewhere if people want to. But unfortunately
+    it does implement a fancy mechanism and we need to fool it.
     """
-
+    
     __bases__ = ()
 
-    def __init__(self, package, name=None, zcml_file='ftesting.zcml'):
+    def __init__(self, package, name=None):
         if name is None:
             name = self.__class__.__name__
         self.__name__ = name
         self.__module__ = package.__name__
-        self.zcml_file = os.path.join(
-            os.path.dirname(package.__file__), zcml_file)
-        self.features = ()
 
     def setUp(self):
-        zope.component.hooks.setHooks()
+        pass
+
+    def tearDown(self):
+        pass
+
+    def testSetUp(self):
+        pass
+
+    def testTearDown(self):
+        pass
+
+class ZCMLLayerBase(LayerBase):
+    """Base class to load up some ZCML.
+    """
+    def __init__(self, package, name=None, features=None):
+        super(ZCMLLayerBase, self).__init__(package, name)
+        self.features = features or []
+
+    def setUp(self):
+        setHooks()
         context = config.ConfigurationMachine()
         xmlconfig.registerCommonDirectives(context)
         for feature in self.features:
             context.provideFeature(feature)
-        context = xmlconfig.file(self.zcml_file, context=context, execute=True)
+        self._load_zcml(context)
 
     def tearDown(self):
         cleanUp()
+
+    def _load_zcml(self, context):
+        raise NotImplementedError
+    
+class ZCMLStringLayer(ZCMLLayerBase):
+    """This layer can be used to run tests with a ZCML string loaded.
+
+    The ZCML string is assumed to include sufficient (meta)configuration
+    so that it can be interpreted itself. I.e. to create a ZCMLLayer
+    based on another ZCMLLayer's ZCML, just use a ZCML include
+    statement in your own ZCML to load it.
+    """
+    def __init__(self, package, name=None, zcml_string=None,
+                 features=None):
+        super(ZCMLStringLayer, self).__init__(package, name, features)
+        self.zcml_string = zcml_string
+
+    def _load_zcml(self, context):
+        xmlconfig.string(self.zcml_string, context=context, execute=True)
+
+class ZCMLFileLayer(ZCMLLayerBase):
+    """This layer can be used to run tests with a ZCML file loaded.
+
+    The ZCML file is assumed to include sufficient (meta)configuration
+    so that it can be interpreted itself. I.e. to create a ZCMLLayer
+    based on another ZCMLLayer's ZCML, just use a ZCML include
+    statement in your own ZCML to load it.
+    """
+    def __init__(self, package, name=None, zcml_file='ftesting.zcml',
+                 features=None):
+        super(ZCMLFileLayer, self).__init__(package, name, features)
+        self.zcml_file = os.path.join(os.path.dirname(package.__file__),
+                                      zcml_file)
+
+    def _load_zcml(self, context):
+        xmlconfig.file(self.zcml_file, context=context, execute=True)

Added: zope.component/branches/sylvain-zcmltestlayer/src/zope/component/testlayer.txt
===================================================================
--- zope.component/branches/sylvain-zcmltestlayer/src/zope/component/testlayer.txt	                        (rev 0)
+++ zope.component/branches/sylvain-zcmltestlayer/src/zope/component/testlayer.txt	2010-01-21 15:05:17 UTC (rev 108357)
@@ -0,0 +1,70 @@
+Layers
+======
+
+zope.component.testlayer defines two things:
+
+* a LayerBase that makes it easier and saner to use zope.testing's
+  test layers.
+
+* a ZCMLLayer which lets you implement a layer that loads up some
+  ZCML.
+
+LayerBase
+---------
+
+We check whether our LayerBase can be used to create layers of our
+own. We do this simply by subclassing::
+
+  >>> from zope.component.testlayer import LayerBase
+  >>> class OurLayer(LayerBase):
+  ...     def setUp(self):
+  ...         super(OurLayer, self).setUp()
+  ...         print "setUp called"
+  ...     def tearDown(self):
+  ...         super(OurLayer, self).tearDown()
+  ...         print "tearDown called"
+  ...     def testSetUp(self):
+  ...         super(OurLayer, self).testSetUp()
+  ...         print "testSetUp called"
+  ...     def testTearDown(self):
+  ...         super(OurLayer, self).testTearDown()
+  ...         print "testTearDown called"
+
+Note that if we wanted to ensure that the methods of the superclass
+were called we have to use super(). In this case we actually wouldn't
+need to, as these methods do nothing at all, but we just ensure that
+they are there in the first place.
+
+Let's instantiate our layer. We need to supply it with the package the
+layer is defined in::
+
+  >>> import zope.component
+  >>> layer = OurLayer(zope.component)
+
+Now we run some tests with this layer::
+
+  >>> import unittest
+  >>> class TestCase(unittest.TestCase):
+  ...    layer = layer
+  ...    
+  ...    def testFoo(self):
+  ...        print "testFoo"
+  >>> suite = unittest.TestSuite()
+  >>> suite.addTest(unittest.makeSuite(TestCase))
+  >>> from zope.testing.testrunner.runner import Runner
+  >>> runner = Runner(found_suites=[suite])
+  >>> succeeded = runner.run()
+  Running zope.component.OurLayer tests:
+    Set up zope.component.OurLayer setUp called
+  in ... seconds.
+  testSetUp called
+  testFoo
+  testTearDown called
+    Ran 1 tests with 0 failures and 0 errors in ... seconds.
+  Tearing down left over layers:
+    Tear down zope.component.OurLayer tearDown called
+  in ... seconds.
+
+ZCMLLayer
+---------
+

Modified: zope.component/branches/sylvain-zcmltestlayer/src/zope/component/tests.py
===================================================================
--- zope.component/branches/sylvain-zcmltestlayer/src/zope/component/tests.py	2010-01-21 15:03:40 UTC (rev 108356)
+++ zope.component/branches/sylvain-zcmltestlayer/src/zope/component/tests.py	2010-01-21 15:05:17 UTC (rev 108357)
@@ -1706,6 +1706,10 @@
                              setUp=setUp, tearDown=tearDown),
         doctest.DocFileSuite('zcml.txt', checker=checker,
                              setUp=setUp, tearDown=tearDown),
+        doctest.DocFileSuite('testlayer.txt',
+                             optionflags=(doctest.ELLIPSIS +
+                                          doctest.NORMALIZE_WHITESPACE +
+                                          doctest.REPORT_NDIFF)),
         zcml_conditional,
         hooks_conditional,
         unittest.makeSuite(StandaloneTests),



More information about the checkins mailing list