okami.mom/albedo

git clone https://git.nkp.pet/okami.mom/albedo

dawnadd charm tui skillf7fcae1

main
6.8 KiB83 linesraw

Testing and release

The worked examples pair concrete changes with real regression tests. Demo test instructions distinguish executed core tests from unexecuted Charm and terminal checks.

Test the user contract in layers

Do not let a screenshot test stand in for state correctness, or a reducer test stand in for a terminal test. Choose the smallest layer that proves each property.

1. State and effect tests

Feed messages directly into the model. Assert state and the presence/absence of the next command. For asynchronous behavior, use controlled completions rather than sleeps. Execute simple commands in a fixture when useful; do not treat a composite batch as if it were one ordinary result.

Required cases for the relevant features:

ContractAdversarial sequence
Filter owns printable keysFocus search; type qjk/? ; app remains active and query changes correctly
Modal consumes onceOpen modal; close with Enter/Escape; underlying selection does not activate
Latest query winsStart A; type B; deliver A before B's debounce; ignore A
Stale failure is harmlessComplete B successfully, then fail A; keep B's success and rows
Cancellation is realCancel owner; blocked work observes context or declared shutdown policy
No empty acceptanceFilter to zero results; Enter, toggle, and navigation cannot index an item
Stable selectionSelect an ID; refresh/reorder/filter; selection does not jump by index
Follow-tail respects readingScroll away; append output; anchor remains; jump-to-latest restores following
Retry remains usableFail an operation; retry; succeed without restarting the program
Output has a contractAccepted/cancelled/error paths produce distinct intended stdout and statuses

The standalone contract exercises cover several of these policies without Charm dependencies. They are not integration tests for any application.

2. Render and layout tests

Create deterministic model snapshots. For v2, inspect the root View().Content as appropriate; assert mode/cursor metadata separately. Freeze width, height, dataset, clock, operation state, theme, and animation frame. Normalize only values that are intentionally nondeterministic.

Test ordinary and hostile sizes. Suggested fixtures are 80x24, 120x40, 40x12, 20x6, 1x1, and an initial 0x0 message. These are test inputs, not universal supported minimums. For every supported mode, verify the rendered cell bounds, valid cursor positions, body allocation, and visible essential actions. Below the declared minimum, verify the safe fallback and responsive cancellation.

Use display-width helpers for assertions. Add long paths, CJK, combining sequences, emoji, trusted ANSI styles, no matches, one item, and a large dataset. Explicitly test the effect of a wrapping footer and a prompt prefix.

A golden snapshot is a proposed visual contract. Review its changes like code. Do not repeatedly run an update flag until a regression becomes the expected result. Keep assertions for semantic state and dimensions alongside snapshots so a golden cannot silently bless a wrong action or overflow.

3. Program-level integration

Use the matching-major helper: github.com/charmbracelet/x/exp/teatest/v2 for Tea v2, not the similarly named legacy module. The inspected v2 helper offers NewTestModel, WithInitialTermSize, WithProgramOptions, Type, Send, WaitFor, FinalModel, and WithFinalTimeout. S14

Wait for a specific state/output condition, send input, and use a bounded final timeout. Arrange cleanup even when an assertion fails. Check the final model's accepted/cancelled result, not merely whether some text appeared. Preserve the distinction between a simulated key event and a real bracketed paste or terminal signal.

When passing program options, verify which options the helper overrides. Pin color profile and terminal size where supported. Avoid recording a new golden for whatever capabilities happen to be present on a developer machine.

4. Real terminal / PTY checks

Run a real terminal or pseudoterminal flow to verify behavior that direct model tests do not establish: resize delivery, raw/canonical modes, restored cursor, alternate-screen exit, paste handling, interrupt, and child-process handoff. Test stdin data plus a terminal input source for pipeline commands. Check that diagnostic output does not corrupt either the screen or stdout's result.

For a targeted platform, use the terminal environments actually supported. A local truecolor terminal is not proof of correctness over SSH, in a multiplexer, or on another OS. Declare untested platforms rather than claiming all-terminal support.

