Tests: the browser suite's conftest turns Django's async-safety guard off for every unit test #1160
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#1160
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What exists today
tests/e2e/conftest.py:33runsos.environ.setdefault("DJANGO_ALLOW_ASYNC_UNSAFE", "true")at import, beforepytest.importorskip("playwright")at:35. The comment at:27-32scopes the reasoning to the browser tests (Playwright's sync API runs an event loop in the test thread).The unit run imports that conftest.
pyproject.toml:197-203setstestpaths = ["tests"]and deselects with-m 'not e2e and not release and not step and not heavy'; nothing ignorestests/e2e(nocollect_ignoreintests/conftest.py, no--ignoreinci.yml:311-325orevery-python.yml:150-164). Deselection by marker happens after collection, so the directory is collected and its conftest imported. Checked withuv run pytest --co -q -p no:cacheprovider -p no:xdist:20842/27656 tests collected (6814 deselected) in 49.82s, the deselected set including the browser tests. Each xdist worker collects too, so every worker process runs with the guard off.Correction to the candidate: today nothing in
src/postulois async apart from the ASGI entry point (config/asgi.py,ASGI_APPLICATIONinsettings/base.py:40), and no unit test usesAsyncClientor an async test runner, so no test currently depends on the guard. The finding is a trap for the first async view or async test, not a present failure.What would change
Set the variable only when browser tests run. Either:
tests/e2e/conftest.py, move it into a session-scoped autouse fixture (withpytest.MonkeyPatch.context()so it is undone), which runs only when a test in that directory is selected; ortests/conftest.py,collect_ignore_glob = ["e2e/*"]unless the-mexpression selectse2e(read fromconfig.getoption("markexpr")inpytest_ignore_collect), which also spares the unit run collecting the browser tests and importing Playwright in every worker (see C1).The first is the smaller change and keeps collection as it is; the second also saves collection time. Either keeps
ci.yml:159's-m e2erun working.What it saves or protects
small (reliability): the unit suite keeps the guard that would catch a synchronous ORM call made from async code; no such code exists today, so the risk is latent
Accessibility
none
Decisions
tests/e2ein unit runs? Recommended: the fixture now; the collection change belongs with C1's--extra chromiumwork if that lands.Found by the efficiency and reliability audit of 2026-10-30 (finding X2; index postulo/postulo#1108). Checked against
mainatdaee30b15(2026-10-30).