Skip to content

Commit d9c63a2

Browse files
hovinenbcopybara-github
authored andcommitted
Improve the output of actual value in test assertion failures.
This makes two changes: * If the total length of the (non-pretty-printed) debug output of the actual value is less than 60, then the non-pretty-printed output is used. Otherwise, the output is pretty-printed as before. This means that short, structured values like `Some(123)` will no longer be printed with newlines. This should reduce visual clutter and make the actual values easier to read. * The match explanation is now separated from the actual value by a newline and is indented. This visually separates the explanation from the actual value, making it easier to distinguish the two. To support this visual separation, it was also necessary to enhance `Description` to support indenting all but the first line. Otherwise, the `all` matcher would have output multiple entries with the first one indented extra spaces like this: ``` Actual: [1, 2, 3], * First explanation * Second explanation * Third explanation ``` I replaced the boolean field `indented` with a enum representing the indentation mode and cleaned a few things up in the implementation along the way. This also increases the use of indoc throughout the unit tests, making them easier to read. PiperOrigin-RevId: 532034798
1 parent 1870887 commit d9c63a2

31 files changed

+483
-360
lines changed

googletest/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ name = "assertion_failure_in_subroutine"
5858
path = "integration_tests/assertion_failure_in_subroutine.rs"
5959
test = false
6060

61+
[[bin]]
62+
name = "assertion_failures_with_short_structured_actual_values"
63+
path = "integration_tests/assertion_failures_with_short_structured_actual_values.rs"
64+
test = false
65+
6166
[[bin]]
6267
name = "async_test_with_expect_that"
6368
path = "integration_tests/async_test_with_expect_that.rs"
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2023 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+
#[test]
22+
fn should_fail_with_option_value() -> Result<()> {
23+
verify_that!(Some(1), some(eq(2)))
24+
}
25+
26+
#[test]
27+
fn should_fail_with_result_ok_value() -> Result<()> {
28+
let value: std::result::Result<i32, ()> = Ok(1);
29+
verify_that!(value, ok(eq(2)))
30+
}
31+
32+
#[test]
33+
fn should_fail_with_result_err_value() -> Result<()> {
34+
let value: std::result::Result<(), i32> = Err(1);
35+
verify_that!(value, err(eq(2)))
36+
}
37+
}

