3.8 KiB
How to Write Tests
TAests are Rust functions that verify that non-test code is funcioning as expected
The bodies of test functions typically perform these three actions:
- Set up any needed data or state
- Run the code you want to test
- Assert that the resutls are what yo expect
Lets look at the features Rst provides specifically for writing tests that take these actions.
This incldes the test
attribute, a few macros, and the should_panic
attribute
The Anatomy of a Test Function
A test in Rus is a function that is annotated with the test
attribute.
Attributes are metadata about peices of Rust code
An example of this that we used in the past was the derive
attribute which was used iwth structs in Ch5(Using Structs to Stucture Related Data)
To change a fucntion into a test function add #[test]
on the line before fn
When you run your tests with the cargo test
command
Rust will then builds a test runner binary that runs the annotated functions and reports whether each test function passes or fails.
Whenever we make a new library project with Cargo, a test module with a test function with a tet function in it is automaticakky generated for us
This module give a template for writing your tests.
This is great becuase you dont have to look up the syntax and structure every time you start a new project.
You can add as many additional test functions and as many modules as you want using that generated template
Find an example of this in the library/directory adder
Lets create the function add
Here is how to create a new library use this command
$ cargo new adder --lib
Created library `adder` project
$ cd adder
Here is what adder
library should look like/ the generated code
pub fn add(left: usize, right: usize) -> usize {
left + right
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
}
Lets focus on the it_works
function.
Note the #[test]
annotation; this attribute indicates this is a test function, so that the test runner knows how to treat this function as a test
We could also have non-test functions in the tests
module to help set up common scenarios or perform common operations, so we always need a way to indicate which are tests
This test example uses the assert_eq!
macro to assert that result
, which contains the result of adding 2 and 2, equlas 4.
This servers as an example of the format of a typical test
After the cargo test
command runs all tests in our project
Here is the result
$ cargo test
Compiling adder v0.1.0 (file:///projects/adder)
Finished `test` profile [unoptimized + debuginfo] target(s) in 0.57s
Running unittests src/lib.rs (target/debug/deps/adder-92948b65e88960b4)
running 1 test
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Doc-tests adder
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
We can see that cargo compiled then ran the test.
We can see first running 1 test
, then it shows the function name ``tests::it_worksand then the result of running that test is
ok`
It then shows the overall summary test result: ok.
which means that all tests passed, and the portion that reads 1 passed; 0 failed
totals th number of tests that passed or failed
It's possible to mark a test as ignored so it doesn't run in a particular instance, that will be overed later in this ch
Because we havent it also shows 0 ignored
The 0 measured
statistic is for benchmark tests that measure performance.
Benchmark tests are only avaialbe in nightly Rust, at the time of 2023 or the writing of the rust programmign language book 2023