# testty
[](https://crates.io/crates/testty)
[](https://docs.rs/testty)
[](../../LICENSE)
testty is a framework for end-to-end testing of terminal apps. It launches your real app
and checks what shows up on screen — text, colors, and highlights — with a single Rust
API.
## Installation
```toml
[dev-dependencies]
testty = "0.9"
tempfile = "3"
```
## Capabilities
### Reliable • No flaky tests
- **Auto-wait.** `wait_for_stable_frame` and `eventually` wait for the screen to settle
before asserting, so you never hard-code sleeps.
- **Screen-first assertions.** Check visible text, colors, and highlighted items, with
ready-made helpers for tabs, dialogs, and footers.
- **Full isolation.** Each test runs your real binary in its own workspace, so tests
never bleed into one another.
### Proof you can share
- **Snapshots.** Compare a run against a saved baseline — screen text or pixels.
- **Reports.** Save what each test saw as plain text, a screenshot, an animated GIF, or
a self-contained HTML report.
## Examples
#### Write a test
```rust
use testty::prelude::*;
#[test]
fn tab_switches_view() {
let temp = tempfile::TempDir::new().unwrap();
let builder = PtySessionBuilder::new(env!("CARGO_BIN_EXE_myapp"))
.size(80, 24)
.workdir(temp.path());
let scenario = Scenario::new("tab_switch")
.wait_for_stable_frame(500, 5_000)
.press_key("Tab")
.wait_for_stable_frame(300, 3_000)
.capture();
let frame = scenario.run(builder).expect("scenario failed");
testty::recipe::expect_selected_tab(&frame, "Sessions");
testty::recipe::expect_unselected_tab(&frame, "Projects");
}
```
```sh
cargo test -p my-app --test e2e
```
#### Wait for something to appear
```rust
use std::time::Duration;
use testty::prelude::*;
let scenario = Scenario::new("counter")
.write_text("+++")
.eventually(
Duration::from_secs(5),
Duration::from_millis(50),
|frame| assertion::match_text_in_region(frame, "Counter: 3", &Region::full(80, 24)),
)
.capture();
```
#### Compare against a saved baseline
```rust
use testty::snapshot::{self, SnapshotConfig};
let config = SnapshotConfig::new("tests/baselines", "tests/artifacts");
snapshot::assert_frame_snapshot_matches(&config, "startup", &frame.all_text())
.expect("snapshot should match");
```
#### Save a shareable report
```rust
use std::path::Path;
use testty::prelude::*;
use testty::proof::html::HtmlBackend;
let (_frame, report) = scenario.run_with_proof(builder).expect("failed");
report.save(&HtmlBackend, Path::new("proof.html")).unwrap();
```
## Resources
- [Getting started](docs/getting-started.md) — install, write your first test, run it
- [Scenarios](docs/scenarios.md) — describe a sequence of actions and waits
- [Assertions](docs/assertions.md) — check text, colors, and highlights on screen
- [Snapshots](docs/snapshots.md) — compare a test against a saved baseline
- [Proof pipeline](docs/proof-pipeline.md) — save what a test saw as text, image, GIF,
or HTML
- [Journeys](docs/journeys.md) — reusable building blocks for tests
- [Frame diffing](docs/frame-diffing.md) — see what changed between two screens
- [Examples](docs/examples.md) — runnable example programs
- [Upgrading](docs/upgrading.md) — version migration notes
- [API reference](https://docs.rs/testty) — full generated docs
## License
Apache-2.0. See [LICENSE](../../LICENSE).