googletest/integration_tests/integration_tests.rs

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ mod tests {
7676
contains_regex(indoc! {"
7777
Value of: value
7878
Expected: is equal to 3
79-
Actual: 2, which isn't equal to 3
79+
Actual: 2,
80+
which isn't equal to 3
8081
at .*googletest/integration_tests/simple_assertion_failure.rs:[0-9]+:9"})
8182
)
8283
}
@@ -91,7 +92,8 @@ mod tests {
9192
contains_regex(indoc! {"
9293
Value of: value
9394
Expected: is equal to 3
94-
Actual: 2, which isn't equal to 3
95+
Actual: 2,
96+
which isn't equal to 3
9597
at .*googletest/integration_tests/simple_assertion_failure_with_assert_that.rs:[0-9]+:9
9698
"})
9799
)
@@ -106,7 +108,8 @@ mod tests {
106108
contains_regex(indoc! {"
107109
Value of: value
108110
Expected: is equal to 3
109-
Actual: 2, which isn't equal to 3
111+
Actual: 2,
112+
which isn't equal to 3
110113
at .*googletest/integration_tests/expect_that_failure.rs:[0-9]+:9
111114
"})
112115
)
@@ -122,12 +125,49 @@ mod tests {
122125
contains_regex(indoc! {"
123126
Value of: value
124127
Expected: is equal to 4
125-
Actual: 2, which isn't equal to 4
128+
Actual: 2,
129+
which isn't equal to 4
126130
at .*googletest/integration_tests/two_expect_that_failures.rs:[0-9]+:9
127131
"})
128132
)
129133
}
130134

135+
#[googletest::test]
136+
fn should_output_failure_message_with_simple_structured_value() -> Result<()> {
137+
let output = run_external_process_in_tests_directory(
138+
"assertion_failures_with_short_structured_actual_values",
139+
)?;
140+
141+
expect_that!(
142+
output,
143+
contains_substring(indoc! {"
144+
Value of: Some(1)
145+
Expected: has a value which is equal to 2
146+
Actual: Some(1),
147+
which has a value which isn't equal to 2
148+
"})
149+
);
150+
expect_that!(
151+
output,
152+
contains_substring(indoc! {"
153+
Value of: value
154+
Expected: is a success containing a value, which is equal to 2
155+
Actual: Ok(1),
156+
which is a success which isn't equal to 2
157+
"})
158+
);
159+
expect_that!(
160+
output,
161+
contains_substring(indoc! {"
162+
Value of: value
163+
Expected: is an error which is equal to 2
164+
Actual: Err(1),
165+
which is an error which isn't equal to 2
166+
"})
167+
);
168+
Ok(())
169+
}
170+
131171
#[test]
132172
fn should_fail_due_to_assertion_failure_in_subroutine() -> Result<()> {
133173
let status = run_external_process("simple_assertion_failure").status()?;
@@ -158,11 +198,13 @@ mod tests {
158198
all!(
159199
contains_substring(indoc! {"
160200
Expected: is equal to 3
161-
Actual: 2, which isn't equal to 3
201+
Actual: 2,
202+
which isn't equal to 3
162203
"}),
163204
contains_substring(indoc! {"
164205
Expected: is equal to 4
165-
Actual: 2, which isn't equal to 4
206+
Actual: 2,
207+
which isn't equal to 4
166208
"})
167209
)
168210
)
@@ -176,7 +218,8 @@ mod tests {
176218
output,
177219
not(contains_substring(indoc! {"
178220
Expected: is equal to 4
179-
Actual: 2, which isn't equal to 4
221+
Actual: 2,
222+
which isn't equal to 4
180223
"}))
181224
)
182225
}
@@ -189,7 +232,8 @@ mod tests {
189232
output,
190233
contains_substring(indoc! {"
191234
Expected: is equal to 3
192-
Actual: 2, which isn't equal to 3
235+
Actual: 2,
236+
which isn't equal to 3
193237
"})
194238
)
195239
}
@@ -424,7 +468,8 @@ mod tests {
424468
contains_substring(indoc! {"
425469
Value of: 1
426470
Expected: is equal to 2
427-
Actual: 1, which isn't equal to 2
471+
Actual: 1,
472+
which isn't equal to 2
428473
"})
429474
)
430475
}
@@ -435,23 +480,23 @@ mod tests {
435480
}
436481

437482
#[test]
438-
fn failure_message_uses_pretty_print_for_actual_value() -> Result<()> {
483+
fn failure_message_uses_pretty_print_for_actual_value_when_long_enough() -> Result<()> {
439484
#[derive(Debug)]
440485
#[allow(unused)]
441486
struct NontrivialStruct {
442-
a: i32,
443-
b: i32,
487+
a: &'static str,
488+
b: &'static str,
444489
}
445-
let value = NontrivialStruct { a: 1, b: 2 };
490+
let value = NontrivialStruct { a: "A long enough string", b: "Another long enough string" };
446491
let failed_assertion_result = verify_that!(value, not(anything()));
447492

448493
verify_that!(
449494
failed_assertion_result,
450-
err(displays_as(contains_substring(indoc! {"
495+
err(displays_as(contains_substring(indoc! {r#"
451496
Actual: NontrivialStruct {
452-
a: 1,
453-
b: 2,
454-
}"})))
497+
a: "A long enough string",
498+
b: "Another long enough string",
499+
}"#})))
455500
)
456501
}
457502

googletest/src/matcher.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,10 @@ pub trait Matcher {
197197
}
198198
}
199199

200+
/// Any actual value whose debug length is greater than this value will be
201+
/// pretty-printed. Otherwise, it will have normal debug output formatting.
202+
const PRETTY_PRINT_LENGTH_THRESHOLD: usize = 60;
203+
200204
/// Constructs a [`TestAssertionFailure`] reporting that the given `matcher`
201205
/// does not match the value `actual`.
202206
///
@@ -208,16 +212,21 @@ pub(crate) fn create_assertion_failure<T: Debug + ?Sized>(
208212
actual_expr: &'static str,
209213
source_location: SourceLocation,
210214
) -> TestAssertionFailure {
215+
let actual_formatted = format!("{actual:?}");
216+
let actual_formatted = if actual_formatted.len() > PRETTY_PRINT_LENGTH_THRESHOLD {
217+
format!("{actual:#?}")
218+
} else {
219+
actual_formatted
220+
};
211221
TestAssertionFailure::create(format!(
212-
"Value of: {}\n\
213-
Expected: {}\n\
214-
Actual: {:#?}, {}\n\
215-
{}",
216-
actual_expr,
222+
"\
223+
Value of: {actual_expr}
224+
Expected: {}
225+
Actual: {actual_formatted},
226+
{}
227+
{source_location}",
217228
matcher.describe(MatcherResult::Matches),
218-
actual,
219229
matcher.explain_match(actual),
220-
source_location,
221230
))
222231
}
223232

0 commit comments

Comments
 (0)