Skip to content

Commit

Permalink
Add assert_str_eq macro for comparing "raw" strings
Browse files Browse the repository at this point in the history
As discussed in #24, pretty_assertion's `assert_eq` will escape line
breaks in multi-line strings, making diffs for them much harder to
read.

This commit introduces another variant, `assert_str_eq`, and the
associated `StrComparison`, which compares the raw strings, where
the newlines are not escaped.

Fixes #24
  • Loading branch information
x3ro committed Jan 31, 2022
1 parent 88cd1be commit 55074f0
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 0 deletions.
64 changes: 64 additions & 0 deletions pretty_assertions/src/lib.rs
Expand Up @@ -141,6 +141,43 @@ where
}
}

/// A comparison of two strings.
///
/// In contrast to [`Comparison`], which uses the [`core::fmt::Debug`] representaiton,
/// this will print newlines unescaped, resulting in multi-line output for multiline strings.
///
/// ```
/// use pretty_assertions::StrComparison;
///
/// print!("{}", StrComparison::new("foo\nbar", "foo\nbaz"));
/// ```
///
/// The values may have different types, although in practice they are usually the same.
pub struct StrComparison<'a>
{
left: &'a str,
right: &'a str,
}

impl<'a> StrComparison<'a>
{
/// Store two values to be compared in future.
///
/// Expensive diffing is deferred until calling `Debug::fmt`.
pub fn new(left: &'a str, right: &'a str) -> StrComparison<'a> {
StrComparison { left: left, right: right }
}
}

impl<'a> Display for StrComparison<'a>
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// And then diff the debug output
printer::write_header(f)?;
printer::write_lines(f, self.left, self.right)
}
}

/// Asserts that two expressions are equal to each other (using [`PartialEq`]).
///
/// On panic, this macro will print a diff derived from [`Debug`] representation of
Expand Down Expand Up @@ -186,6 +223,33 @@ macro_rules! assert_eq {
});
}

/// TODO
#[macro_export]
macro_rules! assert_str_eq {
($left:expr, $right:expr$(,)?) => ({
$crate::assert_str_eq!(@ $left, $right, "", "");
});
($left:expr, $right:expr, $($arg:tt)*) => ({
$crate::assert_str_eq!(@ $left, $right, ": ", $($arg)+);
});
(@ $left:expr, $right:expr, $maybe_semicolon:expr, $($arg:tt)*) => ({
match (&($left), &($right)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
::core::panic!("assertion failed: `(left == right)`{}{}\
\n\
\n{}\
\n",
$maybe_semicolon,
format_args!($($arg)*),
$crate::StrComparison::new(left_val, right_val)
)
}
}
}
});
}

/// Asserts that two expressions are not equal to each other (using [`PartialEq`]).
///
/// On panic, this macro will print the values of the expressions with their
Expand Down
40 changes: 40 additions & 0 deletions pretty_assertions/tests/macros.rs
Expand Up @@ -4,6 +4,46 @@
#[cfg(feature = "alloc")]
extern crate alloc;

#[allow(clippy::eq_op)]
mod assert_str_eq {
#[cfg(feature = "alloc")]
use ::alloc::string::{String, ToString};
#[cfg(feature = "std")]
use ::std::string::{String, ToString};

#[test]
fn passes_str() {
let a = "some value";
::pretty_assertions::assert_str_eq!(a, a);
}

#[test]
fn passes_string() {
let a: String = "some value".to_string();
::pretty_assertions::assert_str_eq!(a, a);
}

#[test]
fn passes_comparable_types() {
let s0: &'static str = "foo";
let s1: String = "foo".to_string();
::pretty_assertions::assert_str_eq!(s0, s1);
}

#[test]
#[should_panic(expected = r#"assertion failed: `(left == right)`
Diff < left / right > :
foo
<bar
>baz
"#)]
fn fails_foo() {
::pretty_assertions::assert_str_eq!("foo\nbar", "foo\nbaz");
}
}

#[allow(clippy::eq_op)]
mod assert_eq {
#[cfg(feature = "alloc")]
Expand Down

0 comments on commit 55074f0

Please sign in to comment.