Reputation: 703
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?
Upvotes: 48
Views: 12002
Reputation: 5780
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::try_init();
// your test code...
Upvotes: 6
Reputation: 3447
The latest documentation has a recommendation on Capturing logs in tests :: env_logger:
Records logged during cargo test will not be captured by the test harness by default. The Builder::is_test method can be used in unit tests to ensure logs will be captured:
#[cfg(test)]
mod tests {
fn init() {
let _ = env_logger::builder().is_test(true).try_init();
}
#[test]
fn it_works() {
init();
info!("This record will be captured by `cargo test`");
assert_eq!(3, 1 + 2);
}
}
Upvotes: 16
Reputation: 433
In addition to Danilo Bargen's comment, you can write it in a shorter form:
use std::sync::Once;
static INIT: Once = Once::new();
fn setup() {
INIT.call_once(env_logger::init);
}
Upvotes: 7
Reputation: 19452
You can use something like this:
use std::sync::Once;
static INIT: Once = Once::new();
/// 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.
Upvotes: 48