Testing Strategy

Test Layers

  • Unit tests: parsing, validation, state machines, and extracted class behavior.

  • Integration tests: WireMock-based API contract verification and E2E generation.

  • Deterministic async harnesses: TUI state machine tests use UiScheduler.immediate() and Duration.ZERO debounce.

  • Property-based tests: ZIP extraction edge cases (path traversal, large archives).

  • Headless CLI tests: HeadlessCli entry point smoke tests (no-subcommand, help, version).

  • Architecture guardrails: ArchUnit tests prevent package-boundary drift across application, cli, runtime, headless, postgen, persistence, and ui.

TUI Test Strategy

TUI tests follow a two-layer approach:

  • Semantic behavior tests first: assert controller state (focusTarget, generation state, exit plans, filters, errors).

  • Golden/render tests selectively: keep a smaller set of snapshot-style assertions for UX copy/layout regression.

Prefer semantic assertions for navigation/workflow logic, and reserve render-string assertions for user-facing text contracts.

UI State-Machine Refactor Contract Baseline

Before and during the UI state-machine migration, these semantic contracts must remain green:

  • routing precedence (overlay/cancel/quit/loading/global/focus/input)

  • generation transitions (IDLE → LOADING → SUCCESS|ERROR|CANCELLED)

  • post-generation exit-plan semantics

  • focus transition semantics

  • extension cancel unwind order

  • overlay layering/z-order contracts

  • resize/tick event behavior

  • catalog load success/failure semantics and startup overlay visibility

  • stale-token completion no-op behavior for async catalog/generation callbacks

  • single-writer transition discipline (state transitions on render thread)

Dedicated Test Suites for Extracted Classes

Class Tests Coverage

PostGenerationMenuState

focused unit suite

Reducer-backed key translation and post-generation menu command routing

MetadataSelectorManager

12

Selector sync, option cycling, boundary conditions

CatalogRowBuilder

24

Section headers, favorites, recents, deduplication

StartupOverlayTracker

8

Duration tracking, visibility state, timing edge cases

CoreUiReducer + UiRenderStateAssembler

contract-focused

Reducer intent/effect outcomes and immutable state snapshot mapping contracts

Architecture Guardrails

HeadlessArchitectureRulesTest is the package-boundary lock-in suite for the refactored codebase.

It asserts, among other things, that:

  • application/ stays independent from CLI, runtime, headless, post-generation, persistence, and UI packages.

  • headless/ remains independent from runtime and TamboUI, with CLI coupling limited to the orchestration boundary types.

  • runtime/ owns the composition root, with RuntimeServices as the only runtime entrypoint allowed to open the headless generation service from an active runtime session.

  • postgen/ stays isolated from CLI/headless/persistence/runtime concerns, and owns TuiSessionSummary so the post-generation seam does not depend back on runtime/.

Run the suite directly with:

./mvnw -q -Dtest=HeadlessArchitectureRulesTest test

Core Verification Commands

The shared verification entrypoints under scripts/verify/ are the source of truth used by CI, release automation, and local maintainer workflows.

scripts/verify/format-check.sh
scripts/verify/verify.sh
scripts/verify/headless-compile.sh
scripts/verify/coverage.sh
scripts/verify/docs-build.sh
scripts/verify/docs-linkcheck.sh
scripts/verify/native-size.sh headless
scripts/verify/native-size.sh interactive
scripts/verify/native-release-smoke.sh <binary> <headless|interactive-posix|interactive-windows>

Or using the included justfile:

just format-check      # spotless:check
just test-unit         # unit tests only
just test              # unit + integration (verify)
just headless-check    # headless profile compile
just docs-build        # docs build verification
just docs-linkcheck    # docs link checking
just verify            # format-check + headless-check + test

CI runs both docs build and docs link checking as separate verification steps. Docs Pages uses the same shared entrypoints when publishing the site.

Release packaging uses scripts/verify/native-release-smoke.sh for both headless and interactive native artifacts. POSIX release runners use the interactive smoke mode, while Windows release runners stay on headless smoke because GitHub Actions does not provide a reliable interactive terminal.

Coverage

JaCoCo reports are generated during scripts/verify/coverage.sh (or just coverage).

  • ./mvnw test (unit-only) does not publish JaCoCo site reports.

  • scripts/verify/coverage.sh publishes merged reports:

    • HTML: target/site/jacoco/index.html

    • XML: target/site/jacoco/jacoco.xml

In CI, a dedicated coverage job runs scripts/verify/coverage.sh on Linux, generates both reports, and uploads them to Codecov and as GitHub Actions artifacts (14-day retention).

To generate coverage locally:

scripts/verify/coverage.sh
# or: just coverage
open target/site/jacoco/index.html  # macOS
x-www-browser target/site/jacoco/index.html  # Linux
start target/site/jacoco/index.html  # Windows (cmd.exe)

Platform Independence

  • Path assertions use Path.toString() instead of hard-coded forward slashes.

  • Temp directories use @TempDir for cross-platform cleanup.

Docs Verification

scripts/verify/docs-build.sh
scripts/verify/docs-linkcheck.sh