RustBrock/Writing_Tests.md

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 isok`

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