Skip to main content

test_that/
assertions.rs

1// Copyright 2022 Google LLC
2// Copyright 2026 Bradford Hovinen <bradford@hovinen.me>
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16// There are no visible documentation elements in this module; the declarative
17// macros are documented at the top level.
18#![doc(hidden)]
19
20/// Checks whether the `Matcher` given by the second argument matches the first
21/// argument.
22///
23/// Evaluates to `Result::Ok(())` if the matcher matches and
24/// `Result::Err(TestAssertionFailure)` if it does not. The caller must then
25/// decide how to handle the `Err` variant. It has a few options:
26///
27///  * Abort the current function with the `?` operator. This requires that the
28///    function return a suitable `Result`.
29///  * Log the test failure and continue by calling the method
30///    `and_log_failure`.
31///
32/// Of course, one can also use all other standard methods on `Result`.
33///
34/// **Invoking this macro by itself does not cause a test failure to be recorded
35/// or output.** The resulting `Result` must be handled as described above to
36/// cause the test to be recorded as a failure.
37///
38/// Example:
39/// ```
40/// # use test_that::prelude::*;
41/// # fn should_pass() -> TestResult<()> {
42/// verify_that!(42, eq(42))?; // This will pass.
43/// # Ok(())
44/// # }
45/// # should_pass().unwrap();
46/// # fn should_fail() -> TestResult<()> {
47/// # #[cfg(feature = "std")]
48/// # test_that::internal::test_outcome::TestOutcome::init_current_test_outcome();
49/// verify_that!(42, eq(123)).and_log_failure();
50///             // This will log a test failure and allow execution to continue.
51/// let _ = verify_that!(42, eq(123)); // This will do nothing.
52/// verify_that!(42, eq(123))?; // This will fail, returning immediately.
53/// verify_that!(42, eq(0))?; // This will not run.
54/// # #[cfg(feature = "std")]
55/// # { test_that::internal::test_outcome::TestOutcome::close_current_test_outcome::<&str>(Ok(())).unwrap_err(); }
56/// # Ok(())
57/// # }
58/// # verify_that!(should_fail(), err(displays_as(contains_substring("Expected: is equal to 123"))))
59/// #     .unwrap();
60/// ```
61///
62/// This macro has special support for matching against container. Namely:
63///   * `verify_that!(actual, [m1, m2, ...])` is equivalent to
64///     `verify_that!(actual, contains_exactly![m1, m2, ...].in_order())`
65///   * `verify_that!(actual, {m1, m2, ...})` is equivalent to
66///     `verify_that!(actual, contains_exactly![m1, m2, ...])`
67#[macro_export]
68macro_rules! verify_that {
69    ($actual:expr, [$($expecteds:expr),+ $(,)?]) => {
70        $crate::assertions::internal::check_matcher(
71            &$actual,
72            $crate::matchers::containers::contains_exactly![$($expecteds),+].in_order(),
73            stringify!($actual),
74            $crate::internal::source_location::SourceLocation::new(file!(), line!(), column!()),
75        )
76    };
77    ($actual:expr, {$($expecteds:expr),+ $(,)?}) => {
78        $crate::assertions::internal::check_matcher(
79            &$actual,
80            $crate::matchers::containers::contains_exactly![$($expecteds),+],
81            stringify!($actual),
82            $crate::internal::source_location::SourceLocation::new(file!(), line!(), column!()),
83        )
84    };
85    ($actual:expr, $expected:expr $(,)?) => {
86        $crate::assertions::internal::check_matcher(
87            &$actual,
88            $expected,
89            stringify!($actual),
90            $crate::internal::source_location::SourceLocation::new(file!(), line!(), column!()),
91        )
92    };
93}
94
95/// Asserts that the given predicate applied to the given arguments returns
96/// true.
97///
98/// Similarly to [`verify_that`], this evaluates to a `Result` whose `Ok`
99/// variant indicates that the given predicate returned true and whose `Err`
100/// variant indicates that it returned false.
101///
102/// The failure message contains detailed information about the arguments. For
103/// example:
104///
105/// ```
106/// # use test_that::prelude::*;
107/// fn equals_modulo(a: i32, b: i32, n: i32) -> bool { a % n == b % n }
108///
109/// # /* The attribute macro would prevent the function from being compiled in a doctest.
110/// #[test]
111/// # */
112/// fn test() -> TestResult<()> {
113///     let a = 1;
114///     let b = 7;
115///     let n = 5;
116///     verify_pred!(equals_modulo(a, b, n))?;
117///     Ok(())
118/// }
119/// # verify_that!(
120/// #     test(),
121/// #     err(displays_as(contains_substring("equals_modulo(a, b, n) was false with")))
122/// # ).unwrap();
123/// ```
124///
125/// This results in the following message:
126///
127/// ```text
128/// equals_modulo(a, b, n) was false with
129///   a = 1,
130///   b = 7,
131///   n = 5
132/// ```
133///
134/// The function passed to this macro must return `bool`. Each of the arguments
135/// must evaluate to a type implementing [`std::fmt::Debug`]. The debug output
136/// is used to construct the failure message.
137///
138/// The predicate can also be a method on a struct, e.g.:
139///
140/// ```ignore
141/// struct AStruct {};
142///
143/// impl AStruct {
144///   fn equals_modulo(...) {...}
145/// }
146///
147/// verify_pred!((AStruct {}).equals_modulo(a, b, n))?;
148/// ```
149///
150/// **Warning:** This macro assumes that the arguments passed to the predicate
151/// are either *variables* or *calls to pure functions*. If two subsequent
152/// invocations to any of the expresssions passed as arguments result in
153/// different values, then the output message of a test failure will deviate
154/// from the values actually passed to the predicate. For this reason, *always
155/// assign the outputs of non-pure functions to variables before using them in
156/// this macro. For example:
157///
158/// ```ignore
159/// let output = generate_random_number();  // Assigned outside of verify_pred.
160/// verify_pred!(is_sufficiently_random(output))?;
161/// ```
162#[macro_export]
163macro_rules! verify_pred {
164    ([$($predicate:tt)*]($($arg:tt),* $(,)?)) => {
165        if !$($predicate)*($($arg),*) {
166            $crate::assertions::internal::report_failed_predicate(
167                concat!(stringify!($($predicate)*), stringify!(($($arg),*))),
168                $crate::__alloc::vec![$((($crate::__alloc::format!(concat!(stringify!($arg), " = {:?}"), $arg)))),*],
169                $crate::internal::source_location::SourceLocation::new(
170                    file!(),
171                    line!(),
172                    column!(),
173                ),
174            )
175        } else {
176            Ok(())
177        }
178    };
179
180    ([$($predicate:tt)*] $first:tt $($rest:tt)*) => {
181        $crate::verify_pred!([$($predicate)* $first] $($rest)*)
182    };
183
184    ($first:tt $($rest:tt)*) => {
185        $crate::verify_pred!([$first] $($rest)*)
186    };
187}
188
189/// Evaluates to a `Result` which contains an `Err` variant with the given test
190/// failure message.
191///
192/// This can be used to force the test to fail if its execution reaches a
193/// particular point. For example:
194///
195/// ```ignore
196/// match some_value {
197///     ExpectedVariant => {...}
198///     UnwantedVaraint => {
199///         fail!("This thing which should not happen happened anyway")?;
200///     }
201/// }
202/// ```
203///
204/// One may include formatted arguments in the failure message:
205///
206/// ```ignore
207/// match some_value {
208///     ExpectedVariant => {...}
209///     UnwantedVaraint => {
210///         fail!("This thing which should not happen happened anyway: {}", some_value)?;
211///     }
212/// }
213/// ```
214///
215/// One may also omit the message, in which case the test failure message will
216/// be generic:
217///
218/// ```ignore
219/// match some_value {
220///     ExpectedVariant => {...}
221///     UnwantedVaraint => {
222///         fail!()?;
223///     }
224/// }
225/// ```
226///
227/// Unlike `panic!` but analogously to [`verify_that`] and [`verify_pred`], this
228/// macro has no effect on the flow of control but instead returns a `Result`
229/// which must be handled by the invoking function. This can be done with the
230/// question mark operator (as above) or the method
231/// [`and_log_failure`](crate::TestResultExt::and_log_failure).
232#[macro_export]
233macro_rules! fail {
234    ($($message:expr),+) => {{
235        // We wrap this in a function so that we can annotate it with the must_use attribute.
236        // must_use on expressions is still experimental.
237        #[must_use = "The assertion result must be evaluated to affect the test result."]
238        fn create_fail_result(message: $crate::__alloc::string::String) -> $crate::TestResult<()> {
239            Err($crate::internal::test_outcome::TestAssertionFailure::create($crate::__alloc::format!(
240                "{}\n{}",
241                message,
242                $crate::internal::source_location::SourceLocation::new(
243                    file!(),
244                    line!(),
245                    column!(),
246                ),
247            )))
248        }
249        create_fail_result($crate::__alloc::format!($($message),*))
250    }};
251
252    () => { fail!("Test failed") };
253}
254
255/// Matches the given value against the given matcher, panicking if it does not
256/// match.
257///
258/// ```should_panic
259/// # use test_that::prelude::*;
260/// # fn should_fail() {
261/// let value = 2;
262/// assert_that!(value, eq(3));  // Fails and panics.
263/// # }
264/// # should_fail();
265/// ```
266///
267/// This is analogous to assertions in most Rust test libraries, where a failed
268/// assertion causes a panic.
269///
270/// One may optionally add arguments which will be formatted and appended to a
271/// failure message. For example:
272///
273/// ```should_panic
274/// # use test_that::prelude::*;
275/// # fn should_fail() {
276/// let value = 2;
277/// let extra_information = "Some additional information";
278/// assert_that!(value, eq(3), "Test failed. Extra information: {extra_information}.");
279/// # }
280/// # should_fail();
281/// ```
282///
283/// This is output as follows:
284///
285/// ```text
286/// Value of: value
287/// Expected: is equal to 3
288/// Actual: 2,
289///   which isn't equal to 3
290///   at ...
291/// Test failed. Extra information: Some additional information.
292/// ```
293///
294/// **Note for users of [GoogleTest for C++](http://google.github.io/googletest/):**
295/// This differs from the `ASSERT_THAT` macro in that it panics rather
296/// than triggering an early return from the invoking function. To get behaviour
297/// equivalent to `ASSERT_THAT`, use [`verify_that!`] with the `?` operator.
298#[macro_export]
299macro_rules! assert_that {
300    ($actual:expr, $expected:expr $(,)?) => {
301        match $crate::verify_that!($actual, $expected) {
302            Ok(_) => {}
303            Err(e) => {
304                // The extra newline before the assertion failure message makes the failure a
305                // bit easier to read when there's some generic boilerplate from the panic.
306                panic!("\n{}", e);
307            }
308        }
309    };
310
311    ($actual:expr, $expected:expr, $($format_args:expr),* $(,)?) => {
312        match $crate::verify_that!($actual, $expected)
313            .with_failure_message(|| format!($($format_args),*))
314        {
315            Ok(_) => {}
316            Err(e) => {
317                // The extra newline before the assertion failure message makes the failure a
318                // bit easier to read when there's some generic boilerplate from the panic.
319                panic!("\n{}", e);
320            }
321        }
322    };
323}
324
325/// Asserts that the given predicate applied to the given arguments returns
326/// true, panicking if it does not.
327///
328/// **Note for users of [GoogleTest for C++](http://google.github.io/googletest/):**
329/// This differs from the `ASSERT_PRED*` family of macros in that it panics
330/// rather than triggering an early return from the invoking function. To get
331/// behaviour equivalent to `ASSERT_PRED*`, use [`verify_pred!`] with the `?`
332/// operator.
333#[macro_export]
334macro_rules! assert_pred {
335    ($($content:tt)*) => {
336        match $crate::verify_pred!($($content)*) {
337            Ok(_) => {}
338            Err(e) => {
339                // The extra newline before the assertion failure message makes the failure a
340                // bit easier to read when there's some generic boilerplate from the panic.
341                panic!("\n{}", e);
342            }
343        }
344    };
345}
346
347/// Matches the given value against the given matcher, marking the test as
348/// failed but continuing execution if it does not match.
349///
350/// This is a *non-fatal* assertion: the test continues
351/// execution in the event of assertion failure.
352///
353/// This can only be invoked inside tests with the
354/// [`test_that::test`][crate::test] attribute. The assertion must
355/// occur in the same thread as that running the test itself.
356///
357/// Invoking this macro is equivalent to using
358/// [`and_log_failure`](crate::TestResultExt::and_log_failure) as follows:
359///
360/// ```ignore
361/// verify_that!(actual, expected).and_log_failure()
362/// ```
363///
364/// One may optionally add arguments which will be formatted and appended to a
365/// failure message. For example:
366///
367/// ```
368/// # use test_that::prelude::*;
369/// # fn should_fail() -> std::result::Result<(), test_that::internal::test_outcome::TestFailure> {
370/// # test_that::internal::test_outcome::TestOutcome::init_current_test_outcome();
371/// let value = 2;
372/// let extra_information = "Some additional information";
373/// expect_that!(value, eq(3), "Test failed. Extra information: {extra_information}.");
374/// # test_that::internal::test_outcome::TestOutcome::close_current_test_outcome::<&str>(Ok(()))
375/// # }
376/// # should_fail().unwrap_err();
377/// ```
378///
379/// This is output as follows:
380///
381/// ```text
382/// Value of: value
383/// Expected: is equal to 3
384/// Actual: 2,
385///   which isn't equal to 3
386///   at ...
387/// Test failed. Extra information: Some additional information.
388/// ```
389#[cfg(feature = "non-fatal-assertions")]
390#[macro_export]
391macro_rules! expect_that {
392    ($actual:expr, $expected:expr $(,)?) => {{
393        use $crate::TestResultExt;
394        $crate::verify_that!($actual, $expected).and_log_failure();
395    }};
396
397    ($actual:expr, $expected:expr, $($format_args:expr),* $(,)?) => {
398        $crate::verify_that!($actual, $expected)
399            .with_failure_message(|| format!($($format_args),*))
400            .and_log_failure()
401    };
402}
403
404/// Asserts that the given predicate applied to the given arguments returns
405/// true, failing the test but continuing execution if not.
406///
407/// This is a *non-fatal* predicate assertion: the test
408/// continues execution in the event of assertion failure.
409///
410/// This can only be invoked inside tests with the
411/// [`test_that::test`][crate::test] attribute. The assertion must
412/// occur in the same thread as that running the test itself.
413///
414/// Invoking this macro is equivalent to using
415/// [`and_log_failure`](crate::TestResultExt::and_log_failure) as follows:
416///
417/// ```ignore
418/// verify_pred!(predicate(...)).and_log_failure()
419/// ```
420#[cfg(feature = "non-fatal-assertions")]
421#[macro_export]
422macro_rules! expect_pred {
423    ($($content:tt)*) => {{
424        use $crate::TestResultExt;
425        $crate::verify_pred!($($content)*).and_log_failure();
426    }};
427}
428
429/// Functions for use only by the procedural macros in this module.
430///
431/// **For internal use only. API stablility is not guaranteed!**
432#[doc(hidden)]
433pub mod internal {
434    use crate::{
435        internal::{source_location::SourceLocation, test_outcome::TestAssertionFailure},
436        matcher::{Matcher, MatcherResult, create_assertion_failure},
437    };
438    use core::fmt::Debug;
439
440    /// Checks whether the matcher `expected` matches the value `actual`, adding
441    /// a test failure report if it does not match.
442    ///
443    /// Returns `Ok(())` if the value matches and `Err(())` if it does not
444    /// match.
445    ///
446    /// **For internal use only. API stablility is not guaranteed!**
447    #[must_use = "The assertion result must be evaluated to affect the test result."]
448    pub fn check_matcher<T: Debug + ?Sized>(
449        actual: &T,
450        expected: impl Matcher<T>,
451        actual_expr: &'static str,
452        source_location: SourceLocation,
453    ) -> Result<(), TestAssertionFailure> {
454        match expected.matches(actual) {
455            MatcherResult::Match => Ok(()),
456            MatcherResult::NoMatch => {
457                Err(create_assertion_failure(&expected, actual, actual_expr, source_location))
458            }
459        }
460    }
461
462    /// Constructs a `Result::Err(TestAssertionFailure)` for a predicate failure
463    /// as produced by the macro [`crate::verify_pred`].
464    ///
465    /// This intended only for use by the macro [`crate::verify_pred`].
466    ///
467    /// **For internal use only. API stablility is not guaranteed!**
468    #[must_use = "The assertion result must be evaluated to affect the test result."]
469    pub fn report_failed_predicate(
470        actual_expr: &'static str,
471        formatted_arguments: alloc::vec::Vec<alloc::string::String>,
472        source_location: SourceLocation,
473    ) -> Result<(), TestAssertionFailure> {
474        Err(TestAssertionFailure::create(alloc::format!(
475            "{} was false with\n  {}\n{}",
476            actual_expr,
477            formatted_arguments.join(",\n  "),
478            source_location,
479        )))
480    }
481}