Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make assert_eq! in Rust show multiline strings

Tags:

rust

I have the following Rust unit test:

    #[test]
    fn test_multiline_strings_are_equal() {
        let expected = "\
one
two
three
four
";
        let actual = "\
one
two
four
";
        assert_eq!(actual, expected);
    }

When it fails, it outputs the following:

---- printer::tests::test_multiline_strings_are_equal stdout ----
thread 'printer::tests::test_multiline_strings_are_equal' panicked at 'assertion failed: `(left == right)`
  left: `"one\ntwo\nfour\n"`,
 right: `"one\ntwo\nthree\nfour\n"`', src\printer.rs:600:9

Can anyone tell me how to make it show "one", "two", "three" and "four" on separate lines, for easier comparison?

like image 322
Huw Walters Avatar asked Sep 06 '25 00:09

Huw Walters


2 Answers

The pretty_assertions library does this. Just add

use pretty_assertions::assert_eq;

and its replacement assert_eq! macro will produce a line-by-line diff; in your example:

Diff < left / right > :
 one
 two
>three
 four

It also works with the Debug output of non-string values:

use pretty_assertions::assert_eq;

#[test]
fn test_struct() {
    #[derive(Debug, PartialEq)]
    struct Foo {
        x: &'static str,
        y: &'static str,
    }

    assert_eq!(
        Foo { x: "x", y: "y" },
        Foo {
            x: "x",
            y: "surprise!",
        }
    );
}
Diff < left / right > :
 Foo {
     x: "x",
<    y: "y",
>    y: "surprise!",
 }
like image 165
Kevin Reid Avatar answered Sep 07 '25 20:09

Kevin Reid


The assert_eq! macro will "print the values of the expressions with their debug representations" if the values are not equal. This uses the Debug format specifier, which for strings will escape newlines and other control characters. So you can't override that without wrapping the strings in some type that makes the Debug implementation use the Display implementation.

An alternative though is the macro allows you to provide your own message using the normal formatting syntax. So you could provide the non-debug output as well:

assert_eq!(actual, expected, "\n expanded left: {actual}\nexpanded right: {expected}\n");
thread 'test_multiline_strings_are_equal' panicked at 'assertion failed: `(left == right)`
  left: `"one\ntwo\nfour\n"`,
 right: `"one\ntwo\nthree\nfour\n"`: 
 expanded left: one
two
four

expanded right: one
two
three
four

', src/lib.rs:14:5

It looks a bit weird since I don't think the macro was really expecting the custom message to have newlines (see the trailing ', src/lib.rs:14:5) but it hopefully it works well enough.

If that's not good enough, it wouldn't be too hard to make your own macro.

like image 22
kmdreko Avatar answered Sep 07 '25 19:09

kmdreko