How to initialize the logger for integration tests

2019-01-15 13:24发布

问题:

I have a crate with production code in the src directory and integration tests in the tests directory. The production code uses log macros.

I would like to init a global logger when running the integration tests (e.g. env_logger::init().unwrap();) There are several tests and the test order is not defined, so I don't know in which test I should put the initialize command.

Is there any way I can do this nicely? Perhaps by overriding the tests main function?

回答1:

There's no good way to do this kind of thing built-in right now.

You can write a macro that inserts some sort of initialization call before each test, but that's as close as there is.



回答2:

You can use something like this:

use std::sync::{Once, ONCE_INIT};

static INIT: Once = ONCE_INIT;

/// Setup function that is only run once, even if called multiple times.
fn setup() {
    INIT.call_once(|| {
        env_logger::init().unwrap();
    });
}

Then simply call setup() in the beginning of each test.

Originally based on this blogpost.



回答3:

For now, you can just re-initialize the logger at the top of every test and ignore the error. It's not a pretty solution but it works and is perfectly safe.

let _ = env_logger::init();

// your test code...


回答4:

I've observed cargo test running the tests in alphabetical order, so I devised a very dirty hack to initialize the logger.

  1. I made a module called aaa_testing residing inside the root of the crate.
  2. Inside the module, I wrote the logger initializer.

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

Yes I did create a test that will always pass, but if you want to have a test for initializing the logger, you can do a assert!(env_logger::try_init().is_ok());


Shepmaster pointed out that cargo test runs tests asynchronously and may make logging of the first few tests unreliable. To prevent this, the tests can be ran in the same thread. (This will cause performance problems, so this answer should not be used if you need multiple threads to test your project.)

If you want to control the number of simultaneous running test cases, pass the --test-threads option to the test binaries:

cargo test -- --test-threads=1


标签: rust