1# GoogleTest Rust 2 3[![crates.io][crates-badge]][crates-url] 4[![docs.rs][docs-badge]][docs-url] 5[![Apache licensed][license-badge]][license-url] 6[![Build Status][actions-badge]][actions-url] 7 8[crates-badge]: https://img.shields.io/crates/v/googletest.svg 9[crates-url]: https://crates.io/crates/googletest 10[docs-badge]: https://img.shields.io/badge/docs.rs-googletest-66c2a5 11[docs-url]: https://docs.rs/googletest/*/googletest/ 12[license-badge]: https://img.shields.io/badge/license-Apache-blue.svg 13[license-url]: https://github.com/google/googletest-rust/blob/main/LICENSE 14[actions-badge]: https://github.com/google/googletest-rust/workflows/CI/badge.svg 15[actions-url]: https://github.com/google/googletest-rust/actions?query=workflow%3ACI+branch%3Amain 16 17This library brings the rich assertion types of Google's C++ testing library 18[GoogleTest](https://github.com/google/googletest) to Rust. It provides: 19 20 * A framework for writing matchers which can be combined to make a wide range 21 of assertions on data, 22 * A rich set of matchers providing similar functionality to those included in 23 [GoogleTest](https://google.github.io/googletest/reference/matchers.html), 24 and 25 * A new set of assertion macros offering similar functionality to those of 26 [GoogleTest](https://google.github.io/googletest/primer.html#assertions). 27 28**The minimum supported Rust version is 1.66**. 29 30> :warning: The API is not fully stable and may still be changed until we 31> publish version 1.0. 32> 33> Moreover, any items or modules starting with `__` (double underscores) must 34> not be used directly. Those items or modules are only for internal uses and 35> their API may change without a major version update. 36 37## Assertions and matchers 38 39The core of GoogleTest is its *matchers*. Matchers indicate what aspect of an 40actual value one is asserting: (in-)equality, containment, regular expression 41matching, and so on. 42 43To make an assertion using a matcher, GoogleTest offers three macros: 44 45 * [`assert_that!`] panics if the assertion fails, aborting the test. 46 * [`expect_that!`] logs an assertion failure, marking the test as having 47 failed, but allows the test to continue running (called a _non-fatal 48 assertion_). It requires the use of the [`googletest::test`] attribute macro 49 on the test itself. 50 * [`verify_that!`] has no side effects and evaluates to a [`Result<()>`] whose 51 `Err` variant describes the assertion failure, if there is one. In 52 combination with the 53 [`?` operator](https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator), 54 this can be used to abort the test on assertion failure without panicking. It 55 is also the building block for the other two macros above. 56 57For example: 58 59```rust 60use googletest::prelude::*; 61 62#[test] 63fn fails_and_panics() { 64 let value = 2; 65 assert_that!(value, eq(4)); 66} 67 68#[googletest::test] 69fn two_logged_failures() { 70 let value = 2; 71 expect_that!(value, eq(4)); // Test now failed, but continues executing. 72 expect_that!(value, eq(5)); // Second failure is also logged. 73} 74 75#[test] 76fn fails_immediately_without_panic() -> Result<()> { 77 let value = 2; 78 verify_that!(value, eq(4))?; // Test fails and aborts. 79 verify_that!(value, eq(2))?; // Never executes. 80 Ok(()) 81} 82 83#[test] 84fn simple_assertion() -> Result<()> { 85 let value = 2; 86 verify_that!(value, eq(4)) // One can also just return the last assertion. 87} 88``` 89 90This library includes a rich set of matchers, covering: 91 92 * Equality, numeric inequality, and approximate equality; 93 * Strings and regular expressions; 94 * Containers and set-theoretic matching. 95 96Matchers are composable: 97 98```rust 99use googletest::prelude::*; 100 101#[googletest::test] 102fn contains_at_least_one_item_at_least_3() { 103 let value = vec![1, 2, 3]; 104 expect_that!(value, contains(ge(3))); 105} 106``` 107 108They can also be logically combined: 109 110```rust 111use googletest::prelude::*; 112 113#[googletest::test] 114fn strictly_between_9_and_11() { 115 let value = 10; 116 expect_that!(value, gt(9).and(not(ge(11)))); 117} 118``` 119 120## Pattern-matching 121 122One can use the macro [`matches_pattern!`] to create a composite matcher for a 123struct or enum that matches fields with other matchers: 124 125```rust 126use googletest::prelude::*; 127 128struct AStruct { 129 a_field: i32, 130 another_field: i32, 131 a_third_field: &'static str, 132} 133 134#[test] 135fn struct_has_expected_values() { 136 let value = AStruct { 137 a_field: 10, 138 another_field: 100, 139 a_third_field: "A correct value", 140 }; 141 expect_that!(value, matches_pattern!(AStruct { 142 a_field: eq(10), 143 another_field: gt(50), 144 a_third_field: contains_substring("correct"), 145 })); 146} 147``` 148 149## Writing matchers 150 151One can extend the library by writing additional matchers. To do so, create a 152struct holding the matcher's data and have it implement the trait [`Matcher`]: 153 154```rust 155struct MyEqMatcher<T> { 156 expected: T, 157} 158 159impl<T: PartialEq + Debug> Matcher for MyEqMatcher<T> { 160 type ActualT = T; 161 162 fn matches(&self, actual: &Self::ActualT) -> MatcherResult { 163 (self.expected == *actual).into() 164 } 165 166 fn describe(&self, matcher_result: MatcherResult) -> String { 167 match matcher_result { 168 MatcherResult::Match => { 169 format!("is equal to {:?} the way I define it", self.expected) 170 } 171 MatcherResult::NoMatch => { 172 format!("isn't equal to {:?} the way I define it", self.expected) 173 } 174 } 175 } 176} 177``` 178 179It is recommended to expose a function which constructs the matcher: 180 181```rust 182pub fn eq_my_way<T: PartialEq + Debug>(expected: T) -> impl Matcher<ActualT = T> { 183 MyEqMatcher { expected } 184} 185``` 186 187The new matcher can then be used in the assertion macros: 188 189```rust 190#[googletest::test] 191fn should_be_equal_by_my_definition() { 192 expect_that!(10, eq_my_way(10)); 193} 194``` 195 196## Non-fatal assertions 197 198Using non-fatal assertions, a single test is able to log multiple assertion 199failures. Any single assertion failure causes the test to be considered having 200failed, but execution continues until the test completes or otherwise aborts. 201 202This is analogous to the `EXPECT_*` family of macros in GoogleTest. 203 204To make a non-fatal assertion, use the macro [`expect_that!`]. The test must 205also be marked with [`googletest::test`] instead of the Rust-standard `#[test]`. 206 207```rust 208use googletest::prelude::*; 209 210#[googletest::test] 211fn three_non_fatal_assertions() { 212 let value = 2; 213 expect_that!(value, eq(2)); // Passes; test still considered passing. 214 expect_that!(value, eq(3)); // Fails; logs failure and marks the test failed. 215 expect_that!(value, eq(4)); // A second failure, also logged. 216} 217``` 218 219This can be used in the same tests as `verify_that!`, in which case the test 220function must also return [`Result<()>`]: 221 222```rust 223use googletest::prelude::*; 224 225#[googletest::test] 226fn failing_non_fatal_assertion() -> Result<()> { 227 let value = 2; 228 expect_that!(value, eq(3)); // Just marks the test as having failed. 229 verify_that!(value, eq(2))?; // Passes, so does not abort the test. 230 Ok(()) // Because of the failing expect_that! call above, the 231 // test fails despite returning Ok(()) 232} 233``` 234 235```rust 236use googletest::prelude::*; 237 238#[googletest::test] 239fn failing_fatal_assertion_after_non_fatal_assertion() -> Result<()> { 240 let value = 2; 241 verify_that!(value, eq(3))?; // Fails and aborts the test. 242 expect_that!(value, eq(3)); // Never executes, since the test already aborted. 243 Ok(()) 244} 245``` 246 247### Interoperability 248 249You can use the `#[googletest::test]` macro together with many other libraries 250such as [rstest](https://crates.io/crates/rstest). Just apply both attribute 251macros to the test: 252 253```rust 254#[googletest::test] 255#[rstest] 256#[case(1)] 257#[case(2)] 258#[case(3)] 259fn rstest_works_with_google_test(#[case] value: u32) -> Result<()> { 260 verify_that!(value, gt(0)) 261} 262``` 263 264Make sure to put `#[googletest::test]` *before* `#[rstest]`. Otherwise the 265annotated test will run twice, since both macros will attempt to register a test 266with the Rust test harness. 267 268The macro also works together with 269[async tests with Tokio](https://docs.rs/tokio/latest/tokio/attr.test.html) in 270the same way: 271 272```rust 273#[googletest::test] 274#[tokio::test] 275async fn should_work_with_tokio() -> Result<()> { 276 verify_that!(3, gt(0)) 277} 278``` 279 280There is one caveat when running async tests: test failure reporting through 281`and_log_failure` will not work properly if the assertion occurs on a different 282thread than runs the test. 283 284## Predicate assertions 285 286The macro [`verify_pred!`] provides predicate assertions analogous to 287GoogleTest's `EXPECT_PRED` family of macros. Wrap an invocation of a predicate 288in a `verify_pred!` invocation to turn that into a test assertion which passes 289precisely when the predicate returns `true`: 290 291```rust 292fn stuff_is_correct(x: i32, y: i32) -> bool { 293 x == y 294} 295 296let x = 3; 297let y = 4; 298verify_pred!(stuff_is_correct(x, y))?; 299``` 300 301The assertion failure message shows the arguments and the values to which they 302evaluate: 303 304``` 305stuff_is_correct(x, y) was false with 306 x = 3, 307 y = 4 308``` 309 310The `verify_pred!` invocation evaluates to a [`Result<()>`] just like 311[`verify_that!`]. There is also a macro [`expect_pred!`] to make a non-fatal 312predicaticate assertion. 313 314## Unconditionally generating a test failure 315 316The macro [`fail!`] unconditionally evaluates to a `Result` indicating a test 317failure. It can be used analogously to [`verify_that!`] and [`verify_pred!`] to 318cause a test to fail, with an optional formatted message: 319 320```rust 321#[test] 322fn always_fails() -> Result<()> { 323 fail!("This test must fail with {}", "today") 324} 325``` 326 327## Configuration 328 329This library is configurable through environment variables. Since the 330configuration does not impact whether a test fails or not but how a failure is 331displayed, we recommend setting those variables in the personal 332`~/.cargo/config.toml` instead of in the project-scoped `Cargo.toml`. 333 334### Configuration variable list 335 336| Variable name | Description | 337| ------------- | ------------------------------------------------------- | 338| NO_COLOR | Disables colored output. See <https://no-color.org/>. | 339| FORCE_COLOR | Forces colors even when the output is piped to a file. | 340 341## Contributing Changes 342 343Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute 344to this project. 345 346[`and_log_failure()`]: https://docs.rs/googletest/*/googletest/trait.GoogleTestSupport.html#tymethod.and_log_failure 347[`assert_that!`]: https://docs.rs/googletest/*/googletest/macro.assert_that.html 348[`expect_pred!`]: https://docs.rs/googletest/*/googletest/macro.expect_pred.html 349[`expect_that!`]: https://docs.rs/googletest/*/googletest/macro.expect_that.html 350[`fail!`]: https://docs.rs/googletest/*/googletest/macro.fail.html 351[`googletest::test`]: https://docs.rs/googletest/*/googletest/attr.test.html 352[`matches_pattern!`]: https://docs.rs/googletest/*/googletest/macro.matches_pattern.html 353[`verify_pred!`]: https://docs.rs/googletest/*/googletest/macro.verify_pred.html 354[`verify_that!`]: https://docs.rs/googletest/*/googletest/macro.verify_that.html 355[`Describe`]: https://docs.rs/googletest/*/googletest/matcher/trait.Describe.html 356[`Matcher`]: https://docs.rs/googletest/*/googletest/matcher/trait.Matcher.html 357[`Result<()>`]: https://docs.rs/googletest/*/googletest/type.Result.html 358