1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
//! ## Snapshot testing for a herd of CLI tests
//!
//! `trycmd` is a test harness that will enumerate test case files and run them to verify the
//! results, taking inspiration from
//! [trybuild](https://crates.io/crates/trybuild) and [cram](https://bitheap.org/cram/).
//!
//! Which tool is right:
//! - Hand-written test cases: for peculiar circumstances
//! - [assert_cmd](https://crates.io/crates/assert_cmd): Test cases follow a certain pattern but
//! special attention is needed in how to verify the results.
//! - `trycmd`: For running a lot of blunt tests (limited test predicates)
//! - Particular attention is given to allow the test data to be pulled into documentation, like
//! with [mdbook](https://rust-lang.github.io/mdBook/)
//! - [cram](https://bitheap.org/cram/): For cases agnostic of any programming language
//!
//! ### Getting Started
//!
//! To create a minimal setup, create a `tests/cli_tests.rs` with
//! ```rust,no_run
//! #[test]
//! fn cli_tests() {
//! trycmd::TestCases::new()
//! .case("tests/cmd/*.trycmd");
//! }
//! ```
//!
//! The test can be run with `cargo test`. This will enumerate all `.trycmd` files and run
//! them as test cases, failing if they do not pass.
//!
//! To temporarily override the results, you can do:
//! ```rust,no_run
//! #[test]
//! fn cli_tests() {
//! trycmd::TestCases::new()
//! .case("tests/cmd/*.trycmd")
//! // See Issue #314
//! .fail("tests/cmd/buggy-case.trycmd");
//! }
//! ```
//!
//! ### File Formats
//!
//! Say you have `tests/cmd/help.trycmd` (or `help.toml`), `trycmd` will look for:
//! - `tests/cmd/help.stdin`
//! - `tests/cmd/help.stdout`
//! - `tests/cmd/help.stderr`
//!
//! #### `*.trycmd`
//!
//! A `trycmd` file is just a command with arguments, with the arguments split with [shlex](https://crates.io/crates/shlex).
//!
//! The command is interpreted as `bin.name` in a `toml` file.
//!
//! #### `*.toml`
//!
//! As an alternative to `.trycmd`, he `toml` files give you a lot more control over how your command runs.
//!
//! [schema](https://github.com/assert-rs/trycmd/blob/main/schema.json):
//! - `bin.name`: The name of the binary target from `Cargo.toml` to be used to find the file path
//!
//! #### `*.stdin`
//!
//! Data to pass to `stdin`.
//! - If not present, nothing will be written to `stdin`
//! - If `binary = false` in `*.toml` (the default), newlines will be normalized.
//!
//! #### `*.stdout` and `*.stderr`
//!
//! Expected results for `stdout` or `stderr`.
//! - If not present, we'll not verify the output
//! - If `binary = false` in `*.toml` (the default), newlines will be normalized before comparing
//!
//! ### Workflow
//!
//! To generate snapshots, run
//! ```bash
//! $ TRYCMD=dump cargo test --test cli_tests
//! ```
//! This will write all of the `.stdout` and `.stderr` files in a `dump/` directory.
//!
//! You can then copy over to `tests/cmd` the cases you want to test
//!
//! To update snapshots, run
//! ```bash
//! $ TRYCMD=overwrite cargo test --test cli_tests
//! ```
//! This will overwrite any existing `.stdout` and `.stderr` file in `tests/cmd`
//!
//! When iterating on a test, you can run:
//! ```bash
//! cargo test --test cli_tests -- cli_tests trycmd=name1 trycmd=name2...
//! ```
//! To filter the tests to those with `name1`, `name2`, etc in their file names.
mod cargo;
mod cases;
mod color;
mod command;
mod runner;
pub mod schema;
mod spec;
pub use cases::TestCases;
pub(crate) use cargo::cargo_bin;
pub(crate) use color::Palette;
pub(crate) use command::wait_with_input_output;
pub(crate) use runner::{Case, Mode, Runner};
pub(crate) use schema::{Bin, CommandStatus, Env, TryCmd};
pub(crate) use spec::RunnerSpec;