VHS can script interaction, wait for screen content, capture frames, and generate textual/ASCII artifacts for regression review. Pin recording conditions and use assertions in the surrounding test workflow; producing a GIF alone is not a pass/fail test. S15

Performance checks

Measure representative workloads and report units, data size, terminal size, and environment. Useful measurements include startup-to-interactive time, update/render duration, allocations per render, idle CPU, resize behavior, and memory growth during a long stream.

Use relative before/after comparisons on the same fixtures. Do not promise a universal millisecond threshold without a target system. Inject backend latency and failures to verify responsiveness while work is pending. Measure worst-case no-match filtering and heavy wrapping, not only a warm cache with a short query.

Run benchmarks in the target repository, for example:

go test ./...
go test -race ./...
go test -run '^$' -bench . -benchmem ./...

These commands may have platform, compiler, network, or fixture prerequisites. Report exact scope and failures. A race-test pass is useful evidence, not a mathematical proof that every schedule is safe.

Release review

Before calling the UI finished, establish all applicable facts:

  • The primary task works with the keyboard, and current help describes working controls.
  • Acceptance, cancellation, errors, and interrupted work have correct outputs and cleanup.
  • Normal and small layouts were inspected; zero-size and no-match states are safe.
  • Light/dark or the deliberately supported theme, monochrome, and ordinary fonts remain understandable.
  • Existing interaction and appearance were compared on fixed fixtures when behavior preservation was requested.
  • No unnecessary dependency migration, configuration system, or component framework was introduced.

Use a delivery note with four short fields: changed, preserved, verified, not verified. Include actual command outcomes or terminal evidence. “Source-reviewed only” is more useful than an unsupported claim of production readiness.

