From: Martin A. <svn...@pl...> - 2010-05-26 15:38:54
|
Author: optilude Date: Wed May 26 15:38:47 2010 New Revision: 36739 Modified: plone.app.testing/trunk/README.txt plone.app.testing/trunk/plone/app/testing/helpers.py plone.app.testing/trunk/plone/app/testing/helpers.txt plone.app.testing/trunk/plone/app/testing/layers.py Log: Better GenericSetup registry sandboxing Modified: plone.app.testing/trunk/README.txt ============================================================================== --- plone.app.testing/trunk/README.txt (original) +++ plone.app.testing/trunk/README.txt Wed May 26 15:38:47 2010 @@ -467,7 +467,10 @@ _import_step_registry.unregisterStep('import-step-id') _export_step_registry.unregisterStep('export-step-id') - + + **Also note:** If you use the ``PloneSandboxLayer`` layer base class, + this will snapshot the registries and tear them down for you. + ``tearDownMultiPluginRegistration(pluginName)`` PluggableAuthService "MultiPlugins" are kept in a global registry. If you have registered a plugin, e.g. using the ``registerMultiPlugin()`` @@ -517,8 +520,8 @@ On tear-down, you will then want to: -1. Remove any GenericSetup profiles that were loaded during setup from the - global registry. +1. Remove any GenericSetup profiles and import/export steps that were loaded + into the global registries during setup. 2. Pop the global component registry to unregister components loaded via ZCML. @@ -528,7 +531,7 @@ tear-down, you'll also want to tear those down explicitly here. Stacking a demo storage and component registry and snapshotting the -GenericSetup profile registry is the easiest way to avoid fixtures bleeding +GenericSetup profile registry is the safest way to avoid fixtures bleeding between tests. However, it can be tricky to ensure that everything happens in the right order. Modified: plone.app.testing/trunk/plone/app/testing/helpers.py ============================================================================== --- plone.app.testing/trunk/plone/app/testing/helpers.py (original) +++ plone.app.testing/trunk/plone/app/testing/helpers.py Wed May 26 15:38:47 2010 @@ -281,7 +281,7 @@ # Push a new database storage so that database changes # commited during layer setup can be easily torn down - self['zodbDB'] = zodb.stackDemoStorage(self.get('zodbDB'), name='HelperDemos') + self['zodbDB'] = zodb.stackDemoStorage(self.get('zodbDB'), name=self.__name__) with ploneSite() as portal: @@ -293,13 +293,18 @@ # the custom configuration from Products.GenericSetup.registry import _profile_registry - preSetupProfiles = _profile_registry._profile_ids[:] + from Products.GenericSetup.registry import _import_step_registry + from Products.GenericSetup.registry import _export_step_registry + + preSetupProfiles = list(_profile_registry._profile_ids) + preSetupImportSteps = list(_import_step_registry.listSteps()) + preSetupExportSteps = list(_export_step_registry.listSteps()) # Call template method - must be implemented by subclasses self.setUpPloneSite(portal) # Keep track of profiles that were added during setup - self.snapshotProfileRegistry(preSetupProfiles) + self.snapshotProfileRegistry(preSetupProfiles, preSetupImportSteps, preSetupExportSteps) def tearDown(self): @@ -322,27 +327,50 @@ # Helpers - def snapshotProfileRegistry(self, preSetupProfiles): + def snapshotProfileRegistry(self, preSetupProfiles, preSetupImportSteps, preSetupExportSteps): """Save a snapshot of all profiles that were added during setup, by comparing to the list of profiles passed in. """ self._addedProfiles = set() + self._addedImportSteps = set() + self._addedExportSteps = set() from Products.GenericSetup.registry import _profile_registry + from Products.GenericSetup.registry import _import_step_registry + from Products.GenericSetup.registry import _export_step_registry + for profileId in _profile_registry._profile_ids: if profileId not in preSetupProfiles: self._addedProfiles.add(profileId) + for stepId in _import_step_registry.listSteps(): + if stepId not in preSetupImportSteps: + self._addedImportSteps.add(stepId) + + for stepId in _export_step_registry.listSteps(): + if stepId not in preSetupExportSteps: + self._addedExportSteps.add(stepId) + def tearDownProfileRegistry(self): """Delete all profiles that were added during setup, as stored by ``snapshotProfileRegistry()``. """ from Products.GenericSetup.registry import _profile_registry + from Products.GenericSetup.registry import _import_step_registry + from Products.GenericSetup.registry import _export_step_registry for profileId in self._addedProfiles: if profileId in _profile_registry._profile_ids: _profile_registry._profile_ids.remove(profileId) if profileId in _profile_registry._profile_info: del _profile_registry._profile_info[profileId] + + for stepId in self._addedImportSteps: + if stepId in _import_step_registry.listSteps(): + _import_step_registry.unregisterStep(stepId) + + for stepId in self._addedExportSteps: + if stepId in _export_step_registry.listSteps(): + _export_step_registry.unregisterStep(stepId) Modified: plone.app.testing/trunk/plone/app/testing/helpers.txt ============================================================================== --- plone.app.testing/trunk/plone/app/testing/helpers.txt (original) +++ plone.app.testing/trunk/plone/app/testing/helpers.txt Wed May 26 15:38:47 2010 @@ -231,6 +231,15 @@ ... # Make some persistent changes ... portal.title = u"New title" ... + ... # Add some entries to the GenericSetup global registries + ... from Products.GenericSetup.registry import _profile_registry + ... from Products.GenericSetup.registry import _import_step_registry + ... from Products.GenericSetup.registry import _export_step_registry + ... + ... _profile_registry.registerProfile('dummy1', u"My package", u"", ".", 'plone.app.testing') + ... _import_step_registry.registerStep('import1', version=1, handler='plone.app.testing.tests.dummy', title=u"Dummy import step", description=u"") + ... _export_step_registry.registerStep('export1', handler='plone.app.testing.tests.dummy', title=u"Dummy import step", description=u"") + ... ... # Make some other global changes not stored in the ZODB or ... # the global component registry ... someGlobal['test'] = 1 @@ -242,15 +251,17 @@ >>> MY_LAYER = MyLayer() Here, we have derived from ``PloneSandboxLayer`` instead of the more usual -``Layer`` base class. This layer implements the sandboxing for us, and -delegates to two template methods: ``setUpPloneSite()`` and +``Layer`` base class. This layer implements the sandboxing of the ZODB, global +component registry, and GenericSetup profile and import/export step registries +for us, and delegates to two template methods: ``setUpPloneSite()`` and ``tearDownPloneSite()``. Both take a configured ``portal`` object as an argument, giving access to the Plone site root. You *must* implement ``setUpPloneSite()``. Implementing ``tearDownPloneSite()`` is optional. If all the state modified during layer -setup is saved in the ZODB and/or the global component registry only, the -standard tear-down will suffice. Other state must be cleaned up explicitly. +setup is saved in the ZODB, the global component registry and/or the global +GenericSetup profile/import/export step registries only, the standard +tear-down will suffice. Other state must be cleaned up explicitly. You may also wish to change the ``defaultBases`` argument. The default is to use ``PLONE_INTEGRATION_TESTING`` as the single default base layer. @@ -281,6 +292,22 @@ >>> someGlobal['test'] 1 + >>> from Products.GenericSetup.registry import _profile_registry + >>> from Products.GenericSetup.registry import _import_step_registry + >>> from Products.GenericSetup.registry import _export_step_registry + + >>> numProfiles = len(_profile_registry.listProfiles()) + >>> 'plone.app.testing:dummy1' in _profile_registry.listProfiles() + True + + >>> numImportSteps = len(_import_step_registry.listSteps()) + >>> 'import1' in _import_step_registry.listSteps() + True + + >>> numExportSteps = len(_export_step_registry.listSteps()) + >>> 'export1' in _export_step_registry.listSteps() + True + We'll now tear down just the MY_LAYER layer. At this point, we should still have a Plone site, but none of the changes from our layer. @@ -297,6 +324,21 @@ >>> 'test' in someGlobal False + >>> len(_profile_registry.listProfiles()) == numProfiles - 1 + True + >>> 'plone.app.testing:dummy1' in _profile_registry.listProfiles() + False + + >>> len(_import_step_registry.listSteps()) == numImportSteps - 1 + True + >>> 'import1' in _import_step_registry.listSteps() + False + + >>> len(_export_step_registry.listSteps()) == numExportSteps - 1 + True + >>> 'export1' in _export_step_registry.listSteps() + False + Let's tear down the rest of the layers too. >>> runner.tear_down_unneeded(options, [], setupLayers) Modified: plone.app.testing/trunk/plone/app/testing/layers.py ============================================================================== --- plone.app.testing/trunk/plone/app/testing/layers.py (original) +++ plone.app.testing/trunk/plone/app/testing/layers.py Wed May 26 15:38:47 2010 @@ -98,8 +98,15 @@ # Stack a new DemoStorage on top of the one from z2.STARTUP. self['zodbDB'] = zodb.stackDemoStorage(self.get('zodbDB'), name='PloneSite') + # Keep track of the GenericSetup registries so that we can snapshot + # the changes from Products.GenericSetup.registry import _profile_registry - preSetupProfiles = _profile_registry._profile_ids[:] + from Products.GenericSetup.registry import _import_step_registry + from Products.GenericSetup.registry import _export_step_registry + + preSetupProfiles = list(_profile_registry._profile_ids) + preSetupImportSteps = list(_import_step_registry.listSteps()) + preSetupExportSteps = list(_export_step_registry.listSteps()) self.setUpZCML() @@ -108,8 +115,9 @@ self.setUpProducts(app) self.setUpDefaultContent(app) - self.snapshotProfileRegistry(preSetupProfiles) - + # Record the changes to the GenericSetup registries + self.snapshotProfileRegistry(preSetupProfiles, preSetupImportSteps, preSetupExportSteps) + def tearDown(self): # Tear down products @@ -124,30 +132,53 @@ self['zodbDB'].close() del self['zodbDB'] - def snapshotProfileRegistry(self, preSetupProfiles): + def snapshotProfileRegistry(self, preSetupProfiles, preSetupImportSteps, preSetupExportSteps): """Save a snapshot of all profiles that were added during setup, by comparing to the list of profiles passed in. """ self._addedProfiles = set() + self._addedImportSteps = set() + self._addedExportSteps = set() from Products.GenericSetup.registry import _profile_registry + from Products.GenericSetup.registry import _import_step_registry + from Products.GenericSetup.registry import _export_step_registry + for profileId in _profile_registry._profile_ids: if profileId not in preSetupProfiles: self._addedProfiles.add(profileId) + for stepId in _import_step_registry.listSteps(): + if stepId not in preSetupImportSteps: + self._addedImportSteps.add(stepId) + + for stepId in _export_step_registry.listSteps(): + if stepId not in preSetupExportSteps: + self._addedExportSteps.add(stepId) + def tearDownProfileRegistry(self): """Delete all profiles that were added during setup, as stored by ``snapshotProfileRegistry()``. """ from Products.GenericSetup.registry import _profile_registry + from Products.GenericSetup.registry import _import_step_registry + from Products.GenericSetup.registry import _export_step_registry for profileId in self._addedProfiles: if profileId in _profile_registry._profile_ids: _profile_registry._profile_ids.remove(profileId) if profileId in _profile_registry._profile_info: del _profile_registry._profile_info[profileId] + + for stepId in self._addedImportSteps: + if stepId in _import_step_registry.listSteps(): + _import_step_registry.unregisterStep(stepId) + + for stepId in self._addedExportSteps: + if stepId in _export_step_registry.listSteps(): + _export_step_registry.unregisterStep(stepId) def setUpZCML(self): """Stack a new global registry and load ZCML configuration of Plone |