ZopeTestCase and packages

Please put ZopeTestCase out of my misery

In this wonderful world between Zope 2 and 3, called limbo... I mean Five, there's a fun little trap concerning ZCML, packages as products and ZopeTestCase.  I wanted to document it somewhere so here it is.

If you're using packages as products, then to install the package as a product for tests, you'll need the ZCML of the package to be loaded.  If the package happens to be included in the configure.zcml of a product,then you'll need Five's loadProducts to have been run in order to install the package as a product.  With ZopeTestCase, in order for a product to be available for Five's loadProducts, installProduct must be called before loadProducts is run.  Five's loadProducts is usually run in the instance's site.zcml which for Plone tests is usually loaded by the ZCML layer.

The end result is that all installProduct calls must be made *before* loadProducts is run which in turn must be run before any installPackage calls can be made if you do any including of packages as products in product configure.zcml files.

Admittedly, this problem goes away if you don't include the ZCML for packages as products inside a product's ZCML.

If anyone is interested here's an example of using layers to work around this:

from Testing import ZopeTestCase
from Products.PloneTestCase import layer

ADDONS = [
    # Your product dependencies here
    ]

class InstallProducts(object):
    """Install products before the ZCML layer so that their ZCML will
    be loaded"""

    @classmethod
    def setUp(cls):
        for dep in ADDONS:
            if ZopeTestCase.hasProduct(dep):
                ZopeTestCase.installProduct(dep)
    
    @classmethod
    def tearDown(cls):
        pass

    @classmethod
    def testSetUp(cls):
        pass

    @classmethod
    def testTearDown(cls):
        pass

class InstallPackages(InstallProducts, layer.ZCML):
    """Install packages after the ZCML layer so that products will
    have had a chance to include the package ZCML"""

    @classmethod
    def setUp(cls):
        for dep in ADDONS:
            if ZopeTestCase.hasPackage(dep):
                ZopeTestCase.installPackage(dep)
    
    @classmethod
    def tearDown(cls):
        pass

    @classmethod
    def testSetUp(cls):
        pass

    @classmethod
    def testTearDown(cls):
        pass

Updated on 22 November 2008

Imported from Plone on Mar 15, 2021. The date for this update is the last modified date in Plone.

Comments

comments powered by Disqus