[go: up one dir, main page]

insta/
lib.rs

1#![warn(clippy::doc_markdown)]
2#![warn(rustdoc::all)]
3
4//! <div align="center">
5//!  <img src="https://github.com/mitsuhiko/insta/blob/master/assets/logo.png?raw=true" width="250" height="250">
6//!  <p><strong>insta: a snapshot testing library for Rust</strong></p>
7//! </div>
8//!
9//! # What are snapshot tests
10//!
11//! Snapshots tests (also sometimes called approval tests) are tests that
12//! assert values against a reference value (the snapshot).  This is similar
13//! to how [`assert_eq!`] lets you compare a value against a reference value but
14//! unlike simple string assertions, snapshot tests let you test against complex
15//! values and come with comprehensive tools to review changes.
16//!
17//! Snapshot tests are particularly useful if your reference values are very
18//! large or change often.
19//!
20//! # What it looks like:
21//!
22//! ```no_run
23//! #[test]
24//! fn test_hello_world() {
25//!     insta::assert_debug_snapshot!(vec![1, 2, 3]);
26//! }
27//! ```
28//!
29//! Where are the snapshots stored?  Right next to your test in a folder
30//! called `snapshots` as individual [`.snap` files](https://insta.rs/docs/snapshot-files/).
31//!
32//! Got curious?
33//!
34//! * [Read the introduction](https://insta.rs/docs/quickstart/)
35//! * [Read the main documentation](https://insta.rs/docs/) which does not just
36//!   cover the API of the crate but also many of the details of how it works.
37//! * There is a screencast that shows the entire workflow: [watch the insta
38//!   introduction screencast](https://www.youtube.com/watch?v=rCHrMqE4JOY&feature=youtu.be).
39//!
40//! # Writing Tests
41//!
42//! ```
43//! use insta::assert_debug_snapshot;
44//!
45//! # #[allow(clippy::test_attr_in_doctest)]
46//! #[test]
47//! fn test_snapshots() {
48//!     assert_debug_snapshot!(vec![1, 2, 3]);
49//! }
50//! ```
51//!
52//! The recommended flow is to run the tests once, have them fail and check
53//! if the result is okay.
54//! By default, the new snapshots are stored next
55//! to the old ones with the extra `.new` extension.  Once you are satisfied
56//! move the new files over.  To simplify this workflow you can use
57//! `cargo insta review` (requires
58//! [`cargo-insta`](https://crates.io/crates/cargo-insta)) which will let you
59//! interactively review them:
60//!
61//! ```text
62//! $ cargo test
63//! $ cargo insta review
64//! ```
65//!
66//! # Use Without `cargo-insta`
67//!
68//! Note that `cargo-insta` is entirely optional.  You can also just use insta
69//! directly from `cargo test` and control it via the `INSTA_UPDATE` environment
70//! variable — see [Updating snapshots](#updating-snapshots) for details.
71//!
72//! You can for instance first run the tests and not write any new snapshots, and
73//! if you like them run the tests again and update them:
74//!
75//! ```text
76//! INSTA_UPDATE=no cargo test
77//! INSTA_UPDATE=always cargo test
78//! ```
79//!
80//! # Assertion Macros
81//!
82//! This crate exports multiple macros for snapshot testing:
83//!
84//! - [`assert_snapshot!`] for comparing basic snapshots of
85//!   [`Display`](std::fmt::Display) outputs, often strings.
86//! - [`assert_debug_snapshot!`] for comparing [`Debug`] outputs of values.
87//!
88//! The following macros require the use of [`serde::Serialize`]:
89//!
90#![cfg_attr(
91    feature = "csv",
92    doc = "- [`assert_csv_snapshot!`] for comparing CSV serialized output. (requires the `csv` feature)"
93)]
94#![cfg_attr(
95    feature = "toml",
96    doc = "- [`assert_toml_snapshot!`] for comparing TOML serialized output. (requires the `toml` feature)"
97)]
98#![cfg_attr(
99    feature = "yaml",
100    doc = "- [`assert_yaml_snapshot!`] for comparing YAML serialized output. (requires the `yaml` feature)"
101)]
102#![cfg_attr(
103    feature = "ron",
104    doc = "- [`assert_ron_snapshot!`] for comparing RON serialized output. (requires the `ron` feature)"
105)]
106#![cfg_attr(
107    feature = "json",
108    doc = "- [`assert_json_snapshot!`] for comparing JSON serialized output. (requires the `json` feature)"
109)]
110#![cfg_attr(
111    feature = "json",
112    doc = "- [`assert_compact_json_snapshot!`] for comparing JSON serialized output while preferring single-line formatting. (requires the `json` feature)"
113)]
114//!
115//! For macros that work with [`serde`] this crate also permits redacting of
116//! partial values.  See [redactions in the
117//! documentation](https://insta.rs/docs/redactions/) for more information.
118//!
119//! # Updating snapshots
120//!
121//! During test runs snapshots will be updated according to the `INSTA_UPDATE`
122//! environment variable.  The default is `auto` which will write snapshots for
123//! any failing tests into `.snap.new` files (if no CI is detected) so that
124//! [`cargo-insta`](https://crates.io/crates/cargo-insta) can pick them up for
125//! review. Normally you don't have to change this variable.
126//!
127//! `INSTA_UPDATE` modes:
128//!
129//! - `auto`: the default. `no` for CI environments or `new` otherwise
130//! - `new`: writes snapshots for any failing tests into `.snap.new` files,
131//!   pending review
132//! - `always`: writes snapshots for any failing tests into `.snap` files,
133//!   bypassing review
134//! - `unseen`: `always` for previously unseen snapshots or `new` for existing
135//!   snapshots
136//! - `no`: does not write to snapshot files at all; just runs tests
137//! - `force`: forcibly updates snapshot files, even if assertions pass
138//!
139//! When `new`, `auto` or `unseen` is used, the
140//! [`cargo-insta`](https://crates.io/crates/cargo-insta) command can be used to
141//! review the snapshots conveniently:
142//!
143//! ```text
144//! $ cargo insta review
145//! ```
146//!
147//! "enter" or "a" accepts a new snapshot, "escape" or "r" rejects, "space" or
148//! "s" skips the snapshot for now.
149//!
150//! For more information [read the cargo insta
151//! docs](https://insta.rs/docs/cli/).
152//!
153//! # Inline Snapshots
154//!
155//! Additionally snapshots can also be stored inline.  In that case the format
156//! for the snapshot macros is `assert_snapshot!(reference_value, @"snapshot")`.
157//! The leading at sign (`@`) indicates that the following string is the
158//! reference value.  On review, `cargo-insta` will update the string with the
159//! new value.
160//!
161//! Example:
162//!
163//! ```no_run
164//! # use insta::assert_snapshot;
165//! assert_snapshot!(2 + 2, @"");
166//! ```
167//!
168//! Like with normal snapshots, an initial test failure will write the proposed
169//! value into a draft file (note that inline snapshots use `.pending-snap`
170//! files rather than `.snap.new` files). Running `cargo insta review` will
171//! review the proposed changes and update the source files on acceptance
172//! automatically.
173//!
174//! # Features
175//!
176//! The following features exist:
177//!
178//! * `csv`: enables CSV support (via [`serde`])
179//! * `json`: enables JSON support (via [`serde`])
180//! * `ron`: enables RON support (via [`serde`])
181//! * `toml`: enables TOML support (via [`serde`])
182//! * `yaml`: enables YAML support (via [`serde`])
183//! * `redactions`: enables support for redactions
184//! * `filters`: enables support for filters
185//! * `glob`: enables support for globbing ([`glob!`])
186//! * `colors`: enables color output (enabled by default)
187//!
188//! For legacy reasons the `json` and `yaml` features are enabled by default in
189//! limited capacity.  You will receive a deprecation warning if you are not
190//! opting into them but for now the macros will continue to function.
191//!
192//! Enabling any of the [`serde`] based formats enables the hidden `serde` feature
193//! which gates some [`serde`] specific APIs such as [`Settings::set_info`].
194//!
195//! # Dependencies
196//!
197//! [`insta`] tries to be light in dependencies but this is tricky to accomplish
198//! given what it tries to do.
199//! By default, it currently depends on [`serde`] for
200//! the [`assert_toml_snapshot!`] and [`assert_yaml_snapshot!`] macros.  In the
201//! future this default dependencies will be removed.  To already benefit from
202//! this optimization you can disable the default features and manually opt into
203//! what you want.
204//!
205//! # Settings
206//!
207//! There are some settings that can be changed on a per-thread (and thus
208//! per-test) basis.  For more information see [Settings].
209//!
210//! Additionally, Insta will load a YAML config file with settings that change
211//! the behavior of insta between runs.  It's loaded from any of the following
212//! locations: `.config/insta.yaml`, `insta.yaml` and `.insta.yaml` from the
213//! workspace root.  The following config options exist:
214//!
215//! ```yaml
216//! behavior:
217//!   # also set by INSTA_REQUIRE_FULL_MATCH
218//!   require_full_match: true/false
219//!   # also set by INSTA_FORCE_PASS
220//!   force_pass: true/false
221//!   # also set by INSTA_OUTPUT
222//!   output: "diff" | "summary" | "minimal" | "none"
223//!   # also set by INSTA_UPDATE
224//!   update: "auto" | "new" | "always" | "no" | "unseen" | "force"
225//!   # also set by INSTA_GLOB_FAIL_FAST
226//!   glob_fail_fast: true/false
227//!
228//! # these are used by cargo insta test
229//! test:
230//!   # also set by INSTA_TEST_RUNNER
231//!   # cargo-nextest binary path can be explicitly set by INSTA_CARGO_NEXTEST_BIN
232//!   runner: "auto" | "cargo-test" | "nextest"
233//!   # whether to fallback to `cargo-test` if `nextest` is not available,
234//!   # also set by INSTA_TEST_RUNNER_FALLBACK, default false
235//!   test_runner_fallback: true/false
236//!   # automatically assume --review was passed to cargo insta test
237//!   auto_review: true/false
238//!   # automatically assume --accept-unseen was passed to cargo insta test
239//!   auto_accept_unseen: true/false
240//!
241//! # these are used by cargo insta review
242//! review:
243//!   # also look for snapshots in ignored folders
244//!   include_ignored: true / false
245//!   # also look for snapshots in hidden folders
246//!   include_hidden: true / false
247//!   # show a warning if undiscovered (ignored or hidden) snapshots are found.
248//!   # defaults to true but creates a performance hit.
249//!   warn_undiscovered: true / false
250//! ```
251//!
252//! # Optional: Faster Runs
253//!
254//! Insta benefits from being compiled in release mode, even as dev dependency.
255//! It will compile slightly slower once, but use less memory, have faster diffs
256//! and just generally be more fun to use.  To achieve that, opt [`insta`] and
257//! [`similar`] (the diffing library) into higher optimization in your
258//! `Cargo.toml`:
259//!
260//! ```yaml
261//! [profile.dev.package.insta]
262//! opt-level = 3
263//!
264//! [profile.dev.package.similar]
265//! opt-level = 3
266//! ```
267//!
268//! You can also disable the default features of [`insta`] which will cut down on
269//! the compile time a bit by removing some quality of life features.
270//!
271//!  [`insta`]: https://docs.rs/insta
272#![cfg_attr(docsrs, feature(doc_cfg))]
273
274#[macro_use]
275mod macros;
276mod content;
277mod env;
278mod output;
279mod runtime;
280#[cfg(feature = "serde")]
281mod serialization;
282mod settings;
283mod snapshot;
284mod utils;
285
286#[cfg(feature = "redactions")]
287mod redaction;
288
289#[cfg(feature = "filters")]
290mod filters;
291
292#[cfg(feature = "glob")]
293mod glob;
294
295#[cfg(test)]
296mod test;
297
298pub use crate::settings::Settings;
299pub use crate::snapshot::{MetaData, Snapshot, TextSnapshotKind};
300
301/// Exposes some library internals.
302///
303/// You're unlikely to want to work with these objects but they
304/// are exposed for documentation primarily.
305///
306/// This module does not follow the same stability guarantees as the rest of the crate and is not
307/// guaranteed to be compatible between minor versions.
308pub mod internals {
309    pub use crate::content::Content;
310    #[cfg(feature = "filters")]
311    pub use crate::filters::Filters;
312    pub use crate::runtime::AutoName;
313    pub use crate::settings::SettingsBindDropGuard;
314    pub use crate::snapshot::{MetaData, SnapshotContents};
315    #[cfg(feature = "redactions")]
316    pub use crate::{
317        redaction::{ContentPath, Redaction},
318        settings::Redactions,
319    };
320}
321
322// exported for cargo-insta only
323#[doc(hidden)]
324#[cfg(feature = "_cargo_insta_internal")]
325pub mod _cargo_insta_support {
326    pub use crate::{
327        content::Error as ContentError,
328        env::{
329            Error as ToolConfigError, OutputBehavior, SnapshotUpdate, TestRunner, ToolConfig,
330            UnreferencedSnapshots,
331        },
332        output::SnapshotPrinter,
333        snapshot::PendingInlineSnapshot,
334        snapshot::SnapshotContents,
335        snapshot::TextSnapshotContents,
336        utils::get_cargo,
337        utils::is_ci,
338    };
339}
340
341// useful for redactions
342#[cfg(feature = "redactions")]
343pub use crate::redaction::{dynamic_redaction, rounded_redaction, sorted_redaction};
344
345// these are here to make the macros work
346#[doc(hidden)]
347pub mod _macro_support {
348    pub use crate::content::Content;
349    pub use crate::env::{get_cargo_workspace, Workspace};
350    pub use crate::runtime::{
351        assert_snapshot, with_allow_duplicates, AutoName, BinarySnapshotValue, InlineValue,
352        SnapshotValue,
353    };
354    pub use core::{file, line, module_path};
355    pub use std::{any, env, format, option_env, path, vec};
356
357    #[cfg(feature = "serde")]
358    pub use crate::serialization::{serialize_value, SerializationFormat, SnapshotLocation};
359
360    #[cfg(feature = "glob")]
361    pub use crate::glob::glob_exec;
362
363    #[cfg(feature = "redactions")]
364    pub use crate::{
365        redaction::Redaction, redaction::Selector, serialization::serialize_value_redacted,
366    };
367}