Rust tip: Improve your testing using context structures

Enable setup and teardown functionality in Rust tests

Fredrik Park published on
2 min, 234 words

Categories: Tips

In Rust, we have no default way of achieving setup and teardown functionality like we have in other languages.

But we can utilize Rusts structures to achieve a similar result.

The pattern is simple

  • Create a struct (it can contain data if you need it)
  • Implement a constructor function for the struct, this will be your setup. Note that you could have several, depending on your different testing needs.
  • If you need to do any teardown (in most cases you do not need it). You can implement the drop trait on your struct.

Here is a full example

#[cfg(test)]
mod test {
    struct TestCtx();

    impl TestCtx {
        fn setup() -> Self {
            println!("Setup");

            Self()
        }
    }

    impl Drop for TestCtx {
        fn drop(&mut self) {
            println!("Teardown");
        }
    }

    #[test]
    fn hello_setup_teardown() {
        let _ctx = TestCtx::setup();

        println!("This is my test");

        // Teardown is automatic thanks to Drop
    }
}

And when we run cargo test this we get the following output.

ℹ️ We need to use -- --nocapture to tell cargo not to capture our tests output

 cargo test -- --nocapture
   Compiling itesting v0.1.0 (/tmp/tmp.FIXDYeNCdW/itesting)
    Finished test [unoptimized + debuginfo] target(s) in 0.21s
     Running unittests src/main.rs (target/debug/deps/itesting-a8ed9686e842fc47)

running 1 test
Setup
This is my test
Teardown
test test::hello_setup_teardown ... ok

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