zudo-test-wisdom
GitHub repository

Type to search...

to open search from anywhere

The Walking-Skeleton E2E

Keep a thin representative for shared integration wiring and add evidence for independent critical boundaries.

Start with One Representative of the Same Path

An external-service feature needs proof of end-to-end wiring, not every input and response replayed through a browser. Start with one thin, untagged, CI-safe journey representing the same integration path, such as e2e/doc-cloud-walking-skeleton.spec.ts.

“One” is neither a permanent system-wide ceiling nor a minimum to add for every feature. An independent authentication, upload, or native boundary may warrant additional proof. Move combinations on the same wiring to cheaper levels; protect a distinct important path with another thin test when needed. Never pack unrelated journeys into one huge spec just to satisfy a count limit.

This is the narrow complement to the aggregate suite budget. The budget page explains why a collection of individually cheap tests can still drown a gate; the walking skeleton prevents that collection from forming. The heavy-test decision rule still decides whether an individual heavy test deserves its tier, but the walking skeleton asks an earlier question: does this proposed e2e variant prove any new integration wiring? If it only adds another input or response condition, it does not.

Note

Untagged is part of the contract. The journey is ordinary T1 coverage, not a special @heavy or scheduled specimen. Keep the fake deterministic and the path short enough that the one proof runs on every PR.

The Worked Journey: Touch Every Joint Once

Consider a document-cloud integration. Its single journey has this shape:

  1. Paste a token. Enter the test token through the same credential UI a user sees. The token reaches the application’s credential boundary; the fake never requires a live secret.

  2. Load the project list. Wait for projects returned by the fake service and choose one. This proves that credential state, the adapter, and the first remote read are connected.

  3. Open a page tab in the same frame. Select a page and record the editor frame’s stable identity. Opening the tab must reuse that frame rather than silently replacing it with a new browsing context.

  4. Edit the page. Change a small, unmistakable piece of content through the editor surface while continuing to assert the same frame identity.

  5. Perform a guarded save. Save with the current remote revision or equivalent write guard. Do not weaken the journey into an unconditional write merely because the fake would accept one.

  6. Verify the refetch in the trace. Read the fake service’s redacted request trace and assert that the guarded write was followed by the expected refetch. The UI reaching a saved-looking state is not proof that this request crossed the seam; the trace proves that it actually happened without exposing the pasted token.

  7. Publish. Trigger the normal publish action against the same fake-backed project and remain in the same editor frame.

  8. Observe the accepted-state chip. Finish on the stable UI outcome: the accepted-state chip appears for the published revision.

The frame identity assertion spans the journey rather than appearing once at setup. Token paste, list load, tab selection, editing, saving, refetch, publishing, and acceptance must all occur through the same long-lived frame. If the application accidentally remounts or swaps the frame halfway through, the final chip alone can still look correct while in-memory editor state, subscriptions, or message routing have been discarded. The walking skeleton guards the integration joint, not just the screenshot at the end.

The journey’s fake belongs at the external-service seam, where requests can be observed without mocking the application’s own adapter away. Use the stateful fake-service recipe so the list, guarded write, refetch, publish, and accepted state are successive observations of one service state rather than unrelated canned responses.

The Trace Is Evidence, Not Another UI Assertion

The redacted request trace closes a specific false-green path. A save handler can update local state optimistically, the accepted-looking UI can appear, and the guarded network request can be missing or malformed. Asking the same UI whether it saved only repeats the application’s own claim.

Instead, inspect the fake from the other side of the seam. The trace entry should establish the request sequence and the non-secret guard metadata needed by the contract: the guarded save arrived, it targeted the selected page, and the application performed the follow-up refetch before publishing. Redaction happens before the trace becomes test evidence, so credential handling is exercised without turning the artifact into a credential leak.

Keep this assertion narrow. The trace is not an invitation to reproduce every header, conflict response, or payload permutation in the browser journey. It supplies independent evidence for the one integration transition whose UI result could otherwise self-agree.

Put Every Matrix Below E2E

The walking skeleton owns topology: can one representative action cross every required boundary and return as observable state? Cheaper suites own breadth:

Behavior familyDeliberate homeWhy it does not extend the journey
Conflict matricesUnit tests around revision and conflict policy; component tests for each conflict presentationThese vary guards and resolutions, not integration topology
SSE failure casesUnit tests for parsing, retry, ordering, and deduplication; component tests for disconnected and recovery statesA dropped, duplicated, or malformed event is a state-machine branch, not another full user journey
Sanitizer casesUnit tests over the complete malicious and malformed input corpusBrowser setup adds cost without improving proof of the transformation contract
Credential handlingUnit tests for storage, redaction, expiry, and rejection; component tests for credential UI statesThe skeleton pastes one safe test token only to prove wiring; it must not become a credential matrix

The split is deliberate even when a variant is important. Importance does not imply e2e. A conflict policy can deserve dozens of cases while deserving zero additional browser journeys. The heavy-test decision rule requires mapping guarantees before moving proof to a lower level; here, demotion is the planned architecture, not a rescue performed after the e2e suite becomes slow.

Warning

Do not append “just one more step” to the walking skeleton to cover a new branch. A step that changes the representative path replaces the old representative when it is genuinely better; it does not accumulate beside it. A variant that exercises the same joints moves to unit or component coverage.

Write the Boundary Where Contributors Will See It

Put the allocation beside the suite — for example, in e2e/README.md — rather than leaving it in a planning issue or a reviewer’s memory. The note should name all three parts of the contract:

  • e2e/doc-cloud-walking-skeleton.spec.ts is the representative untagged e2e spec for this integration path and walks token → list → same-frame edit → guarded save/refetch → publish → accepted state.

  • Conflict matrices, SSE failures, sanitizer cases, and credential variants belong to named unit/component suite locations.

  • A proposal to add an e2e step or variant must either replace the existing representative path or explain a genuinely new integration joint; “important behavior” alone is not sufficient.

That local record survives the two moments when oral convention does not: a new contributor looking for where to add coverage, and a new agent session inferring policy from the files it can see. The README turns absence into an enforceable design choice. Without it, one spec looks merely unfinished.

Bound Growth While the Topology Is Unchanged

Grow cheaper suites for value/state combinations on the same wiring. Independent critical boundaries may legitimately increase integration coverage and cost; T1 cost is not permanently constant. Preserve required contracts under test lifecycle and measure the aggregate suite budget.

Revision History

CreatedUpdated