How to run setup code before any tests run in Rust?

There's nothing built-in that would do this but this should help (you will need to call initialize() in the beginning of every test):

use std::sync::Once;

static INIT: Once = Once::new();

pub fn initialize() {
    INIT.call_once(|| {
        // initialization code here
    });
}

Just to give people more ideas (for example, how not to call setup in every test), one additional thing you could do is to write a helper like this:

fn run_test<T>(test: T) -> ()
    where T: FnOnce() -> () + panic::UnwindSafe
{
    setup();    
    let result = panic::catch_unwind(|| {
        test()
    });    
    teardown();    
    assert!(result.is_ok())
}

Then, in your own tests you would use it like this:

#[test]
fn test() {
    run_test(|| {
        let ret_value = function_under_test();
        assert!(ret_value);
    })
}

You can read more about UnwindSafe trait and catch_unwind here: https://doc.rust-lang.org/std/panic/fn.catch_unwind.html

I've found the original idea of this test helper in this medium article by Eric Opines.

Also, there is rstest crate which has pytest-like fixtures which you can use as a setup code (combined with the Jussi Kukkonen's answer:

use std::sync::Once; 
use rstest::rstest;
static INIT: Once = Once::new();

pub fn setup() -> () { 
    INIT.call_once(|| {
        // initialization code here
    });
}

#[rstest]
fn should_success(setup: ()) {
    // do your test
}

Maybe one day rstest will gain scopes support and Once won't be needed anymore.


If you use the ctor crate, you can take advantage of a global constructor function that will run before any of your tests are run.

Here's an example initialising the popular env_logger crate (assuming you have added ctor to your [dev-dependencies] section in your Cargo.toml file):

#[cfg(test)]
#[ctor::ctor]
fn init() {
    env_logger::init();
}

The function name is unimportant and you may name it anything.