1
0
mirror of https://github.com/home-assistant/supervisor.git synced 2026-05-25 00:58:47 +01:00
Files
supervisor/tests/os
Stefan Agner 3f6c006a6a Run pytest in parallel with pytest-xdist (#6825)
* Run pytest in parallel with pytest-xdist

CI executes the full pytest suite serially, which currently takes
around 4-5 minutes. Most of that time is spent in fixture setup
(D-Bus session, mock services, CoreSys construction) rather than the
test bodies, but each test pays this setup cost on its own worker.

Add pytest-xdist and run with -n auto --dist=loadfile so tests are
distributed across CPU cores while keeping all tests of a file on the
same worker (preserves locality and keeps progress output readable).
GitHub Actions standard runners ship 4 vCPUs, so -n auto picks 4
workers in CI; locally on 8-core machines it picks 8. This matches
the pattern Home Assistant Core has been running for a long time
(--numprocesses auto --dist=loadfile in core's pytest-full job),
so the configuration is already battle-tested in a sibling project.

On an 8-core machine this cuts the local run from ~280s to ~88s
(~3.2x); on the 4-vCPU CI runner expect roughly a ~2x reduction.

The dbus-daemon and other session-scoped fixtures are spawned per
worker, so there is no shared state. pytest-cov already handles xdist
worker coverage merging via the standard .coverage.* files.

* Poll for resolution state in datadisk signal tests

test_multiple_datadisk_add_remove_signals and
test_disabled_datadisk_add_remove_signals fire UDisks2
InterfacesAdded/InterfacesRemoved signals through the real session
dbus-daemon and then assert that supervisor's signal handler chain
has updated coresys.resolution.issues. Each assertion was preceded
by ``await udisks2_service.ping()`` (only confirms signal delivery)
and ``await asyncio.sleep(0.2)`` to let the chained async tasks
finish.

The 0.2 s margin was effectively only 0.1 s of slack:
DataDisk._udisks2_interface_added itself does
``await asyncio.sleep(0.1)`` internally to wait for
UDisks2._interfaces_added (a sibling subscriber on the same signal)
to finish updating the block-device cache before the check runs.
Under xdist parallelism on a 4-vCPU CI runner that 100 ms cushion
evaporates, and the assertion races the handler.

Bumping the test sleep would just kick the can. Instead, replace
the four ``sleep+assert`` sites with a small polling helper
(tests.common.wait_for) that re-checks the predicate every 10 ms
up to a 5 s deadline. The wait completes the moment the resolution
state matches, so the test stays fast on idle and is robust under
load — and the assertion's failure mode becomes a clear "predicate
did not become true within 5 s" instead of a value mismatch.

The product-code sleep inside _udisks2_interface_added is still a
real smell (handler ordering shouldn't depend on a fixed sleep)
but is left for a separate fix; this commit is scoped to the test.
2026-05-08 21:51:55 +02:00
..
2021-09-17 15:01:07 +02:00