Testing is built into the language and Cargo — no framework to install, no config to write. cargo test just works, and Rust supports three flavors of test out of the box.
Unit tests
Unit tests live in the same file as the code they test, in a #[cfg(test)] mod tests block. Functions marked #[test] are run by cargo test. Because they're in the module, they can test private functions — a deliberate Rust choice many languages can't match. Use assert!, assert_eq!, and friends for the checks.
Integration tests
Integration tests live in a top-level tests/ directory, each file a separate crate that uses your library through its public API only — exactly as a real consumer would. They verify your crate works from the outside. The split is intentional: unit tests check internals, integration tests check the contract.
#[test], cargo test, and #[cfg(test)] are language and tooling features — no third-party framework, no setup. That low friction is why idiomatic Rust is heavily tested: when writing a test costs nothing but the test itself, you write more of them.Doctests
The third flavor is uniquely Rust: code examples in your /// doc comments are compiled and run as tests. A wrong example fails cargo test, so your documentation can't drift out of sync with your code. It's the antidote to stale docs — the examples are guaranteed to work because they're tested on every run.