From 978f6d1811440ab9f3936cebba53e05b2a42499e Mon Sep 17 00:00:00 2001 From: Bradford Hovinen Date: Fri, 21 Jul 2023 11:15:41 +0200 Subject: [PATCH] Introduce a function `verify_current_test_outcome`. This allows a test to check whether the current test has passed or failed based on non-fatal assertions such as `expect_that!`. Its naming follows the pattern of `verify_that!` since it uses the same idiom of returning a `googletest::Result`. --- googletest/src/internal/test_outcome.rs | 14 ++++++++++ googletest/src/lib.rs | 34 +++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/googletest/src/internal/test_outcome.rs b/googletest/src/internal/test_outcome.rs index 52a1d4bc..2171cc7b 100644 --- a/googletest/src/internal/test_outcome.rs +++ b/googletest/src/internal/test_outcome.rs @@ -84,6 +84,20 @@ impl TestOutcome { }) } + /// Returns a `Result` corresponding to the outcome of the currently running + /// test. + pub(crate) fn get_current_test_outcome() -> Result<(), TestAssertionFailure> { + TestOutcome::with_current_test_outcome(|mut outcome| { + let outcome = outcome + .as_mut() + .expect("No test context found. This indicates a bug in GoogleTest."); + match outcome { + TestOutcome::Success => Ok(()), + TestOutcome::Failure => Err(TestAssertionFailure::create("Test failed".into())), + } + }) + } + /// Records that the currently running test has failed. fn fail_current_test() { TestOutcome::with_current_test_outcome(|mut outcome| { diff --git a/googletest/src/lib.rs b/googletest/src/lib.rs index 0d76f11d..42f1e39c 100644 --- a/googletest/src/lib.rs +++ b/googletest/src/lib.rs @@ -43,6 +43,7 @@ pub mod matchers; pub mod prelude { pub use super::matcher::Matcher; pub use super::matchers::*; + pub use super::verify_current_test_outcome; pub use super::GoogleTestSupport; pub use super::IntoTestResult; pub use super::Result; @@ -83,6 +84,39 @@ use internal::test_outcome::{TestAssertionFailure, TestOutcome}; /// failed but allow it to continue running, are not encoded in this type. pub type Result = std::result::Result; +/// Returns a [`Result`] corresponding to the outcome of the currently running +/// test. +/// +/// This returns `Result::Err` precisely if the current test has recorded at +/// least one test assertion failure via [`expect_that!`][crate::expect_that], +/// [`expect_pred!`][crate::expect_pred], or +/// [`GoogleTestSupport::and_log_failure`]. It can be used in concert with the +/// `?` operator to continue execution of the test conditionally on there not +/// having been any failure yet. +/// +/// This requires the use of the [`#[googletest::test]`][crate::test] attribute +/// macro. +/// +/// ``` +/// # use googletest::prelude::*; +/// # /* Make sure this also compiles as a doctest. +/// #[googletest::test] +/// # */ +/// # fn foo() -> u32 { 1 } +/// # fn bar() -> u32 { 2 } +/// fn should_fail_and_not_execute_last_assertion() -> Result<()> { +/// # googletest::internal::test_outcome::TestOutcome::init_current_test_outcome(); +/// expect_that!(foo(), eq(2)); // May fail, but will not abort the test. +/// expect_that!(bar(), gt(1)); // May fail, but will not abort the test. +/// verify_current_test_outcome()?; // Aborts the test if one of the previous assertions failed. +/// verify_that!(foo(), gt(0)) // Does not execute. +/// } +/// # verify_that!(should_fail_and_not_execute_last_assertion(), err(displays_as(contains_substring("Test failed")))).unwrap(); +/// ``` +pub fn verify_current_test_outcome() -> Result<()> { + TestOutcome::get_current_test_outcome() +} + /// Adds to `Result` support for GoogleTest Rust functionality. pub trait GoogleTestSupport { /// If `self` is a `Result::Err`, writes to `stdout` a failure report