//! # Pretty Assertions | |
//! | |
//! When writing tests in Rust, you'll probably use `assert_eq!(a, b)` _a lot_. | |
//! | |
//! If such a test fails, it will present all the details of `a` and `b`. | |
//! But you have to spot the differences yourself, which is not always straightforward, | |
//! like here: | |
//! | |
//!  | |
//! | |
//! Wouldn't that task be _much_ easier with a colorful diff? | |
//! | |
//!  | |
//! | |
//! Yep — and you only need **one line of code** to make it happen: | |
//! | |
//! ```rust,ignore | |
//! #[macro_use] extern crate pretty_assertions; | |
//! ``` | |
//! | |
//! <details> | |
//! <summary>Show the example behind the screenshots above.</summary> | |
//! | |
//! ```rust,ignore | |
//! // 1. add the `pretty_assertions` dependency to `Cargo.toml`. | |
//! // 2. insert this line at the top of your crate root or integration test | |
//! #[macro_use] extern crate pretty_assertions; | |
//! | |
//! fn main() { | |
//! #[derive(Debug, PartialEq)] | |
//! struct Foo { | |
//! lorem: &'static str, | |
//! ipsum: u32, | |
//! dolor: Result<String, String>, | |
//! } | |
//! | |
//! 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); | |
//! } | |
//! ``` | |
//! </details> | |
//! | |
//! ## Tip | |
//! | |
//! Specify it as [`[dev-dependencies]`](http://doc.crates.io/specifying-dependencies.html#development-dependencies) | |
//! and it will only be used for compiling tests, examples, and benchmarks. | |
//! This way the compile time of `cargo build` won't be affected! | |
//! | |
//! In your crate root, also add `#[cfg(test)]` to the crate import, like this: | |
//! | |
//! ```rust,ignore | |
//! #[cfg(test)] // <-- not needed in examples + integration tests | |
//! #[macro_use] | |
//! extern crate pretty_assertions; | |
//! ``` | |
//! | |
//! ## Note | |
//! | |
//! * Each example and integration test also needs `#[macro_use] extern crate | |
//! pretty_assertions`, if you want colorful diffs there. | |
//! * The replacement is only effective in your own crate, not in other libraries | |
//! you include. | |
//! * `assert_ne` is also switched to multi-line presentation, but does _not_ show | |
//! a diff. | |
extern crate difference; | |
extern crate ansi_term; | |
mod format_changeset; | |
use std::fmt::{self, Debug, Display}; | |
use difference::Changeset; | |
use format_changeset::format_changeset; | |
pub use ansi_term::Style; | |
#[doc(hidden)] | |
pub struct Comparison(Changeset); | |
impl Comparison { | |
pub fn new<TLeft: Debug, TRight: Debug>(left: &TLeft, right: &TRight) -> Comparison { | |
let left_dbg = format!("{:#?}", *left); | |
let right_dbg = format!("{:#?}", *right); | |
let changeset = Changeset::new(&left_dbg, &right_dbg, "\n"); | |
Comparison(changeset) | |
} | |
} | |
impl Display for Comparison { | |
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
format_changeset(f, &self.0) | |
} | |
} | |
#[macro_export] | |
macro_rules! assert_eq { | |
($left:expr , $right:expr,) => ({ | |
assert_eq!($left, $right) | |
}); | |
($left:expr , $right:expr) => ({ | |
match (&($left), &($right)) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
panic!("assertion failed: `(left == right)`\ | |
\n\ | |
\n{}\ | |
\n", | |
$crate::Comparison::new(left_val, right_val)) | |
} | |
} | |
} | |
}); | |
($left:expr , $right:expr, $($arg:tt)*) => ({ | |
match (&($left), &($right)) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
panic!("assertion failed: `(left == right)`: {}\ | |
\n\ | |
\n{}\ | |
\n", | |
format_args!($($arg)*), | |
$crate::Comparison::new(left_val, right_val)) | |
} | |
} | |
} | |
}); | |
} | |
#[macro_export] | |
#[doc(hidden)] | |
macro_rules! __assert_ne { | |
($left:expr, $right:expr, $maybe_semicolon:expr, $($arg:tt)+) => ({ | |
match (&($left), &($right)) { | |
(left_val, right_val) => { | |
if *left_val == *right_val { | |
let left_dbg = format!("{:?}", *left_val); | |
let right_dbg = format!("{:?}", *right_val); | |
if left_dbg != right_dbg { | |
panic!("assertion failed: `(left != right)`{}{}\ | |
\n\ | |
\n{}\ | |
\n{}: According to the `PartialEq` implementation, both of the values \ | |
are partially equivalent, even if the `Debug` outputs differ.\ | |
\n\ | |
\n", | |
$maybe_semicolon, | |
format_args!($($arg)+), | |
$crate::Comparison::new(left_val, right_val), | |
$crate::Style::new() | |
.bold() | |
.underline() | |
.paint("Note")) | |
} | |
panic!("assertion failed: `(left != right)`{}{}\ | |
\n\ | |
\n{}:\ | |
\n{:#?}\ | |
\n\ | |
\n", | |
$maybe_semicolon, | |
format_args!($($arg)+), | |
$crate::Style::new().bold().paint("Both sides"), | |
left_val) | |
} | |
} | |
} | |
}); | |
} | |
#[macro_export] | |
macro_rules! assert_ne { | |
($left:expr, $right:expr) => ({ | |
__assert_ne!($left, $right, "", ""); | |
}); | |
($left:expr, $right:expr,) => ({ | |
__assert_ne!($left, $right, "", ""); | |
}); | |
($left:expr, $right:expr, $($arg:tt)+) => ({ | |
__assert_ne!($left, $right, ": ", $($arg)+); | |
}); | |
} |