pytest-plone 1.1.1 is out on PyPI. It's a bug-fix release for the @pytest.mark.portal marker and the apply_profiles / create_content fixtures. If you set up your test portal with them, upgrading is recommended:
uv add --dev "pytest-plone>=1.1.1"
Profiles are applied as the site owner
In 1.1.0, @pytest.mark.portal(profiles=[...]) and the apply_profiles fixture ran the GenericSetup import steps as the test user. If an add-on's import step creates content, for example a container, that worked with plone.app.testing.applyProfile but failed under the marker:
# my/addon/setuphandlers.py
def post_install(context):
api.content.create(
container=api.portal.get(), type="Folder", id="things", title="Things"
)
@pytest.mark.portal(profiles=["my.addon:default"])
def test_container_exists(portal):
assert "things" in portal
AccessControl.unauthorized.Unauthorized: Cannot create Folder
Adding roles=["Manager"] didn't help, because the marker grants roles after it applies profiles.
From 1.1.1, profiles are applied as the site owner, just as applyProfile does. The test above passes without any extra roles. The test body still runs as the test user, with only the roles it had plus those you pass in roles=.
You can now remove workarounds such as an autouse fixture that grants Manager before the marker runs.
Marker content shows up in the catalog indexes
Content created by the marker was always found by catalog queries, but reads that go straight to an index could miss the last item created:
CONTENT = [
{"type": "Document", "id": "doc-1", "title": "Doc 1", "subject": ("alpha",)},
{"type": "Document", "id": "doc-2", "title": "Doc 2", "subject": ("beta",)},
{"type": "Document", "id": "doc-3", "title": "Doc 3", "subject": ("gamma",)},
]
@pytest.mark.portal(content=CONTENT)
def test_unique_values(portal):
catalog = api.portal.get_tool("portal_catalog")
assert sorted(catalog.uniqueValuesFor("Subject")) == ["alpha", "beta", "gamma"]
# 1.1.0: ["alpha", "beta"]
The cause is Products.CMFCore.indexing, which queues index operations until the transaction ends. A test never reaches that point. searchResults() processes the queue before it searches, but uniqueValuesFor() doesn't. Any dynamic vocabulary or facet listing built on it saw a partial list, and whether a test failed depended on whether something earlier had happened to run a query.
The marker, create_content and apply_profiles now process the queue before your test runs. This includes content created by a profile's import steps.
Also in this release
- The README is now a short landing page, and the full fixture and marker reference lives in the documentation. The marker reference now also covers the order in which
profiles,contentandrolesare applied, and the security context they run in. - Repository maintenance: Dependabot now keeps the GitHub Actions up to date, its pull requests skip the changelog check, and documentation deploys no longer collide when merges land close together.
Thanks
Thanks to @kunalKumar-13 for the indexing fix and the Dependabot move, which came in before ours, and to @jensens for the documentation work.
The full changelog is on GitHub. As always, issues and pull requests are welcome in plone/pytest-plone.