From 329ffc4da5ef83ba5ea2e97c8fa59cdefcf3b9fc Mon Sep 17 00:00:00 2001 From: Michael Howitz Date: Thu, 17 May 2018 15:54:49 +0200 Subject: [PATCH] Fix tests so they run successfully on Python 2 against the py3 branch of plone.testing. --- buildout.cfg | 20 +++++----- src/plone/app/testing/helpers.py | 7 +++- src/plone/app/testing/helpers.rst | 4 +- src/plone/app/testing/layers.py | 65 ++++++++++++++++++++++++++++--- src/plone/app/testing/layers.rst | 59 +++++++++++++++------------- tox.ini | 7 +++- 6 files changed, 114 insertions(+), 48 deletions(-) diff --git a/buildout.cfg b/buildout.cfg index 2f81926..b41368c 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -1,5 +1,6 @@ [buildout] extends = https://raw.githubusercontent.com/collective/buildout.plonetest/master/test-5.x.cfg + https://raw.githubusercontent.com/plone/buildout.coredev/5.2/versions.cfg parts = coverage @@ -14,15 +15,11 @@ extensions = mr.developer sources = sources versions = versions -auto-checkout = - plone.testing -# Products.GenericSetup +auto-checkout = * sources-dir = src-mrd -develop = - src-mrd/plone.testing -# src-mrd/Products.GenericSetup +develop = . [remotes] plone = git://github.com/plone @@ -33,19 +30,22 @@ zope_push = git@github.com:zopefoundation [versions] plone.app.testing = -Products.GenericSetup = +Products.GenericSetup = >= 2.0b1 +Products.PluginRegistry = >= 1.6 [sources] plone.testing = git ${remotes:plone}/plone.testing.git pushurl=${remotes:plone_push}/plone.testing.git branch=py3 -#Products.GenericSetup = git ${remotes:zope}/Products.GenericSetup.git pushurl=${remotes:plone_push}/Products.GenericSetup branch=master +Products.PluggableAuthService = git ${remotes:zope}/Products.PluggableAuthService.git pushurl=${remotes:zope_push}/Products.PluggableAuthService.git branch=master +Products.CMFPlone = git ${remotes:plone}/Products.CMFPlone.git pushurl=${remotes:plone_push}/Products.CMFPlone.git branch=master +Products.PlonePAS = git ${remotes:plone}/Products.PlonePAS.git pushurl=${remotes:plone_push}/Products.PlonePAS.git branch=master [test] -recipe = collective.xmltestreport +recipe = zc.recipe.testrunner eggs = Pillow plone.testing [test] plone.app.testing [test] -defaults = ['--auto-color', '--auto-progress'] +defaults = ['--auto-color'] selenium-driver = environment = testenv diff --git a/src/plone/app/testing/helpers.py b/src/plone/app/testing/helpers.py index 1a60080..6401d0d 100644 --- a/src/plone/app/testing/helpers.py +++ b/src/plone/app/testing/helpers.py @@ -234,7 +234,7 @@ def persist_profile_upgrade_versions(portal): @contextlib.contextmanager -def ploneSite(db=None, connection=None, environ=None): +def ploneSite(db=None, connection=None, environ=None, flavour=z2): """Context manager for working with the Plone portal during layer setup:: with ploneSite() as portal: @@ -249,11 +249,14 @@ def ploneSite(db=None, connection=None, environ=None): Pass a ZODB handle as ``db`` to use a specificdatabase. Alternatively, pass an open connection as ``connection`` (the connection will not be closed). + + flavour ... either `plone.testing.z2` resp. `plone.testing.zope` for WSGI + or `plone.testing.zserver` for ZServer """ setHooks() site = getSite() - with z2.zopeApp(db, connection, environ) as app: + with getattr(flavour, 'zopeApp')(db, connection, environ) as app: portal = app[PLONE_SITE_ID] setSite(portal) diff --git a/src/plone/app/testing/helpers.rst b/src/plone/app/testing/helpers.rst index eb7bf5c..9027d49 100644 --- a/src/plone/app/testing/helpers.rst +++ b/src/plone/app/testing/helpers.rst @@ -183,8 +183,8 @@ the ``ploneSite()`` context manager as shown above. >>> portal = HELPER_DEMOS_INTEGRATION_TESTING['portal'] # would normally be self.layer['portal'] - >>> getSecurityManager().getUser().getRolesInContext(portal) - ['Member', 'Authenticated'] + >>> sorted(getSecurityManager().getUser().getRolesInContext(portal)) + ['Authenticated', 'Member'] >>> getSecurityManager().getUser().getUserName() == TEST_USER_NAME True diff --git a/src/plone/app/testing/layers.py b/src/plone/app/testing/layers.py index 8257351..3dd3b20 100644 --- a/src/plone/app/testing/layers.py +++ b/src/plone/app/testing/layers.py @@ -17,6 +17,8 @@ from plone.testing import z2 from plone.testing import zca from plone.testing import zodb +from plone.testing import zope +from plone.testing import zserver from Products.MailHost.interfaces import IMailHost from zope.component import getSiteManager from zope.component.hooks import setSite @@ -252,6 +254,47 @@ def setUpDefaultContent(self, app): PLONE_FIXTURE = PloneFixture() +class PloneZServerFixture(PloneFixture): + """PloneFixture using ZServer if you really have to. + + e. g. to use the FTP server. + + """ + + defaultBases = (zserver.STARTUP,) + + def setUp(self): + + # Stack a new DemoStorage on top of the one from zserver.STARTUP. + self['zodbDB'] = zodb.stackDemoStorage( + self.get('zodbDB'), + name='PloneZServerFixture' + ) + + self.setUpZCML() + + # Set up products and the default content + with zserver.zopeApp() as app: + self.setUpProducts(app) + self.setUpDefaultContent(app) + + def tearDown(self): + + # Tear down products + with zserver.zopeApp() as app: + # note: content tear-down happens by squashing the ZODB + self.tearDownProducts(app) + + self.tearDownZCML() + + # Zap the stacked ZODB + self['zodbDB'].close() + del self['zodbDB'] + + +PLONE_ZSERVER_FIXTURE = PloneZServerFixture() + + class PloneTestLifecycle(object): """Mixin class for Plone test lifecycle. This exposes the ``portal`` resource and resets the environment between each test. @@ -315,6 +358,12 @@ def tearDownEnvironment(self, portal): setSite(None) +class PloneZServerTestLifecycle(PloneTestLifecycle): + """PloneTestLifecycle if you have to use ZServer.""" + + defaultBases = (PLONE_ZSERVER_FIXTURE,) + + class MockMailHostLayer(Layer): """Layer for setting up a MockMailHost to store all sent messages as strings into a list at portal.MailHost.messages @@ -359,6 +408,12 @@ class FunctionalTesting(PloneTestLifecycle, z2.FunctionalTesting): """Plone version of the functional testing layer """ + +class ZServerFunctionalTesting( + PloneZServerTestLifecycle, zserver.FunctionalTesting): + """Plone version of the functional testing layer using ZServer. + """ + # # Layer instances # @@ -375,12 +430,12 @@ class FunctionalTesting(PloneTestLifecycle, z2.FunctionalTesting): name='Plone:Functional' ) -PLONE_ZSERVER = FunctionalTesting( - bases=(PLONE_FIXTURE, z2.ZSERVER_FIXTURE), - name='Plone:ZServer' +PLONE_WSGISERVER = PLONE_ZSERVER = FunctionalTesting( + bases=(PLONE_FIXTURE, zope.WSGI_SERVER_FIXTURE), + name='Plone:WSGIServer' ) -PLONE_FTP_SERVER = FunctionalTesting( - bases=(PLONE_FIXTURE, z2.FTP_SERVER_FIXTURE), +PLONE_FTP_SERVER = ZServerFunctionalTesting( + bases=(PLONE_ZSERVER_FIXTURE, zserver.FTP_SERVER_FIXTURE), name='Plone:FTPServer' ) diff --git a/src/plone/app/testing/layers.rst b/src/plone/app/testing/layers.rst index 2f92111..1de247b 100644 --- a/src/plone/app/testing/layers.rst +++ b/src/plone/app/testing/layers.rst @@ -85,10 +85,10 @@ the module ``plone.app.testing.interfaces``. >>> with helpers.ploneSite() as portal: ... print portal['acl_users'].getUser(TEST_USER_NAME).getId() ... print portal['acl_users'].getUser(TEST_USER_NAME).getUserName() - ... print portal['acl_users'].getUser(TEST_USER_NAME).getRolesInContext(portal) + ... print sorted(portal['acl_users'].getUser(TEST_USER_NAME).getRolesInContext(portal)) test_user_1_ test-user - ['Member', 'Authenticated'] + ['Authenticated', 'Member'] There is no default workflow or content: @@ -275,35 +275,36 @@ Layer tear-down resets the environment. HTTP server ~~~~~~~~~~~ -The ``PLONE_ZSERVER`` layer instantiates the ``FunctionalTesting`` class with -two bases: ``PLONE_FIXTURE``, as shown above, and ``ZSERVER_FIXTURE`` from -``plone.testing``, which starts up a ZServer thread. +The ``PLONE_WSGISERVER`` layer instantiates the ``FunctionalTesting`` class with +two bases: ``PLONE_FIXTURE``, as shown above, and ``WSGI_SERVER_FIXTURE`` from +``plone.testing``, which starts up a WSGI server. (There also the name +``PLONE_ZSERVER`` in place which is a BBB alias.) - >>> "%s.%s" % (layers.PLONE_ZSERVER.__module__, layers.PLONE_ZSERVER.__name__,) - 'plone.app.testing.layers.Plone:ZServer' + >>> "%s.%s" % (layers.PLONE_WSGISERVER.__module__, layers.PLONE_WSGISERVER.__name__,) + 'plone.app.testing.layers.Plone:WSGIServer' - >>> layers.PLONE_ZSERVER.__bases__ - (, ) + >>> layers.PLONE_WSGISERVER.__bases__ + (, ) >>> options = runner.get_options([], []) >>> setupLayers = {} - >>> runner.setup_layer(options, layers.PLONE_ZSERVER, setupLayers) + >>> runner.setup_layer(options, layers.PLONE_WSGISERVER, setupLayers) Set up plone.testing.zca.LayerCleanup in ... seconds. Set up plone.testing.zope.Startup in ... seconds. Set up plone.app.testing.layers.PloneFixture in ... seconds. - Set up plone.testing.z2.ZServer in ... seconds. - Set up plone.app.testing.layers.Plone:ZServer in ... seconds. + Set up plone.testing.zope.WSGIServer in ... seconds. + Set up plone.app.testing.layers.Plone:WSGIServer in ... seconds. After layer setup, the resources ``host`` and ``port`` are available, and indicate where Zope is running. - >>> host = layers.PLONE_ZSERVER['host'] + >>> host = layers.PLONE_WSGISERVER['host'] >>> host 'localhost' - >>> port = layers.PLONE_ZSERVER['port'] + >>> port = layers.PLONE_WSGISERVER['port'] >>> import os - >>> port == int(os.environ.get('ZSERVER_PORT', 55001)) + >>> port == int(os.environ.get('WSGI_SERVER_PORT', 55001)) True Let's now simulate a test. Test setup does nothing beyond what the base layers @@ -367,9 +368,10 @@ Test tear-down does nothing beyond what the base layers do. When the server is torn down, the ZServer thread is stopped. >>> runner.tear_down_unneeded(options, [], setupLayers) - Tear down plone.app.testing.layers.Plone:ZServer in ... seconds. - ...Tear down plone.app.testing.layers.PloneFixture in ... seconds. - ...Tear down plone.testing.zope.Startup in ... seconds. + Tear down plone.app.testing.layers.Plone:WSGIServer in ... seconds. + Tear down plone.testing.zope.WSGIServer in ... seconds. + Tear down plone.app.testing.layers.PloneFixture in ... seconds. + Tear down plone.testing.zope.Startup in ... seconds. Tear down plone.testing.zca.LayerCleanup in ... seconds. >>> conn = urllib2.urlopen(portal_url + '/folder1', timeout=5) @@ -388,15 +390,15 @@ from ``plone.testing``, which starts up an FTP server thread. 'plone.app.testing.layers.Plone:FTPServer' >>> layers.PLONE_FTP_SERVER.__bases__ - (, ) + (, ) >>> options = runner.get_options([], []) >>> setupLayers = {} - >>> runner.setup_layer(options, layers.PLONE_FTP_SERVER, setupLayers) + >>> runner.setup_layer(options, layers.PLONE_FTP_SERVER, setupLayers) # here! Set up plone.testing.zca.LayerCleanup in ... seconds. - Set up plone.testing.zope.Startup in ... seconds. - Set up plone.app.testing.layers.PloneFixture in ... seconds. - Set up plone.testing.z2.FTPServer in ... seconds. + Set up plone.testing.zserver.Startup in ... seconds. + Set up plone.app.testing.layers.PloneZServerFixture in ... seconds. + Set up plone.testing.zserver.FTPServer in ... seconds. Set up plone.app.testing.layers.Plone:FTPServer in ... seconds. After layer setup, the resources ``host`` and ``port`` are available, and @@ -478,7 +480,8 @@ Test tear-down does nothing beyond what the base layers do. >>> 'request' in layers.PLONE_FTP_SERVER False - >>> with helpers.ploneSite() as portal: + >>> import plone.testing.zserver + >>> with helpers.ploneSite(flavour=plone.testing.zserver) as portal: ... print 'folder1' in portal.objectIds() False @@ -486,11 +489,11 @@ When the server is torn down, the FTP server thread is stopped. >>> runner.tear_down_unneeded(options, [], setupLayers) Tear down plone.app.testing.layers.Plone:FTPServer in ... seconds. - ...Tear down plone.app.testing.layers.PloneFixture in ... seconds. - ...Tear down plone.testing.zope.Startup in ... seconds. + Tear down plone.testing.zserver.FTPServer in ... seconds. + Tear down plone.app.testing.layers.PloneZServerFixture in ... seconds. + Tear down plone.testing.zserver.Startup in ... seconds. Tear down plone.testing.zca.LayerCleanup in ... seconds. >>> ftpClient.connect(host, port, timeout=5) Traceback (most recent call last): - ... - ... [Errno ...] Connection refused + error: [Errno 61] Connection refused diff --git a/tox.ini b/tox.ini index 6adab4d..bfc9cd8 100644 --- a/tox.ini +++ b/tox.ini @@ -10,6 +10,7 @@ envlist = minversion = 1.9 [testenv] +skip_install = true usedevelop = True pip_pre = True @@ -19,10 +20,14 @@ extras = deps = coverage + setuptools==33.1.1 + zc.buildout commands = python -V - coverage run {envbindir}/zope-testrunner --path=src --all {posargs:-vc} + {envbindir}/buildout -c {toxinidir}/buildout.cfg buildout:directory={envdir} buildout:develop={toxinidir} bootstrap + {envbindir}/buildout -c {toxinidir}/buildout.cfg buildout:directory={envdir} buildout:develop={toxinidir} install test + coverage run {envbindir}/test --all {posargs:-vc} setenv = COVERAGE_FILE=.coverage.{envname}