Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions news/+enrich-api-docstrings.documentation
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Enrich the docstrings of the public testing helpers and layer classes
(``login``, ``logout``, ``setRoles``, ``applyProfile``,
``cleanUpMultiPlugins``, ``IntegrationTesting``, ``FunctionalTesting``)
with parameter descriptions and behaviour notes.
This makes them usable as an autodoc API reference and improves IDE help.
[jensens]
7 changes: 7 additions & 0 deletions src/plone/app/testing/cleanup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@


def cleanUpMultiPlugins():
"""Remove PAS MultiPlugin registrations left in the global registry.

Registered as a ``zope.testing`` cleanup handler, so it runs
automatically between test layers and keeps global PluggableAuthService
state from leaking from one layer into the next. Plugins that
GenericSetup's own cleanup handler already manages are left untouched.
"""
try:
from Products.PluggableAuthService.PluggableAuthService import MultiPlugins

Expand Down
47 changes: 42 additions & 5 deletions src/plone/app/testing/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,39 @@


def login(portal, userName):
"""Log in as the given user in the given Plone site"""
"""Log in as the named user in the given Plone site.

Subsequent operations run as this user until :func:`logout` is called
or the test tears down.

:param portal: the Plone site to log in to.
:param userName: the login name of the user to become, for example
:data:`TEST_USER_NAME`. This is the login name, not the user id.
"""

zope.login(portal["acl_users"], userName)


def logout():
"""Log out, i.e. become anonymous"""
"""Log out, so that subsequent operations run as the anonymous user.

The inverse of :func:`login`.
"""

zope.logout()


def setRoles(portal, userId, roles):
"""Set the given user's roles to a tuple of roles."""
"""Set a user's global roles to exactly the given roles.

Replaces the user's current roles rather than adding to them.

:param portal: the Plone site.
:param userId: the id of the user whose roles to set, for example
:data:`TEST_USER_ID`. This is the user id, not the login name.
:param roles: the roles the user should have, as a sequence of role
names, for example ``["Manager"]``.
"""

userFolder = portal["acl_users"]
zope.setRoles(userFolder, userId, roles)
Expand Down Expand Up @@ -105,8 +125,25 @@ def applyProfile(
archive=None,
blacklisted_steps=None,
):
"""Install an extension profile into the portal. The profile name
should be a package name and a profile name, e.g. 'my.product:default'.
"""Install a GenericSetup extension profile into the portal.

Runs every import step of the profile as the site owner, then rebuilds
the current skin. Use this to install an add-on into the test site,
typically from a layer's ``setUpPloneSite`` or directly in a test.

:param portal: the Plone site to install the profile into.
:param profileName: the profile id in ``package:profile`` form, for
example ``"my.product:default"``. Give it without the ``profile-``
prefix; that is added internally.
:param purge_old: passed through to GenericSetup. When ``None`` (the
default) GenericSetup decides; ``True`` purges existing settings
before importing, ``False`` keeps them.
:param ignore_dependencies: when ``True``, run only the profile's own
import steps and skip the profiles it depends on.
:param archive: an optional GenericSetup archive (tarball) to import
from instead of the profile directory.
:param blacklisted_steps: an optional sequence of import step ids to
skip.
"""

from AccessControl import getSecurityManager
Expand Down
23 changes: 21 additions & 2 deletions src/plone/app/testing/layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,11 +398,30 @@ def testTearDown(self):


class IntegrationTesting(PloneTestLifecycle, zope.IntegrationTesting):
"""Plone version of the integration testing layer"""
"""Testing layer for integration tests.

Wraps a Plone site fixture with per-test isolation: each test runs
inside a transaction that is rolled back on tear-down, so tests do not
see each other's changes. Derive one from your fixture with
``IntegrationTesting(bases=(MY_FIXTURE,), name=...)``.

Use this for in-process tests. When a test makes a real HTTP request,
use :class:`FunctionalTesting` instead.
"""


class FunctionalTesting(PloneTestLifecycle, zope.FunctionalTesting):
"""Plone version of the functional testing layer"""
"""Testing layer for functional tests.

Like :class:`IntegrationTesting`, but each test runs against a stacked
``DemoStorage`` and may commit real transactions, which a separate
process such as a browser or HTTP client can then see. The storage is
discarded on tear-down.

Use this when a request has to travel over the network, for example a
REST API or browser test. Add ``WSGI_SERVER_FIXTURE`` to the bases so a
server is running. For in-process tests, use :class:`IntegrationTesting`.
"""


class ZServerFunctionalTesting(PloneZServerTestLifecycle, zserver.FunctionalTesting):
Expand Down