1# Testing and release
2
3The [worked examples](../examples/WORKED-EXAMPLES.md) pair concrete changes with real regression tests. [Demo test instructions](../examples/worked/README.md) distinguish executed core tests from unexecuted Charm and terminal checks.
4
5## Test the user contract in layers
6
7Do not let a screenshot test stand in for state correctness, or a reducer test stand in for a terminal test. Choose the smallest layer that proves each property.
8
9### 1. State and effect tests
10
11Feed messages directly into the model. Assert state and the presence/absence of the next command. For asynchronous behavior, use controlled completions rather than sleeps. Execute simple commands in a fixture when useful; do not treat a composite batch as if it were one ordinary result.
12
13Required cases for the relevant features:
14
15| Contract | Adversarial sequence |
16| --- | --- |
17| Filter owns printable keys | Focus search; type `qjk/? `; app remains active and query changes correctly |
18| Modal consumes once | Open modal; close with Enter/Escape; underlying selection does not activate |
19| Latest query wins | Start A; type B; deliver A before B's debounce; ignore A |
20| Stale failure is harmless | Complete B successfully, then fail A; keep B's success and rows |
21| Cancellation is real | Cancel owner; blocked work observes context or declared shutdown policy |
22| No empty acceptance | Filter to zero results; Enter, toggle, and navigation cannot index an item |
23| Stable selection | Select an ID; refresh/reorder/filter; selection does not jump by index |
24| Follow-tail respects reading | Scroll away; append output; anchor remains; jump-to-latest restores following |
25| Retry remains usable | Fail an operation; retry; succeed without restarting the program |
26| Output has a contract | Accepted/cancelled/error paths produce distinct intended stdout and statuses |
27
28The [standalone contract exercises](../examples/contracts/README.md) cover several of these policies without Charm dependencies. They are not integration tests for any application.
29
30### 2. Render and layout tests
31
32Create deterministic model snapshots. For v2, inspect the root `View().Content` as appropriate; assert mode/cursor metadata separately. Freeze width, height, dataset, clock, operation state, theme, and animation frame. Normalize only values that are intentionally nondeterministic.
33
34Test ordinary and hostile sizes. Suggested fixtures are `80x24`, `120x40`, `40x12`, `20x6`, `1x1`, and an initial `0x0` message. These are test inputs, not universal supported minimums. For every supported mode, verify the rendered cell bounds, valid cursor positions, body allocation, and visible essential actions. Below the declared minimum, verify the safe fallback and responsive cancellation.
35
36Use display-width helpers for assertions. Add long paths, CJK, combining sequences, emoji, trusted ANSI styles, no matches, one item, and a large dataset. Explicitly test the effect of a wrapping footer and a prompt prefix.
37
38A golden snapshot is a proposed visual contract. Review its changes like code. Do not repeatedly run an update flag until a regression becomes the expected result. Keep assertions for semantic state and dimensions alongside snapshots so a golden cannot silently bless a wrong action or overflow.
39
40### 3. Program-level integration
41
42Use the matching-major helper: `github.com/charmbracelet/x/exp/teatest/v2` for Tea v2, not the similarly named legacy module. The inspected v2 helper offers `NewTestModel`, `WithInitialTermSize`, `WithProgramOptions`, `Type`, `Send`, `WaitFor`, `FinalModel`, and `WithFinalTimeout`. [S14](sources.md#s14)
43
44Wait for a specific state/output condition, send input, and use a bounded final timeout. Arrange cleanup even when an assertion fails. Check the final model's accepted/cancelled result, not merely whether some text appeared. Preserve the distinction between a simulated key event and a real bracketed paste or terminal signal.
45
46When passing program options, verify which options the helper overrides. Pin color profile and terminal size where supported. Avoid recording a new golden for whatever capabilities happen to be present on a developer machine.
47
48### 4. Real terminal / PTY checks
49
50Run a real terminal or pseudoterminal flow to verify behavior that direct model tests do not establish: resize delivery, raw/canonical modes, restored cursor, alternate-screen exit, paste handling, interrupt, and child-process handoff. Test stdin data plus a terminal input source for pipeline commands. Check that diagnostic output does not corrupt either the screen or stdout's result.
51
52For a targeted platform, use the terminal environments actually supported. A local truecolor terminal is not proof of correctness over SSH, in a multiplexer, or on another OS. Declare untested platforms rather than claiming all-terminal support.
53
54VHS can script interaction, wait for screen content, capture frames, and generate textual/ASCII artifacts for regression review. Pin recording conditions and use assertions in the surrounding test workflow; producing a GIF alone is not a pass/fail test. [S15](sources.md#s15)
55
56## Performance checks
57
58Measure representative workloads and report units, data size, terminal size, and environment. Useful measurements include startup-to-interactive time, update/render duration, allocations per render, idle CPU, resize behavior, and memory growth during a long stream.
59
60Use relative before/after comparisons on the same fixtures. Do not promise a universal millisecond threshold without a target system. Inject backend latency and failures to verify responsiveness while work is pending. Measure worst-case no-match filtering and heavy wrapping, not only a warm cache with a short query.
61
62Run benchmarks in the target repository, for example:
63
64```sh
65go test ./...
66go test -race ./...
67go test -run '^$' -bench . -benchmem ./...
68```
69
70These commands may have platform, compiler, network, or fixture prerequisites. Report exact scope and failures. A race-test pass is useful evidence, not a mathematical proof that every schedule is safe.
71
72## Release review
73
74Before calling the UI finished, establish all applicable facts:
75
76- The primary task works with the keyboard, and current help describes working controls.
77- Acceptance, cancellation, errors, and interrupted work have correct outputs and cleanup.
78- Normal and small layouts were inspected; zero-size and no-match states are safe.
79- Light/dark or the deliberately supported theme, monochrome, and ordinary fonts remain understandable.
80- Existing interaction and appearance were compared on fixed fixtures when behavior preservation was requested.
81- No unnecessary dependency migration, configuration system, or component framework was introduced.
82
83Use a delivery note with four short fields: **changed**, **preserved**, **verified**, **not verified**. Include actual command outcomes or terminal evidence. “Source-reviewed only” is more useful than an unsupported claim of production readiness.