a73x

docs/testing-practices.md

Ref:   Size: 2.9 KiB   History

# Testing rationale

The prescriptive development rules live in [CLAUDE.md](../CLAUDE.md); this
page records the failures that explain the testing rules there.

- **Assert behavior, don't assume it. Mocks are assumptions.** Real binaries,
  PTYs and shells have caught failures that fixtures standing in for the
  product could never see.
- **A fixture that holds a dimension constant is blind to that dimension.**
  Where a thing can be plural — sessions, tiles, dials, panes — the DEFAULT
  fixture is plural; where a thing has an origin, the default is off-origin.
  N=1 and offset=0 are extra cases, never the baseline. Three escapes in one
  week were each exactly this, and all three passed a green gate: session
  names aliased their neighbour's because every test held ONE session; a tile
  painted over the rail because `col_off` was 0 in every test body; the
  page's own rules went unpinned because no check executed the page.
- **A harness assumption is Linux-only until it has run on both OSes.** The
  shell scripts are the part of this repo with no compiler behind them, and
  the e2e suite's first run on macOS was sixteen groups and ten of these.
  Ask questions through `test/os_oracle.sh` and add an arm rather than a
  branch in a group file. Three shapes bit hardest and are worth knowing by
  name. A backtick inside an UNQUOTED heredoc is a command substitution
  wherever it stands, comments included, and macOS ships programs a Linux
  box does not — a comment that quoted `expect` started `/usr/bin/expect`,
  which read the rest of the heredoc as its own script and hung the group
  for its whole budget. `$TMPDIR` on macOS is a per-user directory that
  ends in `/` and is nearly fifty characters long, so a path spelled from
  it fails a string compare against the same path normalised, and does not
  fit in a label bar. And BSD's `ps` and `wc` answer in a different shape
  from GNU's — a full path where Linux gives a basename, a padded count
  where Linux gives a bare number.
- **Ask the OS about the OS, not the daemon.** A claim about a pid, an fd, a
  socket or a process tree is asserted against `/proc`, `ps`, or the shell's
  own `$$`. A daemon reporting on itself cannot catch itself being wrong —
  which is why `mux d upgrade`'s gate is a shell pid read off the grid.
- A unit test that writes to stdout once wedged `zig build test` at 0 CPU:
  fd 1 is the test-runner protocol stream. The authoritative rule and the
  supported capture pattern are in [CLAUDE.md](../CLAUDE.md#working-rules).
- A hand-run rig once left dozens of dead host entries because it used the
  user's XDG state and runtime directories. Use the wrapper described in
  [development commands](development.md#ad-hoc-reproductions-and-logs), or
  isolate custom sockets and state yourself.
- Debug timings are dominated by ghostty's page-integrity checks. Performance
  claims belong to the ReleaseSafe throughput path documented in
  [CLAUDE.md](../CLAUDE.md#working-rules).