From 70fb7a463c97a8097e37430399247726f54edcd9 Mon Sep 17 00:00:00 2001 From: vjrj Date: Sat, 11 Jul 2026 00:26:55 +0200 Subject: [PATCH] test: global 90s timeout + document the hang-proof test workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Diagnosed the recurring 'tests hang' pain by measurement: the logic layer is fast and reliable (dart test commons_core ~1s/82 tests; flutter test test/services ~11s/124 tests, green), and only WIDGET tests hang — because pumpAndSettle() waits for a screen to stop scheduling frames and a live source (Drift/Nostr stream, periodic Timer, connectivity/plugin) never does, so it sits at the 10-minute default and the run looks stuck. - apps/app_seeds/dart_test.yaml sets timeout: 90s so such a test FAILS fast and names itself instead of blocking the whole run. - CLAUDE.md now spells out the split-by-layer workflow (logic via dart test/flutter test test/services; widget tests targeted + timed out; never pumpAndSettle a live screen). --- CLAUDE.md | 9 ++++++--- apps/app_seeds/dart_test.yaml | 13 +++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 apps/app_seeds/dart_test.yaml diff --git a/CLAUDE.md b/CLAUDE.md index fc2b2c3..fb2d0fb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -42,9 +42,12 @@ Dependency direction: **`app_seeds` → `commons_core`, never the reverse.** Bou **Prefer workspace-level commands from the repo root** — one lockfile, one `.dart_tool`, both members at once. Verified working: - `dart pub get` (root) — resolves the whole workspace; don't `pub get` per package. -- `dart analyze` (root) — analyzes `commons_core` **and** `app_seeds` together. Use this as the default gate. -- `dart test packages/commons_core` — pure Dart, fast (~1s), the TDD workhorse. -- **Not** `dart test` for `app_seeds` — it needs `flutter test`, which is slow and has hung here; run it locally/per-package, never as a routine gate (see [testing.md](docs/design/testing.md) and the testing-gotchas memory). +- `dart analyze` (root) — analyzes `commons_core` **and** `app_seeds` together. The default gate. + +**Testing — split by layer; NEVER run the whole `flutter test` blind (it's what "hangs").** Diagnosed 2026-07-11: logic tests are fast and reliable; only *widget* tests hang, because `pumpAndSettle()` on a screen with a never-settling source (live Drift/Nostr stream, periodic `Timer`, connectivity/plugin) waits at the 10-min default. The everyday gate: +- `dart test packages/commons_core` — pure Dart, ~1s. The TDD workhorse. (`dart test` can't run `app_seeds` — it needs `flutter`.) +- `flutter test test/services` — app logic + in-memory DB, no widgets, ~10s, reliable. Put new app logic in plain `test()` here. +- Widget tests: run targeted (`flutter test test/ui/`), always with a timeout so a hang FAILS fast — a global `apps/app_seeds/dart_test.yaml` sets `timeout: 90s`; add `--timeout 30s` when in doubt. Never `pumpAndSettle` a live screen; use bounded `pump(Duration)`. See the testing-gotchas memory + [testing.md](docs/design/testing.md). ## Data model (decided, `schemaVersion = 1`) diff --git a/apps/app_seeds/dart_test.yaml b/apps/app_seeds/dart_test.yaml new file mode 100644 index 0000000..a7c652f --- /dev/null +++ b/apps/app_seeds/dart_test.yaml @@ -0,0 +1,13 @@ +# Global per-test timeout. Without it, a widget test that pumpAndSettle()s a +# screen with a never-settling source (a live Drift/Nostr stream, a periodic +# Timer, connectivity_plus, a plugin) waits at the 10-minute default and the +# whole run LOOKS hung. With this, such a test FAILS in 90s and names itself. +# +# The everyday, hang-proof gate is the logic layer, not widgets: +# dart test packages/commons_core # pure Dart, ~1s +# flutter test test/services # logic + in-memory DB, ~10s, no widgets +# Run widget tests targeted (flutter test test/ui/), never blind, and +# never pumpAndSettle a live screen — pump(Duration) a bounded number of times. +# +# A genuinely slower (but finite) test can opt out with @Timeout(Duration(...)). +timeout: 90s