The tests Directory
The tests directory is a special top-level directory placed alongside Cargo.toml and src/ that Cargo automatically scans for integration test files. Every top-level .rs file placed directly inside tests/ is compiled by Cargo as a standalone crate that links against your package's library target (src/lib.rs).
my_package/
├── Cargo.toml
├── src/
│ └── lib.rs <-- Compiled first as library `my_package`
└── tests/
├── auth_flow.rs <-- Compiled as standalone test binary #1
└── billing_flow.rs <-- Compiled as standalone test binary #2
How Cargo Compiles Files in tests/
When you run cargo test:
- Cargo compiles
src/lib.rsas a library crate. - For each
tests/<name>.rsfile, Cargo invokesrustc --test tests/<name>.rs --extern my_package=..., producing a separate executable binary per file. - Because files inside
tests/are never compiled duringcargo build, you do not write#[cfg(test)]at the top of files intests/. Every#[test]function at the top level oftests/auth_flow.rsis discovered and run automatically.
// File: tests/auth_flow.rs (links against `my_package` as an external crate)
mod my_package {
pub fn issue_token(user_id: u64) -> String {
format!("tok_{user_id}_v1")
}
pub fn validate_token(token: &str) -> Option<u64> {
let rest = token.strip_prefix("tok_")?.strip_suffix("_v1")?;
rest.parse().ok()
}
}
#[test]
fn round_trips_issued_token() {
let tok = my_package::issue_token(42);
assert_eq!(my_package::validate_token(&tok), Some(42));
}
#[test]
fn rejects_tampered_suffix() {
assert_eq!(my_package::validate_token("tok_42_v2"), None);
}
fn main() {
let tok = my_package::issue_token(42);
println!("Issued token: {tok}, valid user: {:?}", my_package::validate_token(&tok));
}
Issued token: tok_42_v1, valid user: Some(42)
Running a Single Integration Test File
When a project has multiple files in tests/, you can compile and run just one integration test binary using cargo test --test <filename_without_rs>:
cargo test --test auth_flow
Running tests/auth_flow.rs (target/debug/deps/auth_flow-9a8b7c6d5e4f)
running 2 tests
test rejects_tampered_suffix ... ok
test round_trips_issued_token ... ok
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Custom Integration Test Targets in Cargo.toml
By default, Cargo auto-discovers every tests/*.rs file (autotests = true). If an integration test requires a custom harness (for example, harness = false for custom benchmark or snapshot runners) or specific required features (required-features = ["postgres"]), you can declare a [[test]] section in Cargo.toml:
[[test]]
name = "postgres_integration"
path = "tests/postgres_integration.rs"
required-features = ["postgres-backend"]
When required-features is set, Cargo skips building and running postgres_integration unless --features postgres-backend (or --all-features) is enabled.