Cargo runs unit tests concurrently on separate threads, usually transparently. The main complication is shared global state: unsynchronized mutation can cause compilation failures, data races, or undefined behavior. section 6.5
Choose synchronization and initialization mechanisms deliberately:
- Use an atomic integer for a simple shared counter. section 6.5
- Use Arc when tests need shared ownership, but initialize non-constant statics through lazy_static. section 6.5
- Use a Mutex when tests must serialize access to mutable shared state. section 6.5
- Disable libtest with harness = false only when providing a custom test main is justified. section 6.5
#[cfg(test)]
mod tests {
use lazy_static::lazy_static;
use std::sync::Mutex;
lazy_static! {
static ref MUTEX: Mutex<i32> = Mutex::new(0);
}
#[test]
fn first_test() {
let _guard = MUTEX.lock().expect("couldn’t acquire lock");
println!("first test is running");
}
#[test]
fn second_test() {
let _guard = MUTEX.lock().expect("couldn’t acquire lock");
println!("second test is running");
}
}
A Mutex guard keeps two tests from entering their shared critical sections simultaneously. section 6.5

