Unit Testing

assert_eq!

The assert_eq! macro asserts that two expressions are equal according to the PartialEq trait (left == right). If they are not equal, assert_eq! panics and prints the Debug representation of both the left and right values side by side.

assert_eq!(left, right)
assert_eq!(left, right, "custom context: {}", detail)

Trait Requirements on Operands

Unlike assert!(a == b) (which only requires PartialEq and prints no values on failure), assert_eq!(a, b) requires two traits on its operands:

  1. PartialEq: To evaluate left == right.
  2. std::fmt::Debug: To format both left and right in the panic message if the comparison returns false.

Therefore, always derive #[derive(Debug, PartialEq)] on custom structs and enums that you want to compare with assert_eq!.

#[derive(Debug, PartialEq, Eq)]
struct Point {
    x: i32,
    y: i32,
}

impl Point {
    fn translate(&self, dx: i32, dy: i32) -> Self {
        Self {
            x: self.x + dx,
            y: self.y + dy,
        }
    }
}

fn main() {
    let origin = Point { x: 0, y: 0 };
    let moved = origin.translate(5, -3);

    assert_eq!(moved, Point { x: 5, y: -3 });
    assert_eq!(
        moved.x + moved.y,
        2,
        "sum of coordinates for {moved:?} should be 2"
    );

    println!("Moved point verified: {moved:?}");
}
Moved point verified: Point { x: 5, y: -3 }

How assert_eq! Evaluates and Borrows Operands

Internally, assert_eq!(left, right) expands to match (&left, &right) { (left_val, right_val) => ... }:

  1. Both left and right are evaluated exactly once, even if the assertion fails and prints them.
  2. Both values are borrowed by shared reference (&left, &right), meaning assert_eq! does not move or consume owned variables:
fn main() {
    let message = String::from("rust-2024");
    let expected = String::from("rust-2024");

    // `message` and `expected` are borrowed, not moved
    assert_eq!(message, expected);

    // Both variables remain usable after `assert_eq!`
    println!("Still owned after assert_eq!: {message}");
}
Still owned after assert_eq!: rust-2024

Failure Diagnostic Output

When left == right evaluates to false, assert_eq! displays both left and right clearly:

fn main() {
    let actual = vec![10, 20, 99];
    let expected = vec![10, 20, 30];
    assert_eq!(actual, expected, "mismatch at index 2");
}
thread 'main' panicked at src/main.rs:4:5:
assertion `left == right` failed: mismatch at index 2
  left: [10, 20, 99]
 right: [10, 20, 30]

Floating-Point Caveat (NaN and Precision)

Because f64::NAN != f64::NAN under IEEE 754 PartialEq, assert_eq!(f64::NAN, f64::NAN) always panics. Furthermore, floating-point rounding (0.1 + 0.2 == 0.30000000000000004) makes exact assert_eq! fragile for computed floats; check assert!((actual - expected).abs() < 1e-12) instead.