Skip to content

Commit 5d3724c

Browse files
Merge pull request #345 from google:support-should-panic
PiperOrigin-RevId: 597575847
2 parents 8631e93 + 0017a85 commit 5d3724c

File tree

5 files changed

+103
-2
lines changed

5 files changed

+103
-2
lines changed

googletest_macro/src/lib.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,32 @@ use syn::{parse_macro_input, Attribute, ItemFn, ReturnType};
4040
/// }
4141
/// ```
4242
///
43+
/// This macro can be used with `#[should_panic]` to indicate that the test is
44+
/// expected to panic. For example:
45+
///
46+
/// ```ignore
47+
/// #[googletest::test]
48+
/// #[should_panic]
49+
/// fn passes_due_to_should_panic() {
50+
/// let value = 2;
51+
/// expect_that!(value, gt(0));
52+
/// panic!("This panics");
53+
/// }
54+
/// ```
55+
///
56+
/// Using `#[should_panic]` modifies the behaviour of `#[googletest::test]` so
57+
/// that the test panics (and passes) if any non-fatal assertion occurs.
58+
/// For example, the following test passes:
59+
///
60+
/// ```ignore
61+
/// #[googletest::test]
62+
/// #[should_panic]
63+
/// fn passes_due_to_should_panic_and_failing_assertion() {
64+
/// let value = 2;
65+
/// expect_that!(value, eq(0));
66+
/// }
67+
/// ```
68+
///
4369
/// [`googletest::Result`]: type.Result.html
4470
#[proc_macro_attribute]
4571
pub fn test(
@@ -49,6 +75,15 @@ pub fn test(
4975
let mut parsed_fn = parse_macro_input!(input as ItemFn);
5076
let attrs = parsed_fn.attrs.drain(..).collect::<Vec<_>>();
5177
let (mut sig, block) = (parsed_fn.sig, parsed_fn.block);
78+
let (outer_return_type, trailer) =
79+
if attrs.iter().any(|attr| attr.path().is_ident("should_panic")) {
80+
(quote! { () }, quote! { .unwrap(); })
81+
} else {
82+
(
83+
quote! { std::result::Result<(), googletest::internal::test_outcome::TestFailure> },
84+
quote! {},
85+
)
86+
};
5287
let output_type = match sig.output.clone() {
5388
ReturnType::Type(_, output_type) => Some(output_type),
5489
ReturnType::Default => None,
@@ -81,23 +116,25 @@ pub fn test(
81116
let function = if let Some(output_type) = output_type {
82117
quote! {
83118
#(#attrs)*
84-
#sig -> std::result::Result<(), googletest::internal::test_outcome::TestFailure> {
119+
#sig -> #outer_return_type {
85120
#maybe_closure
86121
use googletest::internal::test_outcome::TestOutcome;
87122
TestOutcome::init_current_test_outcome();
88123
let result: #output_type = #invocation;
89124
TestOutcome::close_current_test_outcome(result)
125+
#trailer
90126
}
91127
}
92128
} else {
93129
quote! {
94130
#(#attrs)*
95-
#sig -> std::result::Result<(), googletest::internal::test_outcome::TestFailure> {
131+
#sig -> #outer_return_type {
96132
#maybe_closure
97133
use googletest::internal::test_outcome::TestOutcome;
98134
TestOutcome::init_current_test_outcome();
99135
#invocation;
100136
TestOutcome::close_current_test_outcome(googletest::Result::Ok(()))
137+
#trailer
101138
}
102139
}
103140
};

integration_tests/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ name = "non_fatal_failure_in_subroutine"
115115
path = "src/non_fatal_failure_in_subroutine.rs"
116116
test = false
117117

118+
[[bin]]
119+
name = "passing_test_with_should_panic"
120+
path = "src/passing_test_with_should_panic.rs"
121+
test = false
122+
118123
[[bin]]
119124
name = "simple_assertion_failure"
120125
path = "src/simple_assertion_failure.rs"

integration_tests/src/integration_tests.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,38 @@ mod tests {
695695
Ok(())
696696
}
697697

698+
#[googletest::test]
699+
#[should_panic]
700+
fn should_pass_with_should_panic() {
701+
expect_that!(2, eq(4));
702+
}
703+
704+
#[googletest::test]
705+
#[should_panic(expected = "See failure output above")]
706+
fn should_pass_with_should_panic_with_expectation() {
707+
expect_that!(2, eq(4));
708+
}
709+
710+
#[should_panic]
711+
#[googletest::test]
712+
fn should_pass_with_should_panic_in_first_position() {
713+
expect_that!(2, eq(4));
714+
}
715+
716+
#[googletest::test]
717+
#[should_panic]
718+
fn should_pass_with_should_panic_and_verify_that() -> Result<()> {
719+
verify_that!(2, eq(4))?;
720+
verify_that!(3, eq(3))
721+
}
722+
723+
#[test]
724+
fn should_fail_when_should_panic_is_present_and_no_panic_occurs() -> Result<()> {
725+
let output = run_external_process_in_tests_directory("passing_test_with_should_panic")?;
726+
727+
verify_that!(output, contains_substring("should panic"))
728+
}
729+
698730
#[::core::prelude::v1::test]
699731
#[should_panic]
700732
fn should_panic_when_expect_that_runs_without_attribute_macro_after_another_test() {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2024 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
fn main() {}
16+
17+
#[cfg(test)]
18+
mod tests {
19+
use googletest::prelude::*;
20+
21+
#[googletest::test]
22+
#[should_panic]
23+
fn passes_but_fails_due_to_should_panic() {
24+
expect_that!(2, eq(2));
25+
}
26+
}

run_integration_tests.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ INTEGRATION_TEST_BINARIES=(
3939
"first_failure_aborts"
4040
"google_test_with_rstest"
4141
"non_fatal_failure_in_subroutine"
42+
"passing_test_with_should_panic"
4243
"simple_assertion_failure"
4344
"simple_assertion_failure_with_assert_that"
4445
"test_returning_anyhow_error"

0 commit comments

Comments
 (0)