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