1 //! # Pretty Assertions
3 //! When writing tests in Rust, you'll probably use `assert_eq!(a, b)` _a lot_.
5 //! If such a test fails, it will present all the details of `a` and `b`.
6 //! But you have to spot the differences yourself, which is not always straightforward,
9 //! ![standard assertion](https://raw.githubusercontent.com/colin-kiegel/rust-pretty-assertions/2d2357ff56d22c51a86b2f1cfe6efcee9f5a8081/examples/standard_assertion.png)
11 //! Wouldn't that task be _much_ easier with a colorful diff?
13 //! ![pretty assertion](https://raw.githubusercontent.com/colin-kiegel/rust-pretty-assertions/2d2357ff56d22c51a86b2f1cfe6efcee9f5a8081/examples/pretty_assertion.png)
15 //! Yep — and you only need **one line of code** to make it happen:
18 //! use pretty_assertions::{assert_eq, assert_ne};
22 //! <summary>Show the example behind the screenshots above.</summary>
24 //! ```rust,should_panic
25 //! // 1. add the `pretty_assertions` dependency to `Cargo.toml`.
26 //! // 2. insert this line at the top of each module, as needed
27 //! use pretty_assertions::{assert_eq, assert_ne};
29 //! #[derive(Debug, PartialEq)]
31 //! lorem: &'static str,
33 //! dolor: Result<String, String>,
36 //! let x = Some(Foo { lorem: "Hello World!", ipsum: 42, dolor: Ok("hey".to_string())});
37 //! let y = Some(Foo { lorem: "Hello Wrold!", ipsum: 42, dolor: Ok("hey ho!".to_string())});
45 //! Specify it as [`[dev-dependencies]`](http://doc.crates.io/specifying-dependencies.html#development-dependencies)
46 //! and it will only be used for compiling tests, examples, and benchmarks.
47 //! This way the compile time of `cargo build` won't be affected!
49 //! Also add `#[cfg(test)]` to your `use` statements, like this:
53 //! use pretty_assertions::{assert_eq, assert_ne};
58 //! * Since `Rust 2018` edition, you need to declare
59 //! `use pretty_assertions::{assert_eq, assert_ne};` per module.
60 //! Before you would write `#[macro_use] extern crate pretty_assertions;`.
61 //! * The replacement is only effective in your own crate, not in other libraries
63 //! * `assert_ne` is also switched to multi-line presentation, but does _not_ show
66 #![deny(clippy::all, missing_docs, unsafe_code)]
68 pub use ansi_term
::Style
;
69 use std
::fmt
::{self, Debug, Display}
;
78 output_vt100
::try_init().ok(); // Do not panic on fail
81 /// A comparison of two values.
83 /// Where both values implement `Debug`, the comparison can be displayed as a pretty diff.
86 /// use pretty_assertions::Comparison;
88 /// print!("{}", Comparison::new(&123, &134));
91 /// The values may have different types, although in practice they are usually the same.
92 pub struct Comparison
<'a
, TLeft
, TRight
>
101 impl<'a
, TLeft
, TRight
> Comparison
<'a
, TLeft
, TRight
>
106 /// Store two values to be compared in future.
108 /// Expensive diffing is deferred until calling `Debug::fmt`.
109 pub fn new(left
: &'a TLeft
, right
: &'a TRight
) -> Comparison
<'a
, TLeft
, TRight
> {
110 Comparison { left, right }
114 impl<'a
, TLeft
, TRight
> Display
for Comparison
<'a
, TLeft
, TRight
>
116 TLeft
: Debug
+ ?Sized
,
117 TRight
: Debug
+ ?Sized
,
119 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
120 // To diff arbitary types, render them as debug strings
121 let left_debug
= format
!("{:#?}", self.left
);
122 let right_debug
= format
!("{:#?}", self.right
);
123 // And then diff the debug output
124 printer
::write_header(f
)?
;
125 printer
::write_lines(f
, &left_debug
, &right_debug
)
129 /// Asserts that two expressions are equal to each other (using [`PartialEq`]).
131 /// On panic, this macro will print a diff derived from [`Debug`] representation of
134 /// This is a drop in replacement for [`std::assert_eq!`].
135 /// You can provide a custom panic message if desired.
140 /// use pretty_assertions::assert_eq;
144 /// assert_eq!(a, b);
146 /// assert_eq!(a, b, "we are testing addition with {} and {}", a, b);
149 macro_rules
! assert_eq
{
150 ($left
:expr
, $right
:expr
,) => ({
151 $
crate::assert_eq
!($left
, $right
)
153 ($left
:expr
, $right
:expr
) => ({
154 match (&($left
), &($right
)) {
155 (left_val
, right_val
) => {
156 if !(*left_val
== *right_val
) {
157 ::std
::panic
!("assertion failed: `(left == right)`\
161 $
crate::Comparison
::new(left_val
, right_val
))
166 ($left
:expr
, $right
:expr
, $
($arg
:tt
)*) => ({
167 match (&($left
), &($right
)) {
168 (left_val
, right_val
) => {
169 if !(*left_val
== *right_val
) {
170 ::std
::panic
!("assertion failed: `(left == right)`: {}\
174 format_args
!($
($arg
)*),
175 $
crate::Comparison
::new(left_val
, right_val
))
182 /// Asserts that two expressions are not equal to each other (using [`PartialEq`]).
184 /// On panic, this macro will print the values of the expressions with their
185 /// [`Debug`] representations.
187 /// This is a drop in replacement for [`std::assert_ne!`].
188 /// You can provide a custom panic message if desired.
193 /// use pretty_assertions::assert_ne;
197 /// assert_ne!(a, b);
199 /// assert_ne!(a, b, "we are testing that the values are not equal");
202 macro_rules
! assert_ne
{
203 ($left
:expr
, $right
:expr
) => ({
204 $
crate::assert_ne
!(@ $left
, $right
, "", "");
206 ($left
:expr
, $right
:expr
,) => ({
207 $
crate::assert_ne
!(@ $left
, $right
, "", "");
209 ($left
:expr
, $right
:expr
, $
($arg
:tt
)+) => ({
210 $
crate::assert_ne
!(@ $left
, $right
, ": ", $
($arg
)+);
212 (@ $left
:expr
, $right
:expr
, $maybe_semicolon
:expr
, $
($arg
:tt
)+) => ({
213 match (&($left
), &($right
)) {
214 (left_val
, right_val
) => {
215 if *left_val
== *right_val
{
216 let left_dbg
= ::std
::format
!("{:?}", &*left_val
);
217 let right_dbg
= ::std
::format
!("{:?}", &*right_val
);
218 if left_dbg
!= right_dbg
{
220 ::std
::panic
!("assertion failed: `(left != right)`{}{}\
223 \n{}: According to the `PartialEq` implementation, both of the values \
224 are partially equivalent, even if the `Debug` outputs differ.\
228 format_args
!($
($arg
)+),
229 $
crate::Comparison
::new(left_val
, right_val
),
236 ::std
::panic
!("assertion failed: `(left != right)`{}{}\
243 format_args
!($
($arg
)+),
244 $
crate::Style
::new().bold().paint("Both sides"),
253 #[allow(clippy::eq_op)]
254 #[no_implicit_prelude]
257 use ::std
::string
::{String, ToString}
;
261 let a
= "some value";
262 crate::assert_eq
!(a
, a
);
266 fn passes_unsized() {
268 crate::assert_eq
!(*a
, *a
);
272 fn passes_comparable_types() {
273 let s0
: &'
static str = "foo";
274 let s1
: String
= "foo".to_string();
275 crate::assert_eq
!(s0
, s1
);
279 #[should_panic(expected = r#"assertion failed: `(left == right)`
281 \e[1mDiff\e[0m \e[31m< left\e[0m / \e[32mright >\e[0m :
282 \e[31m<\e[0m\e[1;48;5;52;31m666\e[0m
283 \e[32m>\e[0m\e[1;48;5;22;32m999\e[0m
287 crate::assert_eq
!(666, 999);
291 #[should_panic(expected = r#"assertion failed: `(left == right)`
293 \e[1mDiff\e[0m \e[31m< left\e[0m / \e[32mright >\e[0m :
294 \e[31m<\e[0m\e[1;48;5;52;31m666\e[0m
295 \e[32m>\e[0m\e[1;48;5;22;32m999\e[0m
298 fn fails_trailing_comma() {
299 crate::assert_eq
!(666, 999,);
303 #[should_panic(expected = r#"assertion failed: `(left == right)`
305 \e[1mDiff\e[0m \e[31m< left\e[0m / \e[32mright >\e[0m :
314 let b
: &[u8] = b
"ee";
315 crate::assert_eq
!(*a
, *b
);
320 expected
= r
#"assertion failed: `(left == right)`: custom panic message
322 \e[1mDiff\e[0m \e[31m< left\e[0m / \e[32mright >\e[0m :
323 \e[31m<\e[0m\e[1;48;5;52;31m666\e[0m
324 \e[32m>\e[0m\e[1;48;5;22;32m999\e[0m
329 crate::assert_eq
!(666, 999, "custom panic message");
334 expected
= r
#"assertion failed: `(left == right)`: custom panic message
336 \e[1mDiff\e[0m \e[31m< left\e[0m / \e[32mright >\e[0m :
337 \e[31m<\e[0m\e[1;48;5;52;31m666\e[0m
338 \e[32m>\e[0m\e[1;48;5;22;32m999\e[0m
342 fn fails_custom_trailing_comma() {
343 crate::assert_eq
!(666, 999, "custom panic message",);
348 use ::std
::string
::{String, ToString}
;
354 crate::assert_ne
!(a
, b
);
358 fn passes_unsized() {
360 let b
: &[u8] = b
"ee";
361 crate::assert_ne
!(*a
, *b
);
365 fn passes_comparable_types() {
366 let s0
: &'
static str = "foo";
367 let s1
: String
= "bar".to_string();
368 crate::assert_ne
!(s0
, s1
);
372 #[should_panic(expected = r#"assertion failed: `(left != right)`
374 \e[1mBoth sides\e[0m:
378 crate::assert_ne
!(666, 666);
382 #[should_panic(expected = r#"assertion failed: `(left != right)`
384 \e[1mBoth sides\e[0m:
387 fn fails_trailing_comma() {
388 crate::assert_ne
!(666, 666,);
392 #[should_panic(expected = r#"assertion failed: `(left != right)`
394 \e[1mBoth sides\e[0m:
402 crate::assert_ne
!(*a
, *a
);
407 expected
= r
#"assertion failed: `(left != right)`: custom panic message
409 \e[1mBoth sides\e[0m:
414 crate::assert_ne
!(666, 666, "custom panic message");
419 expected
= r
#"assertion failed: `(left != right)`: custom panic message
421 \e[1mBoth sides\e[0m:
425 fn fails_custom_trailing_comma() {
426 crate::assert_ne
!(666, 666, "custom panic message",);
429 // If the values are equal but their debug outputs are not
430 // show a specific warning
433 #[should_panic(expected = r#"assertion failed: `(left != right)`
435 \e[1mDiff\e[0m \e[31m< left\e[0m / \e[32mright >\e[0m :
436 \e[31m<\e[0m\e[1;48;5;52;31m-\e[0m\e[31m0.0\e[0m
439 \e[1;4mNote\e[0m: According to the `PartialEq` implementation, both of the values are partially equivalent, even if the `Debug` outputs differ.
442 fn assert_ne_partial() {
443 // Workaround for https://github.com/rust-lang/rust/issues/47619
444 // can be removed, when we require rust 1.25 or higher
448 impl fmt
::Debug
for Foo
{
449 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
450 ::std
::write
!(f
, "{:.1?}", self.0)
454 impl ::std
::cmp
::PartialEq
for Foo
{
455 fn eq(&self, other
: &Self) -> bool
{
460 crate::assert_ne
!(Foo(-0.0), Foo(0.0));
467 fn assert_ne_non_empty_return() {
468 fn not_zero(x
: u32) -> u32 {
469 crate::assert_ne
!(x
, 0);