test suite is too slow to run, improve it #8
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?
Done. 1075s -> ~55s for the full 38-test suite, and it no longer depends on how busy the phone is.
I timed every test individually before changing anything, because the obvious theory was wrong. The suite was not slow because tests wait for simulated time - most wait under 2 seconds. Splitting the fixed cost with a stopwatch script (
tests/_profile_startup.gd) found it:load("res://Main.tscn")was 8.5 seconds, and nearly every test loads it. The cause is the filesystem: the project lives under~/storage/shared, which is Android's FUSE bridge, read through proot on top of that. The same load from a native path is ~2s.What changed
1. Tests run from a copy on Termux's own filesystem.
run_tests.shsyncs the project (~1.4s for the whole suite,.godotimport cache kept warm between runs) into~/.cache/spaceship-testsand runs there. This is the single biggest win and it also sidesteps the FUSE mtime trap, since the copy gets fresh content every run.2. Tests run 6 at a time. Each test is its own Godot process - they call
quit()and stamp on theGameStateautoload, so they cannot share one - which makes the suite a pile of independent, single-core-bound jobs on an 8-core phone. Output is buffered per test and printed only for failures.3. One
proot-distro loginfor the whole run instead of one per test (~0.5s x 38). The container-side half lives intests/_run_inside.sh.4.
--fixed-fps 60. Parallelism alone made the suite lie:test_camera_settlesandtest_planet_prompt_map_interactionfailed on 2 of 3 runs. A test'selapsedcounted REAL seconds, so six processes at once stretched every frame and the gameplay under test saw deltas it never sees in the game. Pinned to 1/60, a test simulates the same 60fps whatever else the machine is doing, and its result no longer depends on load.5.
test_extractor_incomefixture shortened. It sat through a full hauler round trip, and the cycle length is distance/speed - so the fixture distance was the runtime. 4000 units = ~31s of simulated travel; 600 units = ~4.6s. Nothing in it asserts on the distance, only that payout and drawn position track the sameprogress.A test now counts as passed only if it both exits 0 and prints
: PASS, so a crash before reaching its verdict can no longer be mistaken for success.A real bug this surfaced
Pinning the frame rate broke
test_joystick_control- and it turned out to be the game, not the test.Ship._physics_processsetsvelocity = Vector2.ZEROthe moment a ship is withinarrive_radiusof its slot, even though the anchor is still dragging that slot forward atcruise_speedunderneath it.Fleet.stop()braked from that instantaneousvelocity, so releasing the joystick on any frame where the ships happened to be seated stopped the fleet dead instead of coasting.How often that happens depends on the frame rate, because the anchor advances
cruise_speed * deltaper frame. At the ~25fps the headless tests used to run at, it steps ~10 units, ships always lag and always report motion - which is the only reason releasing the stick ever looked right. At a steady 60fps it steps ~4 units and they are often seated. On a fast device this bug is visible in the real game.Fixed in
Fleet.stop()by braking from the ship's true motion,velocity + fleet_velocity- the fleet's own cruise velocity, which each ship already carries as context (and which is zero for a point-to-pointmove_to, wherevelocityalone is the whole story).fleet_velocityis now cleared on stop so a halted ship does not keep facing a heading it is not travelling on.The test deserved part of the blame too: it asserted
centroid.x > moving_centroid.x, which any float wobble satisfies. It now asserts the actual coast distance against the physics -cruise_speed^2 / (2 * acceleration)= ~75 units. Measured 75.1 with the fix, 0.0 without it.Verification
Three consecutive full runs after the fix: 38/38, 38/38, 38/38 in 83s / 52s / 56s. No flakes.
Usage