Expand description
A test runner that builds tests with rustc or cargo (or any other compiler with some configuration effort) and compares the output of the compiler with a file that you check into git. This allows you to test how your libraries show up to your users when the library is used wrongly and emits errors.
§Usage
See examples directory for how to use this in your own crate.
To be able to use it with cargo test
, you need to put
[[test]]
name = "your_test_file"
harness = false
into your Cargo.toml
, otherwise cargo test
will only look for #[test]
s and
not run your fn main()
that actually executes ui_test
§Implicit (and possibly surprising) behavior
- Tests are run in order of their filenames (files first, then recursing into folders). So if you have any slow tests, prepend them with a small integral number to make them get run first, taking advantage of parallelism as much as possible (instead of waiting for the slow tests at the end).
cargo test --test your_test_name -- --help
lists the commands you can specify for filtering, blessing and making your tests less verbose.- Since
cargo test
on its own runs all tests, usingcargo test -- --check
will not work on its own, butcargo test -- --quiet
andcargo test -- some_test_name
will work just fine, as the CLI matches.
- Since
- if there is a
.stdin
file with the same filename as your test, it will be piped as standard input to your program.
§Supported comment annotations
If your test tests for failure, you need to add a //~
annotation where the error is happening
to ensure that the test will always keep failing at the annotated line. These comments can take two forms:
//~ LEVEL: XXX
matches by error level and message textLEVEL
can be one of the following (descending order):ERROR
,HELP
,WARN
,NOTE
orICE
- If a level is specified explicitly, all diagnostics of that level or higher need an annotation. To avoid this see
//@require-annotations-for-level
- This checks the output before normalization, so you can check things that get normalized away, but need to be careful not to accidentally have a pattern that differs between platforms.
- if
XXX
is of the form/XXX/
it is treated as a regex instead of a substring and will succeed if the regex matches.
//~ CODE
matches by diagnostic code.CODE
can take multiple forms such as:E####
,lint_name
,tool::lint_name
.- This will only match a diagnostic at the
ERROR
level.
In order to change how a single test is tested, you can add various //@
comments to the test.
Any other comments will be ignored, and all //@
comments must be formatted precisely as
their command specifies, or the test will fail without even being run.
-
//@ignore-C
avoids running the test when conditionC
is met.C
can betarget: XXX YYY
, which checks whether the target triple containsXXX
orYYY
.C
can behost: XXX YYY
, which checks whether the host triple containsXXX
orYYY
.C
can also bebitwidth:
followed by one or more space separated integer size like64
,32
or16
.C
can also beon-host
, which will only run the test during cross compilation testing.
-
//@only-C
only runs the test when conditionC
is met. The conditions are the same as withignore
. -
//@needs-asm-support
only runs the test when the target supportsasm!
. -
//@stderr-per-bitwidth
produces one stderr file per bitwidth, as they may differ significantly sometimes -
//@error-in-other-file: XXX
can be used to check for errors that can’t have//~
patterns due to being reported in other files. -
//@revisions: XXX YYY
runs the test once for each space separated name in the list- emits one stderr file per revision
//~
comments can be restricted to specific revisions by adding the revision name after the~
in square brackets://~[XXX]
//@
comments can be restricted to specific revisions by adding the revision name after the@
in square brackets://@[XXX]
- Note that you cannot add revisions to the
revisions
command.
- Note that you cannot add revisions to the
For example:
//@revisions: edition2021 edition2024 //@[edition2021] edition:2021 //@[edition2024] edition:2024 //@[edition2024] check-pass // Then in code: let x = 12; //~[edition2021] dead_code let x = 12; //~[edition2021]^ dead_code
-
//@compile-flags: XXX
appendsXXX
to the command line arguments passed to the rustc driver- you can specify this multiple times, and all the flags will accumulate
-
//@rustc-env: XXX=YYY
sets the env varXXX
toYYY
for the rustc driver execution.- for Miri these env vars are used during compilation via rustc and during the emulation of the program
- you can specify this multiple times, accumulating all the env vars
-
//@normalize-stderr-test: "REGEX" -> "REPLACEMENT"
replaces all matches ofREGEX
in the stderr withREPLACEMENT
. The replacement may specify$1
and similar backreferences to paste captures.- you can specify multiple such commands, there is no need to create a single regex that handles multiple replacements that you want to perform.
-
//@require-annotations-for-level: LEVEL
can be used to change the level of diagnostics that require a corresponding annotation.- this is only useful if there are any annotations like
HELP
,WARN
orNOTE
, as these would automatically require annotations for all other diagnostics of the same or higher level.
- this is only useful if there are any annotations like
-
//@check-pass
requires that a test has no error annotations, emits no errors, and exits successfully with exit/status code 0. -
//@edition: EDITION
overwrites the default edition (2021) to the given edition. -
//@no-rustfix
do not run rustfix on tests that have machine applicable suggestions. -
//@aux-build: filename
looks for a file in theauxiliary
directory (within the directory of the test), compiles it as a library and links the current crate against it. This allows you import the crate withextern crate
or just viause
statements. This will automatically detect aux files that are proc macros and build them as proc macros. -
//@run
compiles the test and runs the resulting binary. The resulting binary must exit successfully. Stdout and stderr are taken from the resulting binary. Any warnings during compilation are ignored.- You can also specify a different exit code/status that is expected via e.g.
//@run: 1
or//@run: 101
(the latter is the standard Rust exit code for panics). - run tests collect the run output into
.run.stderr
and.run.stdout
respectively. - if a
.run.stdin
file exists, it will be piped as standard input to your test’s execution.
- You can also specify a different exit code/status that is expected via e.g.
§Significant differences to compiletest-rs
- target selection is done via
ignore-target: xxx
andonly-target: xxx
instead of compiletest’signore-xxx
/only-xxx
. Thexxx
must also be a substring of the target triple; special collections such asmacos
/unix
in compiletest is not supported. - only supports
ui
tests - tests are run in named order, so you can prefix slow tests with
0
in order to make them get run first aux-build
s require specifying nested aux builds explicitly and will not allow you to reference siblingaux-build
s’ artifacts.
Re-exports§
pub use core::run_and_collect;
pub use core::CrateType;
pub use filter::Match;
pub use test_result::Errored;
pub use test_result::TestOk;
pub use color_eyre;
pub use spanned;
Modules§
- aux_
builds - Everything needed to build auxilary files with rustc
- build_
manager - Auxiliary and dependency builder. Extendable to custom builds.
- core
- Basic operations useful for building a testsuite
- custom_
flags - Define custom test flags not natively supported by ui_test
- dependencies
- Use
cargo
to build dependencies and make them available in your tests - diagnostics
- Data structures for handling diagnostic output from tests.
- filter
- Datastructures and operations used for normalizing test output.
- github_
actions - An interface to github actions workflow commands.
- nextest
- Helper functions for nextest emulation.
- per_
test_ config - This module allows you to configure the default settings for all tests.
- status_
emitter - Various schemes for reporting messages during testing or after testing is done.
- test_
result - Various data structures used for carrying information about test success or failure
Structs§
- Abort
Check - An atomic bool that can be set to
true
to abort all tests. Will not cancel child processes, but if set from a Ctrl+C handler, the pressing of Ctrl+C will already have cancelled child processes. - Args
- Plain arguments if
ui_test
is used as a binary. - Command
Builder - A command, its args and its environment. Used for the main command, the dependency builder and the cfg-reader.
- Comment
Parser - Main entry point to parsing comments and handling parsing errors.
- Comments
- This crate supports various magic comments that get parsed as file-specific configuration values. This struct parses them all in one go and then they get processed by their respective use sites.
- Config
- Central datastructure containing all information to run the tests.
- OptWith
Line - An optional spanned value.
- Revisioned
- Comments that can be filtered for specific revisions.
- Target
SubStr - A sub string of a target (or a whole target).
Enums§
- Condition
- The conditions used for “ignore” and “only” filters.
- Error
- All the ways in which a test can fail.
- Format
- Possible choices for styling the output.
- Pattern
- An error pattern parsed from a
//~
comment.
Functions§
- bless_
output_ files - Instead of erroring if the stderr/stdout differs from the expected automatically replace it with the found output (after applying filters).
- default_
any_ file_ filter - Run on all files that are specified by
Config::filter_files
andConfig::skip_files
. - default_
file_ filter - The filter used by
run_tests
to only run on.rs
files that are specified byConfig::filter_files
andConfig::skip_files
. - default_
per_ file_ config - The default per-file config used by
run_tests
. - error_
on_ output_ conflict - Fail the test when mismatches are found, if provided the command string
in
Config::bless_command
will be suggested as a way to bless the test. - ignore_
output_ conflict - Ignore mismatches in the stderr/stdout files.
- run_
tests - Run all tests as described in the config argument. Will additionally process command line arguments.
- run_
tests_ generic - A version of
run_tests
that allows more fine-grained control over running tests. - test_
command - Create a command for running a single file, with the settings from the
config
argument. Ignores various settings fromConfig
that relate to finding test files.
Type Aliases§
- Command
Parser Func - Command parser function type.
- Output
Conflict Handling - Function that performs the actual output conflict handling.
- Result
- type alias for
Result<T, Report>