Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

7 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

tuicov logo: four coverage cells converging under a terminal scanner

tuicov

Four native coverage engines. One clear story for terminal UIs.

Framework end-to-end tests Status: alpha Python 3.9+ arXiv: 2608.03743 License: MIT

Four language-native coverage streams converging through a terminal scanner into one unified report

tuicov instruments terminal applications with the coverage runtime their language already trusts, then normalizes the evidence into cumulative line and widget reports. No tuicov runtime library is added to the application.

Think of it as an air-traffic controller for coverage: Rust, Go, Python, and TypeScript arrive in different formats; tuicov guides them into the same report.

🌈 One coverage story, four ecosystems

Language TUI framework Native line coverage Live collection
πŸ¦€ Rust ratatui LLVM source-based coverage Continuous profiles where LLVM supports them
🫧 Go Bubble Tea go build -cover integration coverage Complete counters at normal exit
🐍 Python Textual coverage.py SIGUSR2 snapshots where available
πŸ’  TypeScript Ink Node.js V8 coverage + source maps v8.takeCoverage() snapshots where available

tuicov also discovers widget construction and render sites statically. A widget site is covered when its source span executes, giving line and widget coverage the same simple meaning: the code at this stable source location ran.

πŸš€ Take your first scan

Install from the checkout

tuicov supports Python 3.9+ and has no mandatory Python runtime dependency outside the standard library.

uv sync --locked
uv run tuicov --version

uv creates the ignored .venv using .python-version; activation is optional.

Inspect without building

uv run tuicov inspect ./path/to/app

That command detects the framework and prints the widget inventory. It is safe to use as an early configuration check on machines that do not have every native toolchain.

Instrument, run, report

# Build the native instrumented target and persist its plan
uv run tuicov instrument ./path/to/app --types line,widget

# Run in a real terminal and collect cumulative snapshots every two seconds
uv run tuicov run ./path/to/app --types line,widget --interval 2s

# Rebuild JSON and HTML reports from persisted native artifacts
uv run tuicov report ./path/to/app

Use instrument --dry-run to persist and print the complete plan without executing its build commands.

πŸ”­ How the scan flows

flowchart LR
    S["TUI source"] --> D["Framework detection"]
    D --> A["Native adapter"]
    A --> M["Manifest + widget inventory"]
    M --> N["Native coverage runtime"]
    N --> Z["Normalized snapshots"]
    Z --> J["report.json"]
    Z --> H["report.html"]
Loading

Each adapter owns detection, native build preparation, launch environment, snapshot requests, and result conversion. Everything after normalization is framework-neutral.

The ratatui adapter resolves the debug binary from Cargo metadata and honors CARGO_TARGET_DIR. The target directory captured in the manifest is reused for later builds and runs, preventing tuicov from instrumenting one binary and profiling another. For unusual workspaces or renamed targets, pass the command explicitly.

🧰 Native toolchain checklist

The application still needs its own ecosystem:

  • Rust: llvm-profdata and llvm-cov, usually from rustup component add llvm-tools-preview
  • Go: Go 1.20 or newer
  • Python: coverage.py in the selected Python environment
  • Ink: a Node.js version with NODE_V8_COVERAGE

TUIs need a real terminal. Run tuicov run interactively or place it inside a PTY driver such as Microsoft shell-use.

⚑ Collect while the app is alive

Start interval and request-triggered collection together:

uv run tuicov run ./path/to/app \
  --interval 2s \
  --on-request \
  --listen 127.0.0.1:0

tuicov prints the chosen endpoint and writes it to .tuicov/service.json. While the application is running:

curl -X POST http://127.0.0.1:PORT/collect
curl http://127.0.0.1:PORT/health
curl http://127.0.0.1:PORT/report

The service accepts loopback addresses only. Snapshots are cumulative: later snapshots include everything observed earlier in the same work directory.

Native runtimes do not all flush on demand, and tuicov does not invent hits when they cannot. It keeps the interval with an availability note and records the complete data when the application exits normally.

Adapter During execution At normal exit
ratatui Continuous LLVM snapshots on supported platforms such as Darwin Complete
Bubble Tea Interval retained with an availability note Complete
Textual Generated launcher saves coverage.py counters on SIGUSR2 where available Complete
Ink Generated preload calls v8.takeCoverage() on SIGUSR2 where available Complete

πŸŽ›οΈ Bring your own command

Put --command last so every remaining argument belongs to the application:

uv run tuicov run ./path/to/app \
  --interval 1s \
  --command node dist/cli.js --demo

For exact argument transport from another program, use JSON:

uv run tuicov run ./path/to/app \
  --command-json '["node","dist/cli.js","--demo"]'

A replacement command must still activate the language's native coverage runtime. The built-in adapter commands do this automatically; custom commands are intentionally your responsibility.

πŸ“¦ What tuicov writes

Generated state stays under the selected work directory, .tuicov/ by default:

.tuicov/
β”œβ”€β”€ manifest.json       detected framework, immutable run plan, widget inventory
β”œβ”€β”€ service.json        active loopback endpoint, when enabled
β”œβ”€β”€ raw/                native profiles and counters
β”œβ”€β”€ generated/          launch hooks and converted profiles
β”œβ”€β”€ snapshots/          normalized cumulative snapshots
β”œβ”€β”€ report.json         machine-readable overall + per-snapshot coverage
└── report.html         standalone human-readable report

The report includes:

  • overall and per-file line totals, missing lines, and hit counts;
  • overall widget totals plus covered and missing stable widget IDs;
  • the same details for every interval, request, and exit snapshot;
  • timestamps, trigger names, completeness, and native-runtime notes.

🧩 Add another adapter

The extension boundary is deliberately small: implement framework detection and return a native run plan; tuicov handles persistence, collection, normalization, and reporting.

πŸ› οΈ Develop and verify

uv sync --locked
uv run python -m unittest discover -s tests -v
uv lock --check

When dependency metadata changes, use uv add --dev PACKAGE and commit both pyproject.toml and uv.lock.

Framework end-to-end tests

Self-terminating fixtures for all four frameworks live under tests/fixtures/e2e/. The harness launches each one in a shell-use headless PTY, verifies the ordered booting β†’ loading β†’ rendering screen flow and process exit, then checks interval, line, and widget reports.

uv run python -m unittest tests.test_e2e_frameworks -v

Run the Textual case with its isolated requirements layered over the locked project:

uv run --locked \
  --with-requirements tests/fixtures/e2e/textual/requirements.txt \
  python -m unittest \
  tests.test_e2e_frameworks.FrameworkEndToEndTests.test_textual_application -v

Missing native toolchains produce actionable skips. GitHub's Framework end-to-end tests workflow installs and runs the complete matrix.

πŸ“„ License

tuicov is available under the MIT License.

πŸ“š Cite this project

If you use tuicov in your research, please cite:

@misc{peng2026llmstestterminaluser,
  title         = {Can LLMs Test Terminal User Interfaces?},
  author        = {Chao Peng and Ruida Hu and Ajitha Rajan and TegawendΓ© F BissyandΓ© and Jacques Klein and Cuiyun Gao},
  year          = {2026},
  eprint        = {2608.03743},
  archivePrefix = {arXiv},
  primaryClass  = {cs.SE},
  url           = {https://arxiv.org/abs/2608.03743},
}

About

Unified line and widget coverage for terminal UIs across ratatui, Bubble Tea, Textual, and Ink.

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages