Running the tests¶
That is the whole suite. What CI runs is a set of nox sessions, each in its own environment, and any of them can be reproduced:
uv run nox -s tests # the suite, on a clean install
uv run nox -s typeguard # the suite with runtime type checking
uv run nox -s xdoctest # the examples in docstrings
uv run nox -s models-check # the generated config models are current
uv run nox -s docs-build # the site, in strict mode
The frontend¶
The editor's page and the scripts of the HTML pages share a suite, and it runs in CI as the page job:
It is not optional dressing. The bridge between the form and the YAML document is where a bug would be silent — a save that quietly drops what the schema does not describe — so those tests are the ones holding the design up.
The translations of the pages¶
The Italian catalog of the HTML pages, packages/fastgeoapi-html/fastgeoapi_html/locale/it/LC_MESSAGES/messages.po, is edited by hand, and tests/test_html_catalogs.py keeps it complete: it extracts every string from the templates and from app/html, and fails on each one the catalog does not translate. A string you add to a page therefore needs its msgid and msgstr in the catalog in the same change. The pages read the .po file as it is, so there is no .mo to compile.
Before you push¶
It does not see untracked files
--all-files means every file git knows about. A file you have just created is not one of them, so the hooks skip it and CI is the first thing to complain. git add -N the new files first — this has cost red builds here more than once.
Two traps this suite has sprung repeatedly¶
Purged modules. Some tests clear sys.modules. After that, a module imported at the top of a test file and the same module imported inside a test are two different objects — so a monkeypatch lands on the one nobody calls, and the test passes alone while failing in the suite. Take the module and the thing you are patching together, inside the test.
Tests that never failed. A green test proves nothing until you have seen it red for the right reason. Where that is impossible — coverage added to code that already works — break the code deliberately and check that the test notices.
The loop must not block¶
A provider that declares itself natively asynchronous makes a claim the suite can check. blockbuster is in the dev group: inside blockbuster_ctx() any blocking call made on the event loop — a socket, a file, time.sleep — raises BlockingError, while the same call made in a worker thread is allowed, because that is where it belongs.
from blockbuster import blockbuster_ctx
with blockbuster_ctx():
tile = await async_view(provider).get_tiles(...)
See Writing an async provider for the red-first version of that test.