tezvyn:

How does cargo differentiate unit and integration tests by location?

AI-drafted, machine-checkedSource: doc.rust-lang.orgintermediate

This tests Rust test layout conventions. Unit tests live inside src files in cfg(test) modules; integration tests go in top-level tests/ files as separate crates. Red flag: saying integration tests need cfg(test) or can use private APIs.

WHAT THIS TESTS: This question probes your familiarity with Cargo conventions for test organization and the compilation model behind unit versus integration tests. Interviewers want to see that you know why tests are placed where they are, not just memorized directory names. The key distinction is whether the test code is compiled as part of the library crate or as a separate external crate.

A GOOD ANSWER COVERS: First, unit tests live inside the src directory alongside the code they exercise, conventionally inside a module named tests that is annotated with cfg(test). This annotation ensures the test code is compiled and run only when you invoke cargo test, not during cargo build, which keeps release artifacts smaller. Because the unit test module is a child of the file it tests, it can bring private functions into scope with a glob import from the parent module and test internal interfaces. Second, integration tests are entirely external to the library and live in a top-level tests directory at the project root, next to src. Cargo automatically discovers files in this directory and compiles each one as its own separate crate. Since they are external consumers, integration tests can only call the public API and do not need the cfg(test) attribute because they are already isolated from the library build by directory convention.

COMMON WRONG ANSWERS: A major red flag is saying integration tests need cfg(test). They do not, because Cargo already treats the tests directory specially and compiles those files only during test runs. Another mistake is claiming integration tests can access private functions or modules; because they are compiled as separate crates, they are subject to normal visibility rules and can only use pub items. Some candidates also confuse the tests module inside a source file with the tests directory, suggesting they are interchangeable, which reveals a shallow understanding of the compilation boundary.

LIKELY FOLLOW-UPS: An interviewer might ask how you would share setup code across multiple integration test files. The answer is to put helper modules in a tests/common/mod.rs or tests/common.rs file so Cargo does not treat them as standalone test crates. They might also ask about binary projects, where integration tests in the tests directory can only test the library target, not the main.rs binary directly, which is why Rustaceans often keep logic in lib.rs.

ONE CONCRETE EXAMPLE: Imagine a library with a public add_two function and a private internal_adder function. In src/lib.rs, you would write a cfg(test) mod tests block that calls internal_adder directly via a glob import from the parent to verify edge cases. Then at tests/integration_test.rs, you would import your crate and write a test that calls add_two exactly as an external user would, ensuring the public contract holds without reaching into internals.

Read the original → doc.rust-lang.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.