Add Zope 2.12 compatibility to the testrunner

Configure the ZopeLite layer, enabling conditional product installation.

Conditionally load zcml on Zope 2.12 and delay the optimize and fortify calls
until after Product initialization by the layer.

Disable printing of profiling information on Zope 2.12 since profiling support
on ZopeTestCase has been removed.

Import copyzopeskel from its proper location on Zope 2.12 (this has a side-
effect of changing slightly the beginning of the test output, suppressing the
"Loading Zope, please stand by ..." initial message). Additionally, add a Zope
2.12 compatible skeleton.

Make sure the skin is configured on the portal object, since it's no longer
configured automatically by acquisition on CMF 2.



git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@30352 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 7cdbe011
...@@ -65,6 +65,21 @@ ZopeTestCase.installProduct('MailHost', quiet=install_product_quiet) ...@@ -65,6 +65,21 @@ ZopeTestCase.installProduct('MailHost', quiet=install_product_quiet)
ZopeTestCase.installProduct('PageTemplates', quiet=install_product_quiet) ZopeTestCase.installProduct('PageTemplates', quiet=install_product_quiet)
ZopeTestCase.installProduct('PythonScripts', quiet=install_product_quiet) ZopeTestCase.installProduct('PythonScripts', quiet=install_product_quiet)
ZopeTestCase.installProduct('ExternalMethod', quiet=install_product_quiet) ZopeTestCase.installProduct('ExternalMethod', quiet=install_product_quiet)
try:
from Testing.ZopeTestCase.layer import onsetup
# On Zope 2.12, installProduct() is a delayed call, so imports that depend on
# products being "initialize"d should only be called "on setup". The
# decorator above delays calls to the decorated function until after Product
# initialization.
# Also, we need Five to wire all our CMF dependencies.
ZopeTestCase.installProduct('Five', quiet=install_product_quiet)
except ImportError:
# On Zope 2.8 the call does not have to be delayed as product installation
# happens immediately
def onsetup(decorated):
return decorated
try: try:
# Workaround iHotFix patch that doesn't work with # Workaround iHotFix patch that doesn't work with
# ZopeTestCase REQUESTs # ZopeTestCase REQUESTs
...@@ -227,7 +242,7 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase): ...@@ -227,7 +242,7 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase):
def shortDescription(self): def shortDescription(self):
description = str(self) description = str(self)
doc = self._TestCase__testMethodDoc doc = self._testMethodDoc
if doc and doc.split("\n")[0].strip(): if doc and doc.split("\n")[0].strip():
description += ', ' + doc.split("\n")[0].strip() description += ', ' + doc.split("\n")[0].strip()
return description return description
...@@ -269,7 +284,11 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase): ...@@ -269,7 +284,11 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase):
def getPortal(self): def getPortal(self):
"""Returns the portal object, i.e. the "fixture root". """Returns the portal object, i.e. the "fixture root".
""" """
return self.app[self.getPortalName()] portal = self.app[self.getPortalName()]
# FIXME: Try not to run this call below so often by moving it somewhere
# where it is called exactly once per test.
portal.setupCurrentSkin(portal.REQUEST)
return portal
getPortalObject = getPortal getPortalObject = getPortal
...@@ -321,7 +340,7 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase): ...@@ -321,7 +340,7 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase):
self.setUp = self._decorate_setUp(self.setUp) self.setUp = self._decorate_setUp(self.setUp)
self.tearDown = self._decorate_tearDown(self.tearDown) self.tearDown = self._decorate_tearDown(self.tearDown)
test_name = self._TestCase__testMethodName test_name = self._testMethodName
test_method = getattr(self, test_name) test_method = getattr(self, test_name)
setattr(self, test_name, self._decorate_testRun(test_method)) setattr(self, test_name, self._decorate_testRun(test_method))
...@@ -334,6 +353,8 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase): ...@@ -334,6 +353,8 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase):
# This is a workaround for the overwriting problem in Testing/__init__.py # This is a workaround for the overwriting problem in Testing/__init__.py
# in Zope. So this overwrites them again to revert the changes made by # in Zope. So this overwrites them again to revert the changes made by
# Testing. # Testing.
# XXX: Leo: Is this still true? We need to reevaluate how we get
# information from our environment.
try: try:
import App.config import App.config
except ImportError: except ImportError:
...@@ -773,6 +794,10 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase): ...@@ -773,6 +794,10 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase):
transaction.commit() transaction.commit()
self.portal = portal self.portal = portal
# Make sure skins are correctly set-up (it's not implicitly set up
# by Acquisition on Zope 2.12 as it is on 2.8)
portal.setupCurrentSkin(portal.REQUEST)
if len(setup_done) == 1: # make sure it is run only once if len(setup_done) == 1: # make sure it is run only once
try: try:
from Products import DeadlockDebugger from Products import DeadlockDebugger
...@@ -1086,6 +1111,7 @@ def dummy_tearDown(self): ...@@ -1086,6 +1111,7 @@ def dummy_tearDown(self):
''' '''
self._clear(1) self._clear(1)
@onsetup
def optimize(): def optimize():
'''Significantly reduces portal creation time.''' '''Significantly reduces portal creation time.'''
def __init__(self, text): def __init__(self, text):
...@@ -1125,7 +1151,7 @@ def optimize(): ...@@ -1125,7 +1151,7 @@ def optimize():
optimize() optimize()
@onsetup
def fortify(): def fortify():
'''Add some extra checks that we don't have at runtime, not to slow down the '''Add some extra checks that we don't have at runtime, not to slow down the
system. system.
......
...@@ -121,17 +121,25 @@ def initializeInstanceHome(tests_framework_home, ...@@ -121,17 +121,25 @@ def initializeInstanceHome(tests_framework_home,
shutil.copy(src, dst) shutil.copy(src, dst)
else: else:
os.symlink(src, dst) os.symlink(src, dst)
# add some paths where we can find copyzopeskel
sys.path.append(os.path.join(zope_home, "bin"))
sys.path.append(os.path.join(zope_home, "utilities"))
import copyzopeskel
kw = { kw = {
"PYTHON":sys.executable, "PYTHON":sys.executable,
"INSTANCE_HOME": instance_home, "INSTANCE_HOME": instance_home,
"SOFTWARE_HOME": software_home, "SOFTWARE_HOME": software_home,
"ZOPE_HOME": zope_home,
} }
skelsrc = os.path.abspath(os.path.join(os.path.dirname(__file__), "skel")) try:
# attempt to import copyzopeskel from its new home on Zope 2.12
from Zope2.utilities import copyzopeskel
# and use the 2.12 version of our skeleton
skeldir = 'skel2.12'
kw['ZOPE_SCRIPTS'] = os.environ['ZOPE_SCRIPTS']
except ImportError:
# add some paths where we can find copyzopeskel
sys.path.append(os.path.join(zope_home, "bin"))
sys.path.append(os.path.join(zope_home, "utilities"))
import copyzopeskel
kw['ZOPE_HOME'] = zope_home
skeldir = 'skel'
skelsrc = os.path.abspath(os.path.join(os.path.dirname(__file__), skeldir))
copyzopeskel.copyskel(skelsrc, instance_home, None, None, **kw) copyzopeskel.copyskel(skelsrc, instance_home, None, None, **kw)
# site specific variables # site specific variables
...@@ -310,6 +318,9 @@ def runUnitTestList(test_list, verbosity=1, debug=0): ...@@ -310,6 +318,9 @@ def runUnitTestList(test_list, verbosity=1, debug=0):
else: else:
products_home = os.path.join(instance_home, 'Products') products_home = os.path.join(instance_home, 'Products')
# The following un-monkey-patch is only required for Zope 2.8.
# On Zope 2.12, import_products() is called by ERP5TestCase before it is
# patched by the layer.setUp() call.
import OFS.Application import OFS.Application
import_products = OFS.Application.import_products import_products = OFS.Application.import_products
from Testing import ZopeTestCase # This will import custom_zodb.py from Testing import ZopeTestCase # This will import custom_zodb.py
...@@ -326,7 +337,13 @@ def runUnitTestList(test_list, verbosity=1, debug=0): ...@@ -326,7 +337,13 @@ def runUnitTestList(test_list, verbosity=1, debug=0):
section = SectionValue({'dateformat': '%Y-%m-%d %H:%M:%S', section = SectionValue({'dateformat': '%Y-%m-%d %H:%M:%S',
'format': '%(asctime)s %(levelname)s %(name)s %(message)s', 'format': '%(asctime)s %(levelname)s %(name)s %(message)s',
'level': logging.INFO, 'level': logging.INFO,
'path': os.environ['EVENT_LOG_FILE']}, 'path': os.environ['EVENT_LOG_FILE'],
'max_size': None,
'old_files': None,
'when': None,
'interval': None,
'formatter': None,
},
None, None) None, None)
section.handlers = [FileHandlerFactory(section)] section.handlers = [FileHandlerFactory(section)]
eventlog = EventLogFactory(section) eventlog = EventLogFactory(section)
...@@ -336,8 +353,6 @@ def runUnitTestList(test_list, verbosity=1, debug=0): ...@@ -336,8 +353,6 @@ def runUnitTestList(test_list, verbosity=1, debug=0):
except ImportError: except ImportError:
pass pass
TestRunner = backportUnittest.TextTestRunner
# allow unit tests of our Products or business templates to be reached. # allow unit tests of our Products or business templates to be reached.
from glob import glob from glob import glob
product_test_list = glob(os.path.join(products_home, '*', 'tests')) product_test_list = glob(os.path.join(products_home, '*', 'tests'))
...@@ -366,6 +381,9 @@ def runUnitTestList(test_list, verbosity=1, debug=0): ...@@ -366,6 +381,9 @@ def runUnitTestList(test_list, verbosity=1, debug=0):
save = int(os.environ.get('erp5_save_data_fs', 0)) save = int(os.environ.get('erp5_save_data_fs', 0))
dummy_test = save and (int(os.environ.get('update_business_templates', 0)) dummy_test = save and (int(os.environ.get('update_business_templates', 0))
or not int(os.environ.get('erp5_load_data_fs', 0))) or not int(os.environ.get('erp5_load_data_fs', 0)))
TestRunner = backportUnittest.TextTestRunner
if dummy_test: if dummy_test:
# Skip all tests in save mode and monkeypatch PortalTestCase.setUp # Skip all tests in save mode and monkeypatch PortalTestCase.setUp
# to skip beforeSetUp and afterSetUp. Also patch unittest.makeSuite, # to skip beforeSetUp and afterSetUp. Also patch unittest.makeSuite,
...@@ -382,7 +400,7 @@ def runUnitTestList(test_list, verbosity=1, debug=0): ...@@ -382,7 +400,7 @@ def runUnitTestList(test_list, verbosity=1, debug=0):
# Hack the profiler to run only specified test methods, and wrap results when # Hack the profiler to run only specified test methods, and wrap results when
# running in debug mode. # running in debug mode.
if debug: if debug:
class DebugTextTestRunner(backportUnittest.TextTestRunner): class DebugTextTestRunner(TestRunner):
def _makeResult(self): def _makeResult(self):
result = super(DebugTextTestRunner, self)._makeResult() result = super(DebugTextTestRunner, self)._makeResult()
return DebugTestResult(result) return DebugTestResult(result)
...@@ -396,6 +414,18 @@ def runUnitTestList(test_list, verbosity=1, debug=0): ...@@ -396,6 +414,18 @@ def runUnitTestList(test_list, verbosity=1, debug=0):
# change current directory to the test home, to create zLOG.log in this dir. # change current directory to the test home, to create zLOG.log in this dir.
os.chdir(tests_home) os.chdir(tests_home)
try:
from Testing.ZopeTestCase import layer
except ImportError:
# Zope 2.8, no need to set-up the ZopeLite layer
pass
else:
# Since we're not using the zope.testing testrunner, we need to set up
# the layer ourselves
# FIXME: We should start using Zope layers. Our setup will probably
# be faster and we could drop most of this code we currently maintain
# ourselves
layer.ZopeLite.setUp()
result = TestRunner(verbosity=verbosity).run(suite) result = TestRunner(verbosity=verbosity).run(suite)
if save: if save:
...@@ -508,8 +538,13 @@ def main(): ...@@ -508,8 +538,13 @@ def main():
result = runUnitTestList(test_list=test_list, result = runUnitTestList(test_list=test_list,
verbosity=verbosity, verbosity=verbosity,
debug=debug) debug=debug)
from Testing.ZopeTestCase import profiler try:
profiler.print_stats() from Testing.ZopeTestCase import profiler
except ImportError:
if os.environ.get('PROFILE_TESTS') == '1':
print "Profiler support is not available from ZopeTestCase in Zope 2.12"
else:
profiler.print_stats()
sys.exit(len(result.failures) + len(result.errors)) sys.exit(len(result.failures) + len(result.errors))
if __name__ == '__main__': if __name__ == '__main__':
......
@set INSTANCE_HOME=<<INSTANCE_HOME>>
@set CONFIG_FILE=%INSTANCE_HOME%\etc\zope.conf
@set ZOPE_RUN=<<ZOPE_SCRIPTS>>\runzope
@set erp5_load_data_fs=1
"%ZOPE_RUN%" -C "%CONFIG_FILE%" %1 %2 %3 %4 %5 %6 %7
#! /bin/sh
INSTANCE_HOME="<<INSTANCE_HOME>>"
CONFIG_FILE="<<INSTANCE_HOME>>/etc/zope.conf"
ZOPE_RUN="<<ZOPE_SCRIPTS>>/runzope"
export INSTANCE_HOME
export erp5_load_data_fs="1"
exec "$ZOPE_RUN" -C "$CONFIG_FILE" "$@"
@set PYTHON=<<PYTHON>>
@set INSTANCE_HOME=<<INSTANCE_HOME>>
@set CONFIG_FILE=%INSTANCE_HOME%\etc\zope.conf
@set ZDCTL=<<ZOPE_SCRIPTS>>\zopectl
@set export erp5_load_data_fs="1"
"%ZDCTL%" -C "%CONFIG_FILE%" %1 %2 %3 %4 %5 %6 %7
#! /bin/sh
PYTHON="<<PYTHON>>"
INSTANCE_HOME="<<INSTANCE_HOME>>"
CONFIG_FILE="<<INSTANCE_HOME>>/etc/zope.conf"
ZDCTL="<<ZOPE_SCRIPTS>>/zopectl"
export INSTANCE_HOME
export PYTHON
export erp5_load_data_fs="1"
exec "$ZDCTL" -C "$CONFIG_FILE" "$@"
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:meta="http://namespaces.zope.org/meta"
xmlns:five="http://namespaces.zope.org/five">
<include package="Products.Five" />
<meta:redefinePermission from="zope2.Public" to="zope.Public" />
<!-- Load the meta -->
<include files="package-includes/*-meta.zcml" />
<five:loadProducts file="meta.zcml"/>
<!-- Load the configuration -->
<include files="package-includes/*-configure.zcml" />
<five:loadProducts />
<!-- Load the configuration overrides-->
<includeOverrides files="package-includes/*-overrides.zcml" />
<five:loadProductsOverrides />
<securityPolicy
component="Products.Five.security.FiveSecurityPolicy" />
</configure>
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment