Testing and Documentation

Write unit tests, integration tests, and generate documentation for your Rust projects.


Rust Testing with Cargo

Introduction to Testing in Rust

Rust provides robust testing capabilities integrated directly into the Cargo build system. This allows developers to easily write and run tests to ensure code quality, correctness, and stability.

Using `cargo test`

The core command for running tests in Rust is cargo test. This command compiles your tests and executes them, providing a summary of the results.

Detailed Explanation of `cargo test`

Basic Usage

Simply running cargo test in the root directory of your Rust project will automatically discover and run all tests defined in your project's source code and in the tests/ directory.

Test Discovery

Cargo automatically discovers tests in the following locations:

  • Functions annotated with the #[test] attribute within your source code (src/lib.rs, src/main.rs, etc.). These are typically unit tests.
  • Modules annotated with the #[cfg(test)] attribute containing functions with the #[test] attribute.
  • Files located in the tests/ directory of your project. These are integration tests. Each file in tests/ is treated as a separate crate.
  • Files located in the benches/ directory of your project. These are benchmarks, which are run separately.

Filtering Tests

You can filter which tests are run by providing a filter string to cargo test. This filter matches against the name of the test function or module.

cargo test my_module

This command will only run tests whose names contain "my_module". This can include a module name like `my_module::my_test` or a test function named `my_module`.

Regular expressions can also be used for more sophisticated filtering. To enable regex filtering, use the --features regex flag when compiling your tests, and then pass a regular expression to cargo test.

cargo test --features regex ".*important.*"

Running Specific Tests

You can run a specific test function by providing its full path (module path followed by function name) to cargo test.

cargo test my_module::my_test

Running Ignored Tests

Tests annotated with #[ignore] are skipped by default. You can run these tests using the --ignored flag.

cargo test --ignored

You can also run only ignored tests with --include-ignored:

cargo test --include-ignored

Running Tests in Release Mode

By default, cargo test compiles your tests in debug mode. To run tests in release mode, use the --release flag. This allows you to test performance-critical code with optimizations enabled.

cargo test --release

Running Tests in Parallel

Cargo automatically runs tests in parallel. You can control the number of threads used with the --test-threads flag. Setting this to 1 will run tests serially.

cargo test --test-threads 4

Running Documentation Tests

Rust supports documentation tests, which are code examples embedded in your documentation that are automatically tested. These tests can be run with cargo test and are included by default. You can disable them with --no-run if you only want to compile the documentation but not run the examples.

Running Benchmarks

Rust supports benchmarking code using the test crate. To define a benchmark, use the #[bench] attribute. Benchmarks are located in the benches/ directory.

To run benchmarks, use the following command:

cargo bench

Benchmarks are run in release mode by default to provide accurate performance measurements. They also require the nightly toolchain.

Understanding Test Output

The output of cargo test provides information about the test results.

Key information in the output includes:

  • Running n tests: Indicates the number of tests being executed.
  • test test_name ... result: Shows the name of each test and its result (ok, failed, ignored).
  • failures: A section listing the specific tests that failed and the corresponding error messages.
  • stdout: The standard output of the test functions, which can be useful for debugging.
  • stderr: The standard error output of the test functions.
  • test result: A summary of the test run, including the number of tests run, the number of tests that passed, failed, ignored, and measured.

For failed tests, the output will typically include a detailed error message indicating the cause of the failure. This often includes a stack trace, helping you pinpoint the location of the error in your code.

When running tests in parallel, the output may be interleaved. Cargo attempts to group the output of each test together to improve readability.

You can customize the verbosity of the output using the -v (verbose) or -q (quiet) flags.