DEV Community

Cover image for [Rust Guide] 11.3. Custom Error Messages
SomeB1oody
SomeB1oody

Posted on

[Rust Guide] 11.3. Custom Error Messages

If you find this helpful, please like, bookmark, and follow. To keep learning along, follow this series.

11.3.1 Adding Error Messages

In 11.2. Assertions (Assert), we learned about the assert!, assert_eq!, and assert_ne! macros, and this article covers their advanced usage.

These three macros can accept custom error messages, but that is optional. If you add a custom message, it will be printed together with the standard failure message:

  • For assert!, the first argument is required and the custom message is the second argument.
  • For assert_eq! and assert_ne!, the first two arguments are required and the custom message is the third argument.

After you pass in the custom message, it will be sent to the format! macro to build a string. Since format! can use {} placeholders, the message you pass in can also use placeholders.

For example:

pub fn greeting(name: &str) -> String {
    format!("Hello {name}!")
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn greeting_contains_name() {
        let result = greeting("Carol");
        assert!(result.contains("Carol"));
    }
}
Enter fullscreen mode Exit fullscreen mode
  • greeting takes a string slice parameter named name, and returns a string formed by concatenating Hello, name, and !.
  • The greeting_contains_name test function first assigns the value returned by greeting("Carol") to result, and then calls the contains method on result to check whether result contains "Carol".

This code passes the test as is.

Now let’s manually introduce a bug by modifying the greeting function:

pub fn greeting(name: &str) -> String {
    format!("Hello!")
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn greeting_contains_name() {
        let result = greeting("Carol");
        assert!(result.contains("Carol"));
    }
}
Enter fullscreen mode Exit fullscreen mode

This test will fail:

$ cargo test
   Compiling greeter v0.1.0 (file:///projects/greeter)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.91s
     Running unittests src/lib.rs (target/debug/deps/greeter-170b942eb5bf5e3a)

running 1 test
test tests::greeting_contains_name ... FAILED

failures:

---- tests::greeting_contains_name stdout ----
thread 'tests::greeting_contains_name' panicked at src/lib.rs:12:9:
assertion failed: result.contains("Carol")
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    tests::greeting_contains_name

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

error: test failed, to rerun pass `--lib`
Enter fullscreen mode Exit fullscreen mode

However, the failure message only says that a panic occurred at line 12, column 9. It does not provide friendlier or more useful information. What should we do? Add a custom message:

pub fn greeting(name: &str) -> String {
    format!("Hello!")
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn greeting_contains_name() {
        let result = greeting("Carol");
        assert!(
            result.contains("Carol"),
            "Greeting did not contain name, value was `{result}`"
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:

$ cargo test
   Compiling greeter v0.1.0 (file:///projects/greeter)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.93s
     Running unittests src/lib.rs (target/debug/deps/greeter-170b942eb5bf5e3a)

running 1 test
test tests::greeting_contains_name ... FAILED

failures:

---- tests::greeting_contains_name stdout ----
thread 'tests::greeting_contains_name' panicked at src/lib.rs:12:9:
Greeting did not contain name, value was `Hello!`
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    tests::greeting_contains_name

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

error: test failed, to rerun pass `--lib`
Enter fullscreen mode Exit fullscreen mode

You can see that the custom message appears in the error output. Such messages are more meaningful in practice, which makes it easier to find the cause of the error.

Top comments (0)