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