1A rich test assertion library for Rust. 2 3This library provides: 4 5 * A framework for writing matchers which can be combined to make a wide 6 range of assertions on data, 7 * A rich set of matchers, and 8 * A new set of test assertion macros. 9 10## Assertions and matchers 11 12The core of GoogleTest is its *matchers*. Matchers indicate what aspect of an 13actual value one is asserting: (in-)equality, containment, regular expression 14matching, and so on. 15 16To make an assertion using a matcher, GoogleTest offers three macros: 17 18 * [`assert_that!`] panics if the assertion fails, aborting the test. 19 * [`expect_that!`] logs an assertion failure, marking the test as having 20 failed, but allows the test to continue running (called a _non-fatal 21 assertion_). It requires the use of the [`googletest::test`][crate::test] 22 attribute macro on the test itself. 23 * [`verify_that!`] has no side effects and evaluates to a [`Result`] whose 24 `Err` variant describes the assertion failure, if there is one. In 25 combination with the 26 [`?` operator](https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator), 27 this can be used to abort the test on assertion failure without panicking. It 28 is also the building block for the other two macros above. 29 30For example: 31 32``` 33use googletest::prelude::*; 34 35# /* The attribute macro would prevent the function from being compiled in a doctest. 36#[test] 37# */ 38fn fails_and_panics() { 39 let value = 2; 40 assert_that!(value, eq(4)); 41} 42 43# /* The attribute macro would prevent the function from being compiled in a doctest. 44#[googletest::test] 45# */ 46fn two_logged_failures() { 47 let value = 2; 48 expect_that!(value, eq(4)); // Test now failed, but continues executing. 49 expect_that!(value, eq(5)); // Second failure is also logged. 50} 51 52# /* The attribute macro would prevent the function from being compiled in a doctest. 53#[test] 54# */ 55fn fails_immediately_without_panic() -> Result<()> { 56 let value = 2; 57 verify_that!(value, eq(4))?; // Test fails and aborts. 58 verify_that!(value, eq(2))?; // Never executes. 59 Ok(()) 60} 61 62# /* The attribute macro would prevent the function from being compiled in a doctest. 63#[test] 64# */ 65fn simple_assertion() -> Result<()> { 66 let value = 2; 67 verify_that!(value, eq(4)) // One can also just return the last assertion. 68} 69``` 70 71Matchers are composable: 72 73``` 74use googletest::prelude::*; 75 76# /* The attribute macro would prevent the function from being compiled in a doctest. 77#[googletest::test] 78# */ 79fn contains_at_least_one_item_at_least_3() { 80# googletest::internal::test_outcome::TestOutcome::init_current_test_outcome(); 81 let value = vec![1, 2, 3]; 82 expect_that!(value, contains(ge(3))); 83# googletest::internal::test_outcome::TestOutcome::close_current_test_outcome::<&str>(Ok(())) 84# .unwrap(); 85} 86# contains_at_least_one_item_at_least_3(); 87``` 88 89They can also be logically combined: 90 91``` 92use googletest::prelude::*; 93 94# /* The attribute macro would prevent the function from being compiled in a doctest. 95#[googletest::test] 96# */ 97fn strictly_between_9_and_11() { 98# googletest::internal::test_outcome::TestOutcome::init_current_test_outcome(); 99 let value = 10; 100 expect_that!(value, gt(9).and(not(ge(11)))); 101# googletest::internal::test_outcome::TestOutcome::close_current_test_outcome::<&str>(Ok(())) 102# .unwrap(); 103} 104# strictly_between_9_and_11(); 105``` 106 107## Available matchers 108 109The following matchers are provided in GoogleTest Rust: 110 111| Matcher | What it matches | 112|----------------------|--------------------------------------------------------------------------| 113| [`all!`] | Anything matched by all given matchers. | 114| [`any!`] | Anything matched by at least one of the given matchers. | 115| [`anything`] | Any input. | 116| [`approx_eq`] | A floating point number within a standard tolerance of the argument. | 117| [`char_count`] | A string with a Unicode scalar count matching the argument. | 118| [`container_eq`] | Same as [`eq`], but for containers (with a better mismatch description). | 119| [`contains`] | A container containing an element matched by the given matcher. | 120| [`contains_each!`] | A container containing distinct elements each of the arguments match. | 121| [`contains_regex`] | A string containing a substring matching the given regular expression. | 122| [`contains_substring`] | A string containing the given substring. | 123| [`displays_as`] | A [`Display`] value whose formatted string is matched by the argument. | 124| [`each`] | A container all of whose elements the given argument matches. | 125| [`elements_are!`] | A container whose elements the arguments match, in order. | 126| [`empty`] | An empty collection. | 127| [`ends_with`] | A string ending with the given suffix. | 128| [`eq`] | A value equal to the argument, in the sense of the [`PartialEq`] trait. | 129| [`eq_deref_of`] | A value equal to the dereferenced value of the argument. | 130| [`err`] | A [`Result`][std::result::Result] containing an `Err` variant the argument matches. | 131| [`field!`] | A struct or enum with a given field whose value the argument matches. | 132| [`ge`] | A [`PartialOrd`] value greater than or equal to the given value. | 133| [`gt`] | A [`PartialOrd`] value strictly greater than the given value. | 134| [`has_entry`] | A [`HashMap`] containing a given key whose value the argument matches. | 135| [`is_contained_in!`] | A container each of whose elements is matched by some given matcher. | 136| [`is_nan`] | A floating point number which is NaN. | 137| [`le`] | A [`PartialOrd`] value less than or equal to the given value. | 138| [`len`] | A container whose number of elements the argument matches. | 139| [`lt`] | A [`PartialOrd`] value strictly less than the given value. | 140| [`matches_pattern!`] | A struct or enum whose fields are matched according to the arguments. | 141| [`matches_regex`] | A string matched by the given regular expression. | 142| [`near`] | A floating point number within a given tolerance of the argument. | 143| [`none`] | An [`Option`] containing `None`. | 144| [`not`] | Any value the argument does not match. | 145| [`ok`] | A [`Result`][std::result::Result] containing an `Ok` variant the argument matches. | 146| [`pat!`] | Alias for [`matches_pattern!`]. | 147| [`points_to`] | Any [`Deref`] such as `&`, `Rc`, etc. whose value the argument matches. | 148| [`pointwise!`] | A container whose contents the arguments match in a pointwise fashion. | 149| [`predicate`] | A value on which the given predicate returns true. | 150| [`some`] | An [`Option`] containing `Some` whose value the argument matches. | 151| [`starts_with`] | A string starting with the given prefix. | 152| [`subset_of`] | A container all of whose elements are contained in the argument. | 153| [`superset_of`] | A container containing all elements of the argument. | 154| [`unordered_elements_are!`] | A container whose elements the arguments match, in any order. | 155 156[`all!`]: matchers::all 157[`any!`]: matchers::any 158[`anything`]: matchers::anything 159[`approx_eq`]: matchers::approx_eq 160[`char_count`]: matchers::char_count 161[`container_eq`]: matchers::container_eq 162[`contains`]: matchers::contains 163[`contains_each!`]: matchers::contains_each 164[`contains_regex`]: matchers::contains_regex 165[`contains_substring`]: matchers::contains_substring 166[`displays_as`]: matchers::displays_as 167[`each`]: matchers::each 168[`elements_are!`]: matchers::elements_are 169[`empty`]: matchers::empty 170[`ends_with`]: matchers::ends_with 171[`eq`]: matchers::eq 172[`eq_deref_of`]: matchers::eq_deref_of 173[`err`]: matchers::err 174[`field!`]: matchers::field 175[`ge`]: matchers::ge 176[`gt`]: matchers::gt 177[`has_entry`]: matchers::has_entry 178[`is_contained_in!`]: matchers::is_contained_in 179[`is_nan`]: matchers::is_nan 180[`le`]: matchers::le 181[`len`]: matchers::len 182[`lt`]: matchers::lt 183[`matches_regex`]: matchers::matches_regex 184[`matches_pattern!`]: matchers::matches_pattern 185[`near`]: matchers::near 186[`none`]: matchers::none 187[`not`]: matchers::not 188[`pat!`]: matchers::pat 189[`ok`]: matchers::ok 190[`points_to`]: matchers::points_to 191[`pointwise!`]: matchers::pointwise 192[`predicate`]: matchers::predicate 193[`some`]: matchers::some 194[`starts_with`]: matchers::starts_with 195[`subset_of`]: matchers::subset_of 196[`superset_of`]: matchers::superset_of 197[`unordered_elements_are!`]: matchers::unordered_elements_are 198[`Deref`]: std::ops::Deref 199[`Display`]: std::fmt::Display 200[`HashMap`]: std::collections::HashMap 201[`Option`]: std::option::Option 202[`PartialEq`]: std::cmp::PartialEq 203[`PartialOrd`]: std::cmp::PartialOrd 204 205## Writing matchers 206 207One can extend the library by writing additional matchers. To do so, create 208a struct holding the matcher's data and have it implement the trait 209[`Matcher`]: 210 211```no_run 212use googletest::{description::Description, matcher::{Matcher, MatcherResult}}; 213use std::fmt::Debug; 214 215struct MyEqMatcher<T> { 216 expected: T, 217} 218 219impl<T: PartialEq + Debug> Matcher for MyEqMatcher<T> { 220 type ActualT = T; 221 222 fn matches(&self, actual: &Self::ActualT) -> MatcherResult { 223 if self.expected == *actual { 224 MatcherResult::Match 225 } else { 226 MatcherResult::NoMatch 227 } 228 } 229 230 fn describe(&self, matcher_result: MatcherResult) -> Description { 231 match matcher_result { 232 MatcherResult::Match => { 233 format!("is equal to {:?} the way I define it", self.expected).into() 234 } 235 MatcherResult::NoMatch => { 236 format!("isn't equal to {:?} the way I define it", self.expected).into() 237 } 238 } 239 } 240} 241``` 242 243 It is recommended to expose a function which constructs the matcher: 244 245 ```no_run 246 # use googletest::{description::Description, matcher::{Matcher, MatcherResult}}; 247 # use std::fmt::Debug; 248 # 249 # struct MyEqMatcher<T> { 250 # expected: T, 251 # } 252 # 253 # impl<T: PartialEq + Debug> Matcher for MyEqMatcher<T> { 254 # type ActualT = T; 255 # 256 # fn matches(&self, actual: &Self::ActualT) -> MatcherResult { 257 # if self.expected == *actual { 258 # MatcherResult::Match 259 # } else { 260 # MatcherResult::NoMatch 261 # } 262 # } 263 # 264 # fn describe(&self, matcher_result: MatcherResult) -> Description { 265 # match matcher_result { 266 # MatcherResult::Match => { 267 # format!("is equal to {:?} the way I define it", self.expected).into() 268 # } 269 # MatcherResult::NoMatch => { 270 # format!("isn't equal to {:?} the way I define it", self.expected).into() 271 # } 272 # } 273 # } 274 # } 275 # 276 pub fn eq_my_way<T: PartialEq + Debug>(expected: T) -> impl Matcher<ActualT = T> { 277 MyEqMatcher { expected } 278 } 279 ``` 280 281 The new matcher can then be used in the assertion macros: 282 283``` 284# use googletest::prelude::*; 285# use googletest::{description::Description, matcher::{Matcher, MatcherResult}}; 286# use std::fmt::Debug; 287# 288# struct MyEqMatcher<T> { 289# expected: T, 290# } 291# 292# impl<T: PartialEq + Debug> Matcher for MyEqMatcher<T> { 293# type ActualT = T; 294# 295# fn matches(&self, actual: &Self::ActualT) -> MatcherResult { 296# if self.expected == *actual { 297# MatcherResult::Match 298# } else { 299# MatcherResult::NoMatch 300# } 301# } 302# 303# fn describe(&self, matcher_result: MatcherResult) -> Description { 304# match matcher_result { 305# MatcherResult::Match => { 306# format!("is equal to {:?} the way I define it", self.expected).into() 307# } 308# MatcherResult::NoMatch => { 309# format!("isn't equal to {:?} the way I define it", self.expected).into() 310# } 311# } 312# } 313# } 314# 315# pub fn eq_my_way<T: PartialEq + Debug>(expected: T) -> impl Matcher<ActualT = T> { 316# MyEqMatcher { expected } 317# } 318# /* The attribute macro would prevent the function from being compiled in a doctest. 319#[googletest::test] 320# */ 321fn should_be_equal_by_my_definition() { 322# googletest::internal::test_outcome::TestOutcome::init_current_test_outcome(); 323 expect_that!(10, eq_my_way(10)); 324# googletest::internal::test_outcome::TestOutcome::close_current_test_outcome::<&str>(Ok(())) 325# .unwrap(); 326} 327# should_be_equal_by_my_definition(); 328``` 329 330## Non-fatal assertions 331 332Using non-fatal assertions, a single test is able to log multiple assertion 333failures. Any single assertion failure causes the test to be considered 334having failed, but execution continues until the test completes or otherwise 335aborts. 336 337To make a non-fatal assertion, use the macro [`expect_that!`]. The test must 338also be marked with [`googletest::test`][crate::test] instead of the 339Rust-standard `#[test]`. 340 341```no_run 342use googletest::prelude::*; 343 344#[googletest::test] 345fn three_non_fatal_assertions() { 346 let value = 2; 347 expect_that!(value, eq(2)); // Passes; test still considered passing. 348 expect_that!(value, eq(3)); // Fails; logs failure and marks the test failed. 349 expect_that!(value, eq(4)); // A second failure, also logged. 350} 351``` 352 353This can be used in the same tests as `verify_that!`, in which case the test 354function must also return [`Result<()>`]: 355 356```no_run 357use googletest::prelude::*; 358 359# /* Make sure this also compiles as a doctest. 360#[googletest::test] 361# */ 362fn failing_non_fatal_assertion() -> Result<()> { 363 let value = 2; 364 expect_that!(value, eq(3)); // Just marks the test as having failed. 365 verify_that!(value, eq(2))?; // Passes, so does not abort the test. 366 Ok(()) // Because of the failing expect_that! call above, the 367 // test fails despite returning Ok(()) 368} 369``` 370 371```no_run 372use googletest::prelude::*; 373 374#[googletest::test] 375fn failing_fatal_assertion_after_non_fatal_assertion() -> Result<()> { 376 let value = 2; 377 expect_that!(value, eq(2)); // Passes; test still considered passing. 378 verify_that!(value, eq(3))?; // Fails and aborts the test. 379 expect_that!(value, eq(3)); // Never executes, since the test already aborted. 380 Ok(()) 381} 382``` 383 384## Predicate assertions 385 386The macro [`verify_pred!`] provides predicate assertions analogous to 387GoogleTest's `EXPECT_PRED` family of macros. Wrap an invocation of a 388predicate in a `verify_pred!` invocation to turn that into a test assertion 389which passes precisely when the predicate returns `true`: 390 391``` 392# use googletest::prelude::*; 393fn stuff_is_correct(x: i32, y: i32) -> bool { 394 x == y 395} 396 397# fn run_test() -> Result<()> { 398let x = 3; 399let y = 4; 400verify_pred!(stuff_is_correct(x, y))?; 401# Ok(()) 402# } 403# run_test().unwrap_err(); 404``` 405 406The assertion failure message shows the arguments and the values to which 407they evaluate: 408 409```text 410stuff_is_correct(x, y) was false with 411 x = 3, 412 y = 4 413``` 414 415The `verify_pred!` invocation evaluates to a [`Result<()>`] just like 416[`verify_that!`]. There is also a macro [`expect_pred!`] to make a non-fatal 417predicaticate assertion. 418 419## Unconditionally generating a test failure 420 421The macro [`fail!`] unconditionally evaluates to a `Result` indicating a 422test failure. It can be used analogously to [`verify_that!`] and 423[`verify_pred!`] to cause a test to fail, with an optional formatted 424message: 425 426``` 427# use googletest::prelude::*; 428# /* The attribute macro would prevent the function from being compiled in a doctest. 429#[test] 430# */ 431fn always_fails() -> Result<()> { 432 fail!("This test must fail with {}", "today") 433} 434# always_fails().unwrap_err(); 435``` 436 437## Integrations with other crates 438 439GoogleTest Rust includes integrations with the 440[Anyhow](https://crates.io/crates/anyhow) and 441[Proptest](https://crates.io/crates/proptest) crates to simplify turning 442errors from those crates into test failures. 443 444To use this, activate the `anyhow`, respectively `proptest` feature in 445GoogleTest Rust and invoke the extension method [`into_test_result()`] on a 446`Result` value in your test. For example: 447 448``` 449# use googletest::prelude::*; 450# #[cfg(feature = "anyhow")] 451# use anyhow::anyhow; 452# #[cfg(feature = "anyhow")] 453# /* The attribute macro would prevent the function from being compiled in a doctest. 454#[test] 455# */ 456fn has_anyhow_failure() -> Result<()> { 457 Ok(just_return_error().into_test_result()?) 458} 459 460# #[cfg(feature = "anyhow")] 461fn just_return_error() -> anyhow::Result<()> { 462 anyhow::Result::Err(anyhow!("This is an error")) 463} 464# #[cfg(feature = "anyhow")] 465# has_anyhow_failure().unwrap_err(); 466``` 467 468One can convert Proptest test failures into GoogleTest test failures when the 469test is invoked with 470[`TestRunner::run`](https://docs.rs/proptest/latest/proptest/test_runner/struct.TestRunner.html#method.run): 471 472``` 473# use googletest::prelude::*; 474# #[cfg(feature = "proptest")] 475# use proptest::test_runner::{Config, TestRunner}; 476# #[cfg(feature = "proptest")] 477# /* The attribute macro would prevent the function from being compiled in a doctest. 478#[test] 479# */ 480fn numbers_are_greater_than_zero() -> Result<()> { 481 let mut runner = TestRunner::new(Config::default()); 482 runner.run(&(1..100i32), |v| Ok(verify_that!(v, gt(0))?)).into_test_result() 483} 484# #[cfg(feature = "proptest")] 485# numbers_are_greater_than_zero().unwrap(); 486``` 487 488Similarly, when the `proptest` feature is enabled, GoogleTest assertion failures 489can automatically be converted into Proptest 490[`TestCaseError`](https://docs.rs/proptest/latest/proptest/test_runner/enum.TestCaseError.html) 491through the `?` operator as the example above shows. 492 493[`and_log_failure()`]: GoogleTestSupport::and_log_failure 494[`into_test_result()`]: IntoTestResult::into_test_result 495[`Matcher`]: matcher::Matcher 496