Tests & verification
All app verification artifacts live under App/Tests/ (ADR-0001). Unit tests that run, plus Integration / E2E / TestDocs boxes, share one parent so the product tree (App/Tokfuel*) stays separate from ops trees (Site / Docs / Scripts). This page carries that layout and how verification is meant to work.
Directory layout
App/Tests/
UnitTests/ … Swift Testing; what swift test runs
IntegrationTests/ … integration (placeholder for now)
E2E/ … end-to-end implementations (not under swift test)
TestDocs/ … scenario design (documents, not runnable)
README.md … parent-directory note
UnitTests
Put headless-checkable logic here. TokfuelTests in Package.swift points at this path; swift test runs it. When you add logic, add tests next to that layer.
Do not write tests that touch real user state under ~/Library/Application Support/Tokfuel.
Line coverage
Snapshot from swift test --enable-code-coverage (2026-08-08). App/ sources only — dependency checkouts excluded.
367 unit tests / 63 suites
App total 2821 / 7800 lines (36.2%)
TokfuelCursor
TokfuelCore
TokfuelSettings
TokfuelBudget
TokfuelStore
TokfuelClaude
TokfuelCodex
TokfuelAnalytics
TokfuelUI
Tokfuel (app)
TokfuelUI and the Tokfuel executable skew toward SwiftUI surfaces, so line coverage reads low there. Looks go through ui-preview; headless logic stays in UnitTests.
IntegrationTests
Placeholder for integration tests (README only today). When you add some, use a separate test target or an explicit Package.swift entry — do not dump them into the default UnitTests path.
E2E
Home for end-to-end implementations. Not part of swift test; a separate runner is expected. Do not bring in mobile stacks like Maestro or Appium. Add only what a macOS menu-bar app needs (launch smoke, screen reach) as later Issues require. Scenario design stays canonical in TestDocs.
TestDocs
Scenario design documents — not runnable code. Keep coverage viewpoints here; progress is ticket → implement → update status. Templates, viewpoint IDs, and individual scenarios land in later Issues; the directory box is reserved first.
What UnitTests cover
Store / aggregation & display shaping
UsageStore — totals, charts, per-model breakdown, refresh
CostChart / CostDisplayMode / Formatting — display shaping and modes
MenuBarReadout / MenuBarImage — menu-bar text and rendering
RefreshScheduler — idle vs active refresh intervals
Claude (retok)
RetokReport — report decoding
TranscriptScanner — transcript scanning
AdvicePrompt — saving-tip prompts
Cursor / Codex
CursorDashboardService / CursorPricing / CursorPricingService — dashboard fetch and price table
CursorCostDriver / CursorAdvice — cost estimate and advice
CodexCostDriver — cost from Codex CLI sessions
Budget / Settings / other
BudgetMonitor — monthly / daily thresholds and once-per-level alerts
AppSettings — UserDefaults-backed settings
CSVExportService — on-device CSV export
UpdateChecker — Releases polling and download boundary
HTTPClient / RemoteDiagnosticsPolicy / UsageEventLog — networking and diagnostics policy
ScreenshotRenderer — fixture screens for ui-preview
Local verification gates
swift test— runs App/Tests/UnitTests. Baseline gate before a PR.swift build -c release— release build close to what Scripts/build.sh packages.bash Scripts/build.sh— installs Tokfuel.app into /Applications and launches it for runtime observation. Do not claim unverified behavior works.
CI
.github/workflows/ci.yml runs unit tests on PRs that touch App/Tokfuel, App/Tests, Package.swift, and related paths. Docs / Site-only changes skip that job. Release packaging is checked via Scripts/build.sh and the distribution flow.
UI preview (screenshots)
Keep new UI visible to reviewers. When you add or change PopoverView, SettingsView, AboutView, or any new standalone View (consent dialogs, alerts, …), update the following in the same PR:
ScreenshotRenderer.allScreens() fixtures
ORDER / screen_title lists in ui-preview.yml
PRs labeled ui-preview can render those states. Views only reachable through live singletons (network responses, real install paths) need injectable fixtures (see UpdateChecker.preview). Put dialog copy in a SwiftUI view shared by runtime and preview.
How coverage is chosen
Prefer UnitTests for logic that can be checked headlessly. Looks and reachability are covered by ui-preview (VRT-like) and E2E only where needed. Write “what we guarantee” in TestDocs, then implement in UnitTests / IntegrationTests / E2E.