How to Write Tests in Rust

How to Write Tests in Rust

ยท

3 min read

Testing is an essential part of software development, especially when coding professionally and improving your code's quality.

In Rust, testing is built into the language, making writing and running tests straightforward.

This article will introduce you to the basics of testing in Rust with practical examples.

If you prefer a video version VARIABLES (40)

Create the lib project

In this case, we will create a library project using the following command:

cargo new adder --lib

Remember to use the --bin flag to create a binary project.

To run the tests, you can use the following command:

cargo test

This command will compile the code and run the tests.

Now let's create a simple function to test.

Basic Test Function

Let's start with a simple test function. In Rust, test functions are annotated with #[test].

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}

In this example, the #[cfg(test)] attribute ensures that the test module is only compiled when running tests. The #[test] attribute marks the function as a test.

The assert_eq! macro checks if the two arguments are equal. If they are not, the test will fail.

The output of the test will look like this:

running 1 test
test tests::it_works ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

Making a Test That Fails

It's often useful to see what happens when a test fails.

Here's an example:

#[cfg(test)]
mod tests {
    #[test]
    fn it_fails() {
        assert_eq!(2 + 2, 5);
    }
}

When you run this test, it will fail, and you'll see an error message like this:

---- it_fails stdout ----
thread 'tests::it_fails' panicked at 'assertion failed: `(left == right)`
  left: `4`,
 right: `5`', src/lib.rs:4:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Using the assert! Macro

The assert! macro is used to check boolean expressions. If the expression evaluates to false, the test will fail.

#[cfg(test)]
mod tests {
    #[test]
    fn check_true() {
        assert!(true);
    }
}

Testing Equality with assert_eq! and assert_ne!

The assert_eq! macro checks if two values are equal, while assert_ne! checks if they are not.

#[cfg(test)]
mod tests {
    #[test]
    fn test_equality() {
        assert_eq!(3 * 3, 9);
        assert_ne!(3 * 3, 8);
    }
}

Adding Custom Failure Messages

You can add custom failure messages to your tests using the assert! macro.

#[cfg(test)]
mod tests {
    #[test]
    fn custom_message() {
        assert_eq!(2 + 2, 5, "Math is broken!");
    }
}

In this example, the test will fail with the message "Math is broken!".

The output will look like this:

---- custom_message stdout ----
thread 'tests::custom_message' panicked at 'assertion failed: `(left == right)`
  left: `4`,
 right: `5`: Math is broken!', src/lib.rs:4:9

Checking for Panics with should_panic

You can test if a function panics using the should_panic attribute.

#[cfg(test)]
mod tests {
    #[test]
    #[should_panic]
    fn it_panics() {
        panic!("This test will panic");
    }
}

Using Result in Tests

Test functions can return Result<(), E> to use the ? operator for error handling.

#[cfg(test)]
mod tests {
    #[test]
    fn test_with_result() -> Result<(), String> {
        if 2 + 2 == 4 {
            Ok(())
        } else {
            Err("Math is broken".into())
        }
    }
}

Conclusion

Rust makes testing easy and powerful with its built-in features.

By using attributes like #[test], assert!, assert_eq!, and should_panic, you can write robust tests for your code.

If you prefer a video version VARIABLES (40)

Did you find this article valuable?

Support Francesco Ciulla by becoming a sponsor. Any amount is appreciated!