Skip to content

Commit

Permalink
Fix tests so they run successfully on Python 2 against the py3 branch…
Browse files Browse the repository at this point in the history
… of plone.testing.
  • Loading branch information
Michael Howitz committed May 17, 2018
1 parent ddbc331 commit 329ffc4
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 48 deletions.
20 changes: 10 additions & 10 deletions buildout.cfg
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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

Expand Down
7 changes: 5 additions & 2 deletions src/plone/app/testing/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/plone/app/testing/helpers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
65 changes: 60 additions & 5 deletions src/plone/app/testing/layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
#
Expand All @@ -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'
)
59 changes: 31 additions & 28 deletions src/plone/app/testing/layers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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__
(<Layer 'plone.app.testing.layers.PloneFixture'>, <Layer 'plone.testing.z2.ZServer'>)
>>> layers.PLONE_WSGISERVER.__bases__
(<Layer 'plone.app.testing.layers.PloneFixture'>, <Layer 'plone.testing.zope.WSGIServer'>)

>>> 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
Expand Down Expand Up @@ -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)
Expand All @@ -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__
(<Layer 'plone.app.testing.layers.PloneFixture'>, <Layer 'plone.testing.z2.FTPServer'>)
(<Layer 'plone.app.testing.layers.PloneZServerFixture'>, <Layer 'plone.testing.zserver.FTPServer'>)

>>> 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
Expand Down Expand Up @@ -478,19 +480,20 @@ 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

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
7 changes: 6 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ envlist =
minversion = 1.9

[testenv]
skip_install = true
usedevelop = True

pip_pre = True
Expand All @@ -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}
Expand Down

0 comments on commit 329ffc4

Please sign in to comment.