📣 `assert_eq!` with colorful diff (drop-in replacement)

:wave: Ok, I need as many volunteers as possible to try this in different terminals and report back which symbols render correctly: :slight_smile:

$ echo "+ > → ❭ ❯ ❱ ▶ ➤"

Please also mention the terminal and any special fonts you are using.


This is because the current fancy arrow glyphs don't render well under OSX (iTerm2 + standard terminal):

2 Likes

xfce4-terminal 0.6.3 with zsh: I can't even paste the unicode characters -- it does a carriage-return for each of them. However, putting your command in a .sh file and running it shows all eight of them on the terminal.

Nice to see that an RFC with similar goals is already in!

Highly naive tentative discussions of these first questions:

  • More user-friendly assertion output should probably the default, unless it bloats the runtime too much with respect to the minimal one. The first goal of an error message is to be as readable as possible in order to make troubleshooting faster.
  • Diffs are most useful when there are few changes and these are close to one another. If the two quantities being compared are completely different (for some definition thereof, to be elaborated), a raw left/right display makes more sense. A nice middle ground is the left/right side by side display, but it probably requires too much horizontal space for the average terminal.
  • At some point, we will always hit the sad truth that text terminals are not good at displaying lots of data, and that GUI-style interactive tree views are better for visualizing deeply nested constructs. I think your format scales better to complex contents than the current automatic Debug format thanks to proper use of punctuation (line feeds, indentation), but it is pretty clear that it will nevertheless consume too much horizontal space on deeply nested types, such as those generated by recursive macros. A separate issue is that of displays with lots of lines (e.g. structs with lots of members, arrays in vertical layout), for which some form of compression of unchanged information (as done by diff) would be desirable.
  • I do not know enough about the requirements of JSON output to comment on that, but I guess that at the very least ANSI color codes should be dropped :slight_smile:

Another question that might be asked concerns the use of color. While an important feature for interactive usability, it also has a number of annoying edge cases:

  • We want to print colored output only during interactive usage. ANSI escape codes in redirected stdout/stderr output are no fun :wink:
  • The most prevalent forms of colorblindness result in an inability to distinguish red and green. At the same time, these colors are consistent with "standard" diff output. This may require more thought.

As for this command...

$ echo "+ > → ❭ ❯ ❱ ▶ ➤"

Every character displays and parses just fine for me on Linux, using Xfce-terminal v0.8.5.1 with the Monospace Regular font and the bash shell (v4.4).

1 Like

Works correctly on

  • Qt: 4.6.2
    KDE: 4.3.4 (KDE 4.3.4)
    Konsole: 2.3.3
    DejaVu sans Mono

  • xterm
    XOrg 6.8.99.903(253)
    Luxi Mono

  • gnome-terminal 2.3.13
    DejaVu sans Mono

Ok, thanks. I switched to / glyphs - fingers crossed. :wink:

UPDATE: ok, it's plain < / > now, because the triangles sometimes overlapped with neighbouring letters...

1 Like

Ha! I see a lot of testing was done already! To add my two cents: all of your candidates, including the ones you picked, render correctly on the phone* that had trouble with the original arrows :tada:

Fairphone 2, Firefox 55.0.2 Android build.

:wave: Hey, I could use some input on which version looks best! :slight_smile:

I am trying to improve the readability of multi-line changes and have to consider. Here are the three candidates I am taking into consideration right now - both on a bright and dark terminal scheme.

  • A - only bold
  • B - black on light colored background
  • C - bold on dark colored background

0 voters

I put my thoughts below each pair of screenshots. You are welcome to add your remarks in a comment.

A - only bold

issue12_A issue12_A_light

  • puts focus on visible characters
  • whitespace characters are not highlighted

B - black on light colored background

issue12_B issue12_B_light

  • I feel there is a stronger focus on whitespace characters than on visible characters

C - bold on dark colored background

issue12_C issue12_C_light

  • I feel there is a balanced focus on both whitespace and visible characters

Want to try it in your terminal?

Here is the bash code to reproduce all three variants at once in your shell:

echo -e "\n\e[1m# A - only bold\e[0m\n\n## removed ##\n    0,\n    0,\n    128,\n## added ##\n    84,\n    248,\n## diff ##\n\e[31m<\e[0m\e[31m    \e[0m\e[1;31m0\e[0m\e[31m,\e[0m\n\e[31m<\e[0m\e[31m    \e[0m\e[1;31m0,\e[0m\n\e[1;31m<\e[0m\e[1;31m    1\e[0m\e[31m2\e[0m\e[31m8,\e[0m\n\e[32m>\e[0m\e[32m    \e[0m\e[1;32m84\e[0m\e[32m,\e[0m\n\e[32m>\e[0m\e[32m    \e[0m\e[32m2\e[0m\e[1;32m4\e[0m\e[32m8,\e[0m\n\n\e[1m# B - black on light colored background\e[0m\n\n## removed ##\n    0,\n    0,\n    128,\n## added ##\n    84,\n    248,\n## diff ##\n\e[31m<\e[0m\e[31m    \e[0m\e[41;30m0\e[0m\e[31m,\e[0m\n\e[31m<\e[0m\e[31m    \e[0m\e[41;30m0,\e[0m\n\e[1;31m<\e[0m\e[41;30m    1\e[0m\e[31m2\e[0m\e[31m8,\e[0m\n\e[32m>\e[0m\e[32m    \e[0m\e[42;30m84\e[0m\e[32m,\e[0m\n\e[32m>\e[0m\e[32m    \e[0m\e[32m2\e[0m\e[42;30m4\e[0m\e[32m8,\e[0m\n\n\e[1m# C - bold on dark colored background\e[0m\n\n## removed ##\n    0,\n    0,\n    128,\n## added ##\n    84,\n    248,\n## diff ##\n\e[31m<\e[0m\e[31m    \e[0m\e[1;48;5;52;31m0\e[0m\e[31m,\e[0m\n\e[31m<\e[0m\e[31m    \e[0m\e[1;48;5;52;31m0,\e[0m\n\e[1;31m<\e[0m\e[1;48;5;52;31m    1\e[0m\e[31m2\e[0m\e[31m8,\e[0m\n\e[32m>\e[0m\e[32m    \e[0m\e[1;48;5;22;32m84\e[0m\e[32m,\e[0m\n\e[32m>\e[0m\e[32m    \e[0m\e[32m2\e[0m\e[1;48;5;22;32m4\e[0m\e[32m8,\e[0m\n"
1 Like

Wondering if these pretty diffs could be added to assertion libraries like @mindsbackyard's galvanic-assert.Then we'd really be starting to close in on the loveliness of unit testing in the scripting world! :heart_eyes:

2 Likes

Basically yes, I've already planned to enhance the error output of assertions in a future version. Though currently there is a lot on my plate and I'm also trying to finish galvanic-test (hopefully this week, the implementation is ready but the documentation is not).

Ideally the output formatter would be pluggable, but I'm not quite sure how to implement this without adding too much overhead.

2 Likes

Just tried it on my project and that should really be built-in! Super helpful.

1 Like

I'm working on a fairly big project where we're often generating or manipulating trees and I found this crate to be a massive productivity boost. Especially when working with things like XML bindings, having the ability to detect which nodes aren't what you expect is super useful.

Imagine trying to detect something like this without pretty-assertions!

9 Likes

:tada: better windows support

With pretty_assertions (v0.6) the terminal state is now modified to properly handle ANSI color codes on Windows. :sun_with_face:

use pretty_assertions::{assert_eq, assert_ne};

let x = /* ... */;
let y = /* ... */;

assert_eq!(x, y);

7 Likes

I like this, but one minor nitpick: Green should be used for left (expected) and red for right (actual).

The colours actually match diff / patch format colours -- red for the first parameter (what was subtracted), and green for the second (what was added), so if you think of it that way, it works :slightly_smiling_face:

3 Likes

So a typo was added by swapping the o and r letters in "World"? :smiley: Perhaps changing that in the sample image would reduce confusion.

1 Like

The diff equals RHS minus LHS, so to say: If you apply the diff on the LHS, you get the RHS. You got that right.

The example code is this.

let x = Some(Foo { lorem: "Hello World!", ipsum: 42, dolor: Ok("hey".to_string())});
let y = Some(Foo { lorem: "Hello Wrold!", ipsum: 42, dolor: Ok("hey ho!".to_string())});

assert_eq!(x, y);

The diff doesn't care if the typo is in LHS or RHS. My personal style is assert_eq!(expected, actual). What's yours? Do you put the expected value left or right? Is there a common rust way to place this?

But even if you reverse the order, the typo could have been in the expected value too. So ... I guess I'll keep the screenshot as is and leave the interpretation to the audience. :smile:

I don't speak for everyone, but it might be easy to generalize that we think of red meaning "bad" (or stop), and green meaning "good" (or go).

Visually, it is jarring to see the expectation in red, indicating that is the "wrong" result, even though it is expected. I suppose this is easy to correct by swapping the expected/actual order in the assertion itself. I think that clears it up. :slight_smile:

2 Likes

I usually use assert(result, expected) so the colours would be 'wrong' for me. Perhaps you could use different colours than green and red to avoid such confusion.

Thanks.

I don't think in terms of right or wrong, but expected and unexpected. My guiding principle is to stay consistent with existing conventions, like command-line diff. As azriel91 pointed out

As long as preferences are different, this de-facto standard colour scheme makes most sense to me.

However I am open to PRs introducing different colour schemes behind either feature flags or macros, etc. :slight_smile:

3 Likes