pytest-plone is a pytest plugin providing fixtures and helpers to test Plone add-ons.
This package is built on top of zope.pytestlayer.
Despite the fact Plone, and Zope, have their codebases tested with unittest
, over the years
pytest
became the most popular choice for testing in Python.
pytest
is more flexible and easier to use than unittest
and has a rich ecosystem of plugins that you can use to extend its functionality.
THIS PACKAGE IS NOT CONSIDERED TO BE STABLE AND FIXTURES COULD CHANGE BEFORE A FINAL RELEASE
In your top-level conftest.py
import your testing layers, and also import fixtures_factory
-- which will accept a iterator of tuples containing the testing layer and a prefix to be used to generate the needed pytest fixtures.
from Products.CMFPlone.testing import PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING
from Products.CMFPlone.testing import PRODUCTS_CMFPLONE_INTEGRATION_TESTING
from pytest_plone import fixtures_factory
pytest_plugins = ["pytest_plone"]
globals().update(
fixtures_factory(
(
(PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING, "functional"),
(PRODUCTS_CMFPLONE_INTEGRATION_TESTING, "integration"),
)
)
)
In the code above, the following pytest fixtures will be available to your tests:
Fixture | Scope |
---|---|
functional_session | Session |
functional_class | Class |
functional | Function |
integration_session | Session |
integration_class | Class |
integration | Function |
Description | Set environment variable to force Zope to compile translation files |
Required Fixture | |
Scope | Session |
Add a new fixture to your conftest.py
to force generate_mo
to be called for all tests.
@pytest.fixture(scope="session", autouse=True)
def session_initialization(generate_mo):
"""Fixture used to force translation files to be compiled."""
yield
Description | Zope root |
Required Fixture | integration |
Scope | Function |
def test_app(app):
"""Test portal title."""
assert app.getPhysicalPath() == ("", )
Description | Portal object |
Required Fixture | integration |
Scope | Function |
def test_portal_title(portal):
"""Test portal title."""
assert portal.title == "Plone Site"
Description | HTTP Request |
Required Fixture | integration |
Scope | Function |
from plone import api
def test_myproduct_controlpanel_view(portal, http_request):
"""Test myproduct_controlpanel browser view is available."""
view = api.content.get_view(
"myproduct-controlpanel", portal, http_request
)
assert view is not None
Description | Installer browser view. Used to install/uninstall/check for an add-on. |
Required Fixture | integration |
Scope | Function |
import pytest
PACKAGE_NAME = "myproduct"
@pytest.fixture
def uninstall(installer):
"""Fixture to uninstall a package."""
installer.uninstall_product(PACKAGE_NAME)
def test_product_installed(installer):
"""Test if myproduct is installed."""
assert installer.is_product_installed(PACKAGE_NAME) is True
@pytest.mark.parametrize(
"package",
[
"collective.casestudy",
"pytest-plone",
]
)
def test_dependency_installed(installer, package):
"""Test if dependency is installed."""
assert installer.is_product_installed(package) is True
Description | List of available browser layers. Used to test if a specific browser layer is registered. |
Required Fixture | integration |
Scope | Function |
def test_browserlayer(browser_layers):
"""Test that IMyProductLayer is registered."""
from myproduct.interfaces import IMyProductLayer
assert IMyProductLayer in browser_layers
Description | List of control panel actions ids. Used to test if a specific control panel is installed or not. |
Required Fixture | integration |
Scope | Function |
def test_configlet_install(controlpanel_actions):
"""Test if control panel is installed."""
assert "myproductcontrolpanel" in controlpanel_actions
Description | Function to get the Factory Type Info (FTI) for a content type. |
Required Fixture | integration |
Scope | Function |
def test_get_fti(get_fti):
"""Test if Document fti is installed."""
assert get_fti("Document") is not None
Description | Function to list behaviors for a content type. |
Required Fixture | integration |
Scope | Function |
import pytest
def test_block_in_document(get_behaviors):
"""Test if blocks behavior is installed for Document."""
assert "volto.blocks" in get_behaviors("Document")
@pytest.mark.parametrize(
"behavior",
[
"plone.dublincore",
"plone.namefromtitle",
"plone.shortname",
"plone.excludefromnavigation",
"plone.relateditems",
"plone.versioning",
"volto.blocks",
"volto.navtitle",
"volto.preview_image",
"volto.head_title",
],
)
def test_has_behavior(self, get_behaviors, behavior):
assert behavior in get_behaviors("Document")
Description | Function to get a named vocabulary. |
Required Fixture | integration |
Scope | Function |
from zope.schema.vocabulary import SimpleVocabulary
VOCAB = "plone.app.vocabularies.AvailableContentLanguages"
def test_get_vocabulary(get_vocabulary):
"""Test plone.app.vocabularies.AvailableContentLanguages."""
vocab = get_vocabulary(VOCAB)
assert vocab is not None
assert isinstance(vocab, SimpleVocabulary)
Description | Portal Setup tool. |
Required Fixture | integration |
Scope | Function |
def test_setup_tool(setup_tool):
"""Test setup_tool."""
assert setup_tool is not None
Description | Function to get the last version of a profile. |
Required Fixture | integration |
Scope | Function |
PACKAGE_NAME = "collective.case_study"
def test_last_version(profile_last_version):
"""Test setup_tool."""
profile = f"{PACKAGE_NAME}:default"
version = profile_last_version(profile)
assert version == "1000"
You need a working python
environment (system, virtualenv, pyenv, etc) version 3.8 or superior.
Then install the dependencies and a development instance using:
make install
To run tests for this package:
make test
By default we use the latest Plone version in the 6.x series.
The project is licensed under the GPLv2.