| r[attributes.testing] |
| # Testing attributes |
| |
| The following [attributes] are used for specifying functions for performing |
| tests. Compiling a crate in "test" mode enables building the test functions |
| along with a test harness for executing the tests. Enabling the test mode also |
| enables the [`test` conditional compilation option]. |
| |
| <!-- template:attributes --> |
| r[attributes.testing.test] |
| ## The `test` attribute |
| |
| r[attributes.testing.test.intro] |
| The *`test` [attribute][attributes]* marks a function to be executed as a test. |
| |
| > [!EXAMPLE] |
| > ```rust,no_run |
| > # pub fn add(left: u64, right: u64) -> u64 { left + right } |
| > #[test] |
| > fn it_works() { |
| > let result = add(2, 2); |
| > assert_eq!(result, 4); |
| > } |
| > ``` |
| |
| r[attributes.testing.test.syntax] |
| The `test` attribute uses the [MetaWord] syntax. |
| |
| r[attributes.testing.test.allowed-positions] |
| The `test` attribute may only be applied to [free functions] that are monomorphic, that take no arguments, and where the return type implements the [`Termination`] trait. |
| |
| > [!NOTE] |
| > Some of types that implement the [`Termination`] trait include: |
| > * `()` |
| > * `Result<T, E> where T: Termination, E: Debug` |
| |
| r[attributes.testing.test.duplicates] |
| Only the first use of `test` on a function has effect. |
| |
| > [!NOTE] |
| > `rustc` lints against any use following the first. This may become an error in the future. |
| |
| <!-- TODO: This is a minor lie. Currently rustc warns that duplicates are ignored, but it then generates multiple test entries with the same name. I would vote for rejecting this in the future. --> |
| |
| r[attributes.testing.test.stdlib] |
| The `test` attribute is exported from the standard library prelude as [`std::prelude::v1::test`]. |
| |
| r[attributes.testing.test.enabled] |
| These functions are only compiled when in test mode. |
| |
| > [!NOTE] |
| > The test mode is enabled by passing the `--test` argument to `rustc` or using `cargo test`. |
| |
| r[attributes.testing.test.success] |
| The test harness calls the returned value's [`report`] method, and classifies the test as passed or failed depending on whether the resulting [`ExitCode`] represents successful termination. |
| In particular: |
| * Tests that return `()` pass as long as they terminate and do not panic. |
| * Tests that return a `Result<(), E>` pass as long as they return `Ok(())`. |
| * Tests that return `ExitCode::SUCCESS` pass, and tests that return `ExitCode::FAILURE` fail. |
| * Tests that do not terminate neither pass nor fail. |
| |
| > [!EXAMPLE] |
| > ```rust,no_run |
| > # use std::io; |
| > # fn setup_the_thing() -> io::Result<i32> { Ok(1) } |
| > # fn do_the_thing(s: &i32) -> io::Result<()> { Ok(()) } |
| > #[test] |
| > fn test_the_thing() -> io::Result<()> { |
| > let state = setup_the_thing()?; // expected to succeed |
| > do_the_thing(&state)?; // expected to succeed |
| > Ok(()) |
| > } |
| > ``` |
| |
| <!-- template:attributes --> |
| r[attributes.testing.ignore] |
| ## The `ignore` attribute |
| |
| r[attributes.testing.ignore.intro] |
| The *`ignore` [attribute][attributes]* can be used with the [`test` attribute][attributes.testing.test] to tell the test harness to not execute that function as a test. |
| |
| > [!EXAMPLE] |
| > ```rust,no_run |
| > #[test] |
| > #[ignore] |
| > fn check_thing() { |
| > // … |
| > } |
| > ``` |
| |
| > [!NOTE] |
| > The `rustc` test harness supports the `--include-ignored` flag to force ignored tests to be run. |
| |
| r[attributes.testing.ignore.syntax] |
| The `ignore` attribute uses the [MetaWord] and [MetaNameValueStr] syntaxes. |
| |
| r[attributes.testing.ignore.reason] |
| The [MetaNameValueStr] form of the `ignore` attribute provides a way to specify a reason why the test is ignored. |
| |
| > [!EXAMPLE] |
| > ```rust,no_run |
| > #[test] |
| > #[ignore = "not yet implemented"] |
| > fn mytest() { |
| > // … |
| > } |
| > ``` |
| |
| r[attributes.testing.ignore.allowed-positions] |
| The `ignore` attribute may only be applied to functions annotated with the `test` attribute. |
| |
| > [!NOTE] |
| > `rustc` ignores use in other positions but lints against it. This may become an error in the future. |
| |
| r[attributes.testing.ignore.duplicates] |
| Only the first use of `ignore` on a function has effect. |
| |
| > [!NOTE] |
| > `rustc` lints against any use following the first. This may become an error in the future. |
| |
| r[attributes.testing.ignore.behavior] |
| Ignored tests are still compiled when in test mode, but they are not executed. |
| |
| <!-- template:attributes --> |
| r[attributes.testing.should_panic] |
| ## The `should_panic` attribute |
| |
| r[attributes.testing.should_panic.intro] |
| The *`should_panic` [attribute][attributes]* causes a test to pass only if the [test function][attributes.testing.test] to which the attribute is applied panics. |
| |
| > [!EXAMPLE] |
| > ```rust,no_run |
| > #[test] |
| > #[should_panic(expected = "values don't match")] |
| > fn mytest() { |
| > assert_eq!(1, 2, "values don't match"); |
| > } |
| > ``` |
| |
| r[attributes.testing.should_panic.syntax] |
| The `should_panic` attribute has these forms: |
| |
| - [MetaWord] |
| > [!EXAMPLE] |
| > ```rust,no_run |
| > #[test] |
| > #[should_panic] |
| > fn mytest() { panic!("error: some message, and more"); } |
| > ``` |
| |
| - [MetaNameValueStr] --- The given string must appear within the panic message for the test to pass. |
| > [!EXAMPLE] |
| > ```rust,no_run |
| > #[test] |
| > #[should_panic = "some message"] |
| > fn mytest() { panic!("error: some message, and more"); } |
| > ``` |
| |
| - [MetaListNameValueStr] --- As with the [MetaNameValueStr] syntax, the given string must appear within the panic message. |
| > [!EXAMPLE] |
| > ```rust,no_run |
| > #[test] |
| > #[should_panic(expected = "some message")] |
| > fn mytest() { panic!("error: some message, and more"); } |
| > ``` |
| |
| r[attributes.testing.should_panic.allowed-positions] |
| The `should_panic` attribute may only be applied to functions annotated with the `test` attribute. |
| |
| > [!NOTE] |
| > `rustc` ignores use in other positions but lints against it. This may become an error in the future. |
| |
| r[attributes.testing.should_panic.duplicates] |
| Only the first use of `should_panic` on a function has effect. |
| |
| > [!NOTE] |
| > `rustc` lints against any use following the first with a future-compatibility warning. This may become an error in the future. |
| |
| r[attributes.testing.should_panic.expected] |
| When the [MetaNameValueStr] form or the [MetaListNameValueStr] form with the `expected` key is used, the given string must appear somewhere within the panic message for the test to pass. |
| |
| r[attributes.testing.should_panic.return] |
| The return type of the test function must be `()`. |
| |
| [`Termination`]: std::process::Termination |
| [`report`]: std::process::Termination::report |
| [`test` conditional compilation option]: ../conditional-compilation.md#test |
| [attributes]: ../attributes.md |
| [`ExitCode`]: std::process::ExitCode |
| [free functions]: ../glossary.md#free-item |