Tests
rustc
has a built-in facility for building and running tests for a crate.
More information about writing and running tests may be found in the Testing
Chapter of the Rust Programming Language book.
Tests are written as free functions with the #[test]
attribute. For example:
#![allow(unused)] fn main() { #[test] fn it_works() { assert_eq!(2 + 2, 4); } }
Tests "pass" if they return without an error. They "fail" if they panic, or
return a type such as Result
that implements the Termination
trait
with a non-zero value.
By passing the --test
option to rustc
, the compiler will build the crate
in a special mode to construct an executable that will run the tests in the
crate. The --test
flag will make the following changes:
- The crate will be built as a
bin
crate type, forcing it to be an executable. - Links the executable with
libtest
, the test harness that is part of the standard library, which handles running the tests. - Synthesizes a
main
function which will process command-line arguments and run the tests. This newmain
function will replace any existingmain
function as the entry point of the executable, though the existingmain
will still be compiled. - Enables the
test
cfg option, which allows your code to use conditional compilation to detect if it is being built as a test. - Enables building of functions annotated with the
test
andbench
attributes, which will be run by the test harness.
After the executable is created, you can run it to execute the tests and
receive a report on what passes and fails. If you are using Cargo to manage
your project, it has a built-in cargo test
command which handles all of
this automatically. An example of the output looks like this:
running 4 tests
test it_works ... ok
test check_valid_args ... ok
test invalid_characters ... ok
test walks_the_dog ... ok
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Note: Tests must be built with the
unwind
panic strategy. This is because all tests run in the same process, and they are intended to catch panics, which is not possible with theabort
strategy. See the unstable-Z panic-abort-tests
option for experimental support of theabort
strategy by spawning tests in separate processes.
Test attributes
Tests are indicated using attributes on free functions. The following attributes are used for testing, see the linked documentation for more details:
#[test]
— Indicates a function is a test to be run.#[bench]
— Indicates a function is a benchmark to be run. Benchmarks are currently unstable and only available in the nightly channel, see the unstable docs for more details.#[should_panic]
— Indicates that the test function will only pass if the function panics.#[ignore]
— Indicates that the test function will be compiled, but not run by default. See the--ignored
and--include-ignored
options to run these tests.
CLI arguments
The libtest harness has several command-line arguments to control its behavior.
Note: When running with
cargo test
, the libtest CLI arguments must be passed after the--
argument to differentiate between flags for Cargo and those for the harness. For example:cargo test -- --nocapture
Filters
Positional arguments (those without a -
prefix) are treated as filters which
will only run tests whose name matches one of those strings. The filter will
match any substring found in the full path of the test function. For example,
if the test function it_works
is located in the module
utils::paths::tests
, then any of the filters works
, path
, utils::
, or
utils::paths::tests::it_works
will match that test.
See Selection options for more options to control which tests are run.
Action options
The following options perform different actions other than running tests.
--list
Prints a list of all tests and benchmarks. Does not run any of the tests. Filters can be used to list only matching tests.
-h
, --help
Displays usage information and command-line options.
Selection options
The following options change how tests are selected.
--test
This is the default mode where all tests will be run as well as running all
benchmarks with only a single iteration (to ensure the benchmark works,
without taking the time to actually perform benchmarking). This can be
combined with the --bench
flag to run both tests and perform full
benchmarking.
--bench
This runs in a mode where tests are ignored, and only runs benchmarks. This
can be combined with --test
to run both benchmarks and tests.
--exact
This forces filters to match the full path of the test exactly.
For example, if the test it_works
is in the module utils::paths::tests
,
then only the string utils::paths::tests::it_works
will match that test.
--skip
FILTER
Skips any tests whose name contains the given FILTER string. This flag may be passed multiple times.
--ignored
Runs only tests that are marked with the ignore
attribute.
--include-ignored
Runs both ignored and non-ignored tests.
--exclude-should-panic
Excludes tests marked with the should_panic
attribute.
⚠️ 🚧 This option is unstable, and requires the -Z unstable-options
flag. See tracking issue
#82348 for more information.
Execution options
The following options affect how tests are executed.
--test-threads
NUM_THREADS
Sets the number of threads to use for running tests in parallel. By default,
uses the amount of concurrency available on the hardware as indicated by
available_parallelism
.
This can also be specified with the RUST_TEST_THREADS
environment variable.
--force-run-in-process
Forces the tests to run in a single process when using the abort
panic
strategy.
⚠️ 🚧 This only works with the unstable -Z panic-abort-tests
option, and
requires the -Z unstable-options
flag. See tracking issue
#67650 for more information.
--ensure-time
⚠️ 🚧 This option is unstable, and requires the -Z unstable-options
flag. See tracking issue
#64888 and the unstable
docs for more information.
--shuffle
Runs the tests in random order, as opposed to the default alphabetical order.
This may also be specified by setting the RUST_TEST_SHUFFLE
environment
variable to anything but 0
.
The random number generator seed that is output can be passed to
--shuffle-seed
to run the tests in the same order
again.
Note that --shuffle
does not affect whether the tests are run in parallel. To
run the tests in random order sequentially, use --shuffle --test-threads 1
.
⚠️ 🚧 This option is unstable, and requires the -Z unstable-options
flag. See tracking issue
#89583 for more information.
--shuffle-seed
SEED
Like --shuffle
, but seeds the random number generator with
SEED. Thus, calling the test harness with --shuffle-seed
SEED twice runs
the tests in the same order both times.
SEED is any 64-bit unsigned integer, for example, one produced by
--shuffle
.
This can also be specified with the RUST_TEST_SHUFFLE_SEED
environment
variable.
⚠️ 🚧 This option is unstable, and requires the -Z unstable-options
flag. See tracking issue
#89583 for more information.
Output options
The following options affect the output behavior.
-q
, --quiet
Displays one character per test instead of one line per test. This is an alias
for --format=terse
.
--nocapture
Does not capture the stdout and stderr of the test, and allows tests to print to the console. Usually the output is captured, and only displayed if the test fails.
This may also be specified by setting the RUST_TEST_NOCAPTURE
environment
variable to anything but 0
.
--show-output
Displays the stdout and stderr of successful tests after all tests have run.
Contrast this with --nocapture
which allows tests to print
while they are running, which can cause interleaved output if there are
multiple tests running in parallel, --show-output
ensures the output is
contiguous, but requires waiting for all tests to finish.
--color
COLOR
Control when colored terminal output is used. Valid options:
auto
: Colorize if stdout is a tty and--nocapture
is not used. This is the default.always
: Always colorize the output.never
: Never colorize the output.
--format
FORMAT
Controls the format of the output. Valid options:
pretty
: This is the default format, with one line per test.terse
: Displays only a single character per test.--quiet
is an alias for this option.json
: Emits JSON objects, one per line. ⚠️ 🚧 This option is unstable, and requires the-Z unstable-options
flag. See tracking issue #49359 for more information.
--logfile
PATH
Writes the results of the tests to the given file.
--report-time
⚠️ 🚧 This option is unstable, and requires the -Z unstable-options
flag. See tracking issue
#64888 and the unstable
docs for more information.
Unstable options
Some CLI options are added in an "unstable" state, where they are intended for
experimentation and testing to determine if the option works correctly, has
the right design, and is useful. The option may not work correctly, break, or
change at any time. To signal that you acknowledge that you are using an
unstable option, they require passing the -Z unstable-options
command-line
flag.
Benchmarks
The libtest harness supports running benchmarks for functions annotated with
the #[bench]
attribute. Benchmarks are currently unstable, and only
available on the nightly channel. More information may be found in the
unstable book.
Custom test frameworks
Experimental support for using custom test harnesses is available on the nightly channel. See tracking issue #50297 and the custom_test_frameworks documentation for more information.