Shared Test Utilities
When multiple integration test files in tests/ need common setup helpers, mock servers, or sample data builders, those shared test utilities must be placed inside a subdirectory module (such as tests/common/mod.rs) rather than a top-level tests/common.rs file.
Why tests/common.rs Causes Unwanted Empty Test Runs
If you create tests/common.rs directly inside tests/, Cargo treats common.rs as an independent integration test binary with zero #[test] functions, printing an empty Running tests/common.rs (0 tests) section on every cargo test run.
Placing the shared module inside a subdirectory—tests/common/mod.rs—tells Cargo not to compile common as a standalone test target:
Correct Layout for Shared Utilities:
tests/
├── common/
│ └── mod.rs <-- Subdirectory: NOT compiled as a standalone binary
├── client_tests.rs <-- Declares `mod common;`
└── server_tests.rs <-- Declares `mod common;`
Suppressing False-Positive dead_code Warnings in tests/common/mod.rs
When both tests/client_tests.rs and tests/server_tests.rs write mod common;, each integration test binary compiles its own copy of common. If common defines setup_client() (used only by client_tests.rs) and setup_server() (used only by server_tests.rs), the compiler will emit a warning: function setup_server is never used while compiling client_tests.rs.
There are two clean solutions:
- Add
#![allow(dead_code)]at the top oftests/common/mod.rs. - Consolidate your integration tests into a single top-level
tests/integration.rsbinary (as shown in Section 54.4) so all submodules share the same crate compilation unit.
// File: tests/common/mod.rs
pub mod common {
#![allow(dead_code)]
#[derive(Debug)]
pub struct TestAccount {
pub username: String,
pub api_key: String,
}
pub fn fixture_account(name: &str) -> TestAccount {
TestAccount {
username: name.to_string(),
api_key: format!("test_key_{name}_99"),
}
}
pub fn unused_in_this_binary_helper() -> u32 {
42
}
}
fn main() {
let acct = common::fixture_account("alice");
println!("Created shared fixture for {}: {}", acct.username, acct.api_key);
}
Created shared fixture for alice: test_key_alice_99
Sharing Utilities Between Unit Tests (src/) and Integration Tests (tests/)
A unit test module (#[cfg(test)] mod tests inside src/lib.rs) cannot import tests/common/mod.rs because src/lib.rs is compiled before tests/. If you need the exact same test builders or mock traits in both unit tests (src/) and integration tests (tests/), you have two options:
- Workspace internal test crate: Create a small workspace member crate (e.g.,
crates/test_utils) and list it under[dev-dependencies]inCargo.toml. Bothsrc/unit tests andtests/integration tests can importtest_utils::*. - Feature-gated
test-utilmodule: Expose apub mod test_utilinsrc/lib.rsguarded by#[cfg(any(test, feature = "test-util"))].