Skip to content

feat(assert): Add assert_data_eq! #321

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions crates/snapbox/src/assert/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ impl Assert {
}

let checks: Vec<_> =
crate::path::PathDiff::subset_eq_iter_inner(expected_root, actual_root).collect();
crate::dir::PathDiff::subset_eq_iter_inner(expected_root, actual_root).collect();
self.verify(checks);
}

Expand Down Expand Up @@ -319,7 +319,7 @@ impl Assert {
Action::Ignore | Action::Verify | Action::Overwrite => {}
}

let checks: Vec<_> = crate::path::PathDiff::subset_matches_iter_inner(
let checks: Vec<_> = crate::dir::PathDiff::subset_matches_iter_inner(
expected_root,
actual_root,
&self.substitutions,
Expand All @@ -332,7 +332,7 @@ impl Assert {
#[track_caller]
fn verify(
&self,
mut checks: Vec<Result<(std::path::PathBuf, std::path::PathBuf), crate::path::PathDiff>>,
mut checks: Vec<Result<(std::path::PathBuf, std::path::PathBuf), crate::dir::PathDiff>>,
) {
if checks.iter().all(Result::is_ok) {
for check in checks {
Expand Down
4 changes: 2 additions & 2 deletions crates/snapbox/src/data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use filters::FilterSet;
///
/// let actual = some_function();
/// let expected = snapbox::str![["5"]];
/// snapbox::assert_eq(actual.to_debug(), expected);
/// snapbox::assert_data_eq!(actual.to_debug(), expected);
/// ```
pub trait ToDebug {
fn to_debug(&self) -> Data;
Expand All @@ -64,7 +64,7 @@ impl<D: std::fmt::Debug> ToDebug for D {
///
/// let actual = some_function();
/// let expected = snapbox::str![["5"]];
/// snapbox::assert_eq(actual.into_json(), expected);
/// snapbox::assert_data_eq!(actual.into_json(), expected);
/// ```
#[cfg(feature = "json")]
pub trait IntoJson {
Expand Down
20 changes: 10 additions & 10 deletions crates/snapbox/src/data/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,41 +372,41 @@ impl PathRuntime {
#[cfg(test)]
mod tests {
use super::*;
use crate::assert_eq;
use crate::assert_data_eq;
use crate::prelude::*;
use crate::str;

#[test]
fn test_format_patch() {
let patch = format_patch(None, "hello\nworld\n");

assert_eq(
assert_data_eq!(
patch,
str![[r##"
[r#"
hello
world
"#]"##]],
patch,
);

let patch = format_patch(None, r"hello\tworld");
assert_eq(str![[r##"[r#"hello\tworld"#]"##]], patch);
assert_data_eq!(patch, str![[r##"[r#"hello\tworld"#]"##]].raw());

let patch = format_patch(None, "{\"foo\": 42}");
assert_eq(str![[r##"[r#"{"foo": 42}"#]"##]], patch);
assert_data_eq!(patch, str![[r##"[r#"{"foo": 42}"#]"##]]);

let patch = format_patch(Some(0), "hello\nworld\n");
assert_eq(
assert_data_eq!(
patch,
str![[r##"
[r#"
hello
world
"#]"##]],
patch,
);

let patch = format_patch(Some(4), "single line");
assert_eq(str![[r#""single line""#]], patch);
assert_data_eq!(patch, str![[r#""single line""#]]);
}

#[test]
Expand All @@ -415,7 +415,8 @@ mod tests {
patchwork.patch(4..7, "zwei");
patchwork.patch(0..3, "один");
patchwork.patch(8..13, "3");
assert_eq(
assert_data_eq!(
patchwork.to_debug(),
str![[r#"
Patchwork {
text: "один zwei 3",
Expand All @@ -435,7 +436,6 @@ mod tests {
],
}
"#]],
patchwork.to_debug(),
);
}

Expand Down
24 changes: 12 additions & 12 deletions crates/snapbox/src/filter/redactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ impl Redactions {
}

pub(crate) fn with_exe() -> Self {
let mut substitutions = Self::new();
substitutions
let mut redactions = Self::new();
redactions
.insert("[EXE]", std::env::consts::EXE_SUFFIX)
.unwrap();
substitutions
redactions
}

/// Insert an additional match pattern
Expand Down Expand Up @@ -172,7 +172,7 @@ fn validate_placeholder(placeholder: &'static str) -> crate::assert::Result<&'st
Ok(placeholder)
}

fn normalize(input: &str, pattern: &str, substitutions: &Redactions) -> String {
fn normalize(input: &str, pattern: &str, redactions: &Redactions) -> String {
if input == pattern {
return input.to_owned();
}
Expand All @@ -191,7 +191,7 @@ fn normalize(input: &str, pattern: &str, substitutions: &Redactions) -> String {
input_lines[input_index..]
.iter()
.copied()
.map(|s| substitutions.substitute(s)),
.map(|s| redactions.substitute(s)),
);
break 'outer;
};
Expand All @@ -204,7 +204,7 @@ fn normalize(input: &str, pattern: &str, substitutions: &Redactions) -> String {
};
let next_input_index = input_index + 1;

if line_matches(input_line, pattern_line, substitutions) {
if line_matches(input_line, pattern_line, redactions) {
pattern_index = next_pattern_index;
input_index = next_input_index;
normalized.push(Cow::Borrowed(pattern_line));
Expand Down Expand Up @@ -232,7 +232,7 @@ fn normalize(input: &str, pattern: &str, substitutions: &Redactions) -> String {
input_lines[input_index..]
.iter()
.copied()
.map(|s| substitutions.substitute(s)),
.map(|s| redactions.substitute(s)),
);
break 'outer;
}
Expand All @@ -250,7 +250,7 @@ fn normalize(input: &str, pattern: &str, substitutions: &Redactions) -> String {
input_lines[input_index..future_input_index]
.iter()
.copied()
.map(|s| substitutions.substitute(s)),
.map(|s| redactions.substitute(s)),
);
pattern_index = future_pattern_index;
input_index = future_input_index;
Expand All @@ -262,7 +262,7 @@ fn normalize(input: &str, pattern: &str, substitutions: &Redactions) -> String {
input_lines[input_index..]
.iter()
.copied()
.map(|s| substitutions.substitute(s)),
.map(|s| redactions.substitute(s)),
);
break 'outer;
}
Expand All @@ -275,15 +275,15 @@ fn is_line_elide(line: &str) -> bool {
line == "...\n" || line == "..."
}

fn line_matches(line: &str, pattern: &str, substitutions: &Redactions) -> bool {
fn line_matches(line: &str, pattern: &str, redactions: &Redactions) -> bool {
if line == pattern {
return true;
}

let subbed = substitutions.substitute(line);
let subbed = redactions.substitute(line);
let mut line = subbed.as_ref();

let pattern = substitutions.clear(pattern);
let pattern = redactions.clear(pattern);

let mut sections = pattern.split("[..]").peekable();
while let Some(section) = sections.next() {
Expand Down
14 changes: 10 additions & 4 deletions crates/snapbox/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//! ## Which tool is right
//!
//! - [cram](https://bitheap.org/cram/): End-to-end CLI snapshotting agnostic of any programming language
//! - See also [scrut](https://github.com/facebookincubator/scrut)
//! - [trycmd](https://crates.io/crates/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/)
Expand All @@ -25,7 +26,7 @@
//! ## Getting Started
//!
//! Testing Functions:
//! - [`assert_eq`][crate::assert_eq()] and [`assert_matches`] for reusing diffing / pattern matching for non-snapshot testing
//! - [`assert_data_eq!`] for quick and dirty snapshotting
//! - [`harness::Harness`] for discovering test inputs and asserting against snapshot files:
//!
//! Testing Commands:
Expand All @@ -44,17 +45,17 @@
//!
//! # Examples
//!
//! [`assert_matches`]
//! [`assert_data_eq!`]
//! ```rust
//! snapbox::assert_matches("Hello [..] people!", "Hello many people!");
//! snapbox::assert_data_eq!("Hello many people!", "Hello [..] people!");
//! ```
//!
//! [`Assert`]
//! ```rust,no_run
//! let actual = "...";
//! snapbox::Assert::new()
//! .action_env("SNAPSHOTS")
//! .matches(snapbox::file!["help_output_is_clean.txt"], actual);
//! .eq_(actual, snapbox::file!["help_output_is_clean.txt"]);
//! ```
//!
//! [`harness::Harness`]
Expand Down Expand Up @@ -160,6 +161,10 @@ pub mod prelude {
/// assert_eq(file!["output.txt"], actual);
/// ```
#[track_caller]
#[deprecated(
since = "0.5.11",
note = "Replaced with `assert_data_eq!(actual, expected.raw())`"
)]
pub fn assert_eq(expected: impl Into<crate::Data>, actual: impl Into<crate::Data>) {
Assert::new()
.action_env(assert::DEFAULT_ACTION_ENV)
Expand Down Expand Up @@ -192,6 +197,7 @@ pub fn assert_eq(expected: impl Into<crate::Data>, actual: impl Into<crate::Data
/// assert_matches(file!["output.txt"], actual);
/// ```
#[track_caller]
#[deprecated(since = "0.5.11", note = "Replaced with `assert_data_eq!(actual)`")]
pub fn assert_matches(pattern: impl Into<crate::Data>, actual: impl Into<crate::Data>) {
Assert::new()
.action_env(assert::DEFAULT_ACTION_ENV)
Expand Down
47 changes: 47 additions & 0 deletions crates/snapbox/src/macros.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,50 @@
/// Check if a value is the same as an expected value
///
/// By default [`filters`][crate::filter] are applied, including:
/// - `...` is a line-wildcard when on a line by itself
/// - `[..]` is a character-wildcard when inside a line
/// - `[EXE]` matches `.exe` on Windows
/// - `\` to `/`
/// - Newlines
///
/// To limit this to newline normalization for text, call [`Data::raw`][crate::Data] on `expected`.
///
/// # Effective signature
///
/// ```rust
/// # use snapbox::IntoData;
/// fn assert_data_eq(actual: impl IntoData, expected: impl IntoData) {
/// // ...
/// }
/// ```
///
/// # Examples
///
/// ```rust
/// # use snapbox::assert_data_eq;
/// let output = "something";
/// let expected = "so[..]g";
/// assert_data_eq!(output, expected);
/// ```
///
/// Can combine this with [`file!`]
/// ```rust,no_run
/// # use snapbox::assert_data_eq;
/// # use snapbox::file;
/// let actual = "something";
/// assert_data_eq!(actual, file!["output.txt"]);
/// ```
#[macro_export]
macro_rules! assert_data_eq {
($actual: expr, $expected: expr $(,)?) => {{
let actual = $crate::IntoData::into_data($actual);
let expected = $crate::IntoData::into_data($expected);
$crate::Assert::new()
.action_env($crate::assert::DEFAULT_ACTION_ENV)
.eq_(actual, expected);
}};
}

/// Find the directory for your source file
#[doc(hidden)] // forced to be visible in intended location
#[macro_export]
Expand Down
22 changes: 11 additions & 11 deletions crates/snapbox/tests/testsuite/assert.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
use snapbox::assert_eq;
use snapbox::assert_data_eq;
use snapbox::file;
use snapbox::str;

#[test]
fn test_trivial_assert() {
assert_eq(str!["5"], "5");
assert_data_eq!("5", str!["5"]);
}

#[test]
fn smoke_test_indent() {
assert_eq(
assert_data_eq!(
"\
line1
line2
",
str![[r#"
line1
line2
"#]]
.indent(true),
);

assert_data_eq!(
"\
line1
line2
",
);

assert_eq(
str![[r#"
line1
line2
"#]]
.indent(false),
"\
line1
line2
",
);
}

#[test]
fn test_expect_file() {
assert_eq(file!["../../README.md"], include_str!("../../README.md"))
assert_data_eq!(include_str!("../../README.md"), file!["../../README.md"]);
}
Loading