What are the rules for `#[cfg(test)]`?

cfg(test) is enabled when building “unit tests” and “unit benchmarks” found inside your library or binary crate. If you have a #[test] or #[bench] function inside your library crate (src/lib.rs and its submodules) or your binary crate (src/main.rs or its submodules), Cargo will build that entire crate with rustc --test, which enables cfg(test) and produces a “test harness” binary containing all of its unit tests/benchmarks.

However, if you have “integration tests” or “integration benchmarks” that live outside of your main crate (by default, Cargo looks for these in tests/*.rs and benches/*.rs), these are not compiled against a test version of your library crate. Cargo will build your library in its normal (non-test) configuration, then build each integration test/benchmark as a sepate binary crate which links to that library. So library code marked with #[cfg(test)] is not available in integration tests/benches.

Doctests are also compiled like integration tests, linking to a non-test build of your library.

Similarly, if your Cargo package contains both library and binary crates, unit tests in the binary are linked to a non-test build of the library, so they can't use #[cfg(test)] code from the library crate.

10 Likes