Releases: google/googletest-rust
v0.13.0
API Changes
-
Note that the minimum supported Rust version has increased from 1.66 to 1.70.
-
Rename
#[googletest::test]
to#[googletest::gtest]
and add it to the prelude.Note that
#[googletest::test]
will not be deprecated because this spelling is useful for compatibility with the rstest crate. -
Add
assert_pred!
to prelude.
New Features
-
Add test fixture support for synchronous tests.
Various traits to represent different types of test fixtures have been added. The core
Fixture
trait may be used like this:struct MyFixture {...} impl Fixture for MyFixture { fn set_up() -> Result<MyFixture> { Ok(MyFixture {...}) } fn tear_down(self) -> Result<()> { Ok(()) } } #[googletest::test] fn test_with_fixture(my_fixture: &MyFixture) {...}
ConsumableFixture
has only aset_up
method and notear_down
method.FixtureOf<T>
adapts aT: Default
into aConsumableFixture
.StaticFixture
has aset_up_once
method which is called only once before any tests are run. -
Add
impl Matcher<&()> for ()
. -
Handle the printing of arguments passed to gtest macros that do not implement
Debug
using inherent method specialization. -
Generalize
verify_pred!
such that it can take any expression and provide meaningful output of intermediate values on failure. -
Add support for printing the two sides of a binary operator and traversing inside a unary operator in
verify_pred!
.For example, an assertion of the form
verify_pred!(a == b)
will print both the left and right-hand sides when it fails. -
Add support for sequences (ordered and unordered) to
expect_that!
andassert_that!
. -
Add
result_of!
andresult_of_ref!
matchers for matching with a function applied to the value first.Example:
verify_that!(100, result_of!(|value| value + 1, eq(101)))?;
will pass. -
Add special cases to
verify_eq!
so that, when doingeq
matching on sequences of tuple elements, the matcher applies tuple matching, distributingeq
pointwise.This improves the ergonomics of tests that check for tuple contents, such as:
let hash_map: std::collections::HashMap<String, String> = std::collections::HashMap::from([ ("a".into(), "A".into()), ("b".into(), "B".into())]); verify_eq!(hash_map, {("a", "A"), ("b", "B")})
because the matcher for
&str
is compatible with&String
.The specialization applies on the inner structure; without it, the general matcher on tuples doesn't apply in the above case due to the definition of
PartialEq
on whole tuples, which is currently limited by rust-lang/rust#105092. -
Add
is_true!
andis_false!
Boolean matchers.
Bug Fixes
-
Fix
#[gtest]
failing to compile when a user-declaredstd
orcore
module is in scope. -
Fix stack overflow that occurs when
verify_pred!
is used with nested function calls. -
Fix bug in
summarize_diff
where actual and expected strings were considered equal despite only one of the two ending in a newline character.
Full Changelog: v0.12.0...v0.13.0
v0.12.0
Breaking changes
Matcher trait definition
The Matcher
trait definition has changed:
Pre 0.12.0
pub trait Matcher {
type ActualT: Debug + ?Sized;
fn matches(&self, actual: &Self::ActualT) -> MatcherResult;
}
0.12.0
pub trait Matcher<ActualT: Debug + Copy> {
fn matches(&self, actual: ActualT) -> MatcherResult;
}
This makes the trait implementation more generic in three ways:
- A single struct can implement
Matcher
for multiple types, sinceActual
is now a generic type parameter. ActualT
can be passed as value if it implementsCopy
, which solved #351.- When
ActualT
is a reference, theMatcher
implementation can put constraint on its lifetime, which solved #323.
We tried to make sure this change had as limited an impact on users of the library as possible. Often, the library can be updated without changes on the tests. However, there are two areas requiring changes:
Matcher
implementation
Obviously, libraries implementing their own matcher will need to update their implementation to match the new trait definition. For instance:
Pre 0.12.0
#[derive(Debug)]
enum MyEnum {
...
}
struct MyEnumMatcher { ... }
impl Matcher for MyEnumMatcher {
type ActualT = MyEnumMatcher;
fn matches(&self, actual: &Self::ActualT) -> MatcherResult {
match actual {
...
}
}
}
will become:
#[derive(Debug)]
enum MyEnum {
...
}
#[derive(MatcherBase)]
struct MyEnumMatcher { ... }
impl Matcher<&MyEnum> for MyEnumMatcher {
fn matches(&self, actual: &MyEnum) -> MatcherResult {
match actual {
...
}
}
}
If MyEnum
implements Copy
, it is appropriate to also implement Matcher<MyEnum>
.
MatcherBase
is a super trait to Matcher
which allow the usage of .and(...)
and .or(...)
.
eq(...)
often becomes eq(&...)
The eq(...)
matcher now expects a type matching the actual reference-ness. In other words, you may get error:
no implementation for `&MyStruct == MyStruct`
for instance from a test like:
#[derive(Debug, PartialEq)]
struct MyStruct {...}
let actual = MyStruct {...};
let expected = MyStruct {...};
verify_that!(actual, eq(expected))
The issue is that actual
is auto-ref to match the Copy
bound from the matcher. However, verify_that!
is not able to auto-ref expected
which stays a MyStruct
. The simple solution is to add a &
before expected
.
verify_that!(actual, eq(&expected))
Even if the snippet above compiles, it will look strange to the reader, as it seems to compare a MyStruct
to a &MyStruct
.
There are two solutions here:
- Add
&
toactual
as well, since the auto-ref will detect that another&
is not necessary.verify_that!(&actual, eq(&expected))
- Use
verify_eq!()
which supports auto-ref on bothactual
andexpected
.verify_eq!(actual, expected)
.
Changes to property!
and matches_pattern!
Receiver reference-ness
property!
and matches_pattern!
now requires that the receiver must also be referenced in the declaration to match the method definition. In other words, fn method1(&self) -> ...
requires matches_pattern!(&MyStruct { method1(): ....})
and property!(&MyStruct.method1(), ...)
.
Dereference not necessary
Previously, property!
and matches_pattern!
required to add a *
to "dereference" the method returned value.
Pre 0.12.0
#[derive(Debug)]
struct MyStruct{
field: Field
};
impl MyStruct{
fn field(&self) -> &Field {&self.field}
}
verify_that!(MyStruct{...}, matches_pattern!(MyStruct{*field(): field_matcher()}))
In 0.12.0, this is not necessary nor supported
verify_that!(MyStruct{...}, matches_pattern!(&MyStruct{field(): field_matcher()}))
New features
expect_eq!(..., ...)
and friends
GoogleTest now provides macros similar to assert_eq!()
and friends with verify_
and expect_
behavior.
auto_eq
Most macro matchers now automatically inject eq()
matchers if the parameters they are expecting does not implement Matcher
.
For instance:
#[derive(Debug)]
struct MyStruct {
field1: String,
field2: String,
}
verify_that!(actual, matches_pattern!(MyStruct{field1: "field1", field2: "my field2"}))
Generalized .into_test_result()?
.into_test_result()
now extends all std::result::Result
and Option
which simplifies error handling in test arrangements.
matches_pattern!(...)
binding modes
matches_pattern!(...)
now supports both move and reference binding modes, to be more consistent with Rust pattern matching.
For instance,
struct MyStruct {
field1: String,
field2: String
}
verify_that!(actual, matches_pattern!(MyStruct{field1: "something", field2: "else"}))
verify_that!(actual, matches_pattern!(&MyStruct{field1: ref "something", field2: ref "else"}))
This is useful, if you prefer to capture some fields by reference, with the ref
keyword, and some by value (they would need to implement Copy
).
Full Changelog: v0.11.0...v0.12.0
v0.11.0
API Changes
-
The Minimum Rust Supported Version was updated from 1.59 to 1.66
-
The
property!
andmatches_pattern!
matchers use*
instead ofref
to handle properties returned by reference.
For instance, to match the following structure:struct Strukt { a_field: i32 } impl Strukt { fn get_a_field(&self) -> &i32 {&self.a_field} }
OLD:
verify_that(Strukt{a_field: 123}, property!(ref Strukt.get_a_field(), eq(123))
NEW:
verify_that(Strukt{a_field: 123}, property!(*Strukt.get_a_field(), eq(123))
-
Macro matchers are not exported on the top level anymore but exported in the
googletest::matchers
module as well as thegoogletest::prelude
module.
OLD:use googletest::elements_are; verify_that(vec![1,2,3], elements_are![1,2,3])
NEW:
use googletest::matchers::elements_are; verify_that(vec![1,2,3], elements_are![1,2,3])
-
Matcher::explain_match
andMatcher::describe
now returns aDescription
instead of aString
. Handling of wrapping matcher motivated this change and will make them simpler to write. For simple matchers, this change should be straightforward.
OLD:impl Matcher for MyMatcher { ... fn explain_match(&self, actual: &Self::Actual) -> String { "explanation".to_string() } fn describe(&self) -> String { "description".to_string() } }
NEW:
impl Matcher for MyMatcher { ... fn explain_match(&self, actual: &Self::Actual) -> Description { "explanation".into() } fn describe(&self) -> Description { "description".into() } }
Other new features and improvements
is_utf8_string(...)
is a new matcher which matches a byte array with proper ut8 encoding.assert_that!
andexpect_that!
accepts an error message as third argument, likeassert_eq!(...)
.- Trailing commas support in
assert_that!
,expect_that!
,elements_are!
, andunordered_elements_are!
- Diff summary will highlight the mismatching line with colors.
#[should_panic]
can be used with the#[googletest::test]
macro.
Other minor changes
- When using
eq(...)
with different types (e.g.String
and&str
), thePartialEq
relationship has been switched. See #334 for more details. - Documentation fix in #299 and #332
- Add an extra whitespace between subsequent non-fatal failure messages.
Full Changelog: v0.10.0...v0.11.0
0.10.0
API Changes
None
Bug fixes
None
Other new features and improvements
- #290 Support test functions returning () with
#[googletest::test]
. This allows tests which only useexpect_*
macros to define an alwaysOk(())
return type. - #270 Introduce a function
verify_current_test_outcome
. - #279 Introduce a macro
any!
as a complement to the macroall!
.
Other minor changes
- #275 Add support for using
is_terminal
and environment variables to determine whether to output ANSI colour sequences. - #267 Do not rely on a color term crate to generate ANSI character.
- #271 Clarify the behaviour of fatal and non-fatal assertions in the documentation.
- #283 Reduce the visibility of most submodules of
matchers
. - #295 Add docstrings for some elements which were missing it.
0.9.0
API Changes
-
We eliminated the macro
tuple!
and implemented theMatcher
trait directly for tuples of matchers. #260Previously, if one wanted to match against a tuple of matchers, one would use the
tuple!
macro. Now, one can construct a matcher just by taking a tuple of matchers. To port code, just remove the call totuple!
:OLD:
verify_that!((1, 2), tuple!(eq(1), eq(2)))
NEW:
verify_that!((1, 2), (eq(1), eq(2)))
If the tuple is a singleton, one must ensure that a trailing comma is present so that the Rust compiler recognises it as a tuple:
OLD:
verify_that!((1,), tuple!(eq(1)))
NEW:
verify_that!((1), (eq(1),))
-
We renamed the variants of
MatcherResult
. #258We renamed the variants of the enum
MatcherResult
fromMatches
andDoesNotMatch
toMatch
respectivelyNoMatch
. The new names are more concise and work better linguistically.To port code, just use the new variants:
OLD:
fn matches(&self, actual: &Self::ActualT) -> MatcherResult { if condition { MatcherResult::Matches } else { MatcherResult::DoesNotMatch } }
NEW:
fn matches(&self, actual: &Self::ActualT) -> MatcherResult { if condition { MatcherResult::Match } else { MatcherResult::NoMatch } }
This should only affect developers who write their own matchers, not those using existing matchers.
-
We renamed
MatcherResult::into_bool
toMatcherResult::is_match
. This name is clearer and more in line with Rust idioms such asResult::is_ok
andResult::is_err
. #259let result = matcher.matches(&value); if result.into_bool() { ... }
NEW:
let result = matcher.matches(&value); if result.is_match() { ... }
We have also added a corresponding method
MatcherResult::is_no_match()
which we recommend instead of negating the output ofMatcherResult::is_match()
.This should only affect developers who write their own matchers, not those using existing matchers.
Bugfixes
- All test assertion failures -- fatal and nonfatal -- will now be output when using a mix of assertion types with the
#[googletest::test]
macro. Previously, when a fatal failure occurred after a non-fatal failure, only the non-fatal failure would be output to the console. #254
Other new features and improvements
-
The diff of actual and expected values is now coloured, with extra lines from the actual value appearing in red and lines missing from the expected value appearing in green. The + and - characters are still present for the case that colours are not available or the reader of the output has colourblindness. There is also now an explanation of the output at the top of the diff. #232 #251
-
The assertion failure message for
matches_pattern!
has been improved when matching enums with fields. It now indicates directly that the wrong enum variant was used rather than showing a confusing message about the field not being present. #245For example:
enum AnEnum { A(u32), B(u32) } let actual = A(123); verify_that!(actual, matches_pattern!(AnEnum::B(eq(123))))
Previous output:
Value of: actual Expected: is AnEnum :: B which has field `0`, which is equal to 123 Actual: A(123), which has no field `0`
New output:
Value of: actual Expected: is AnEnum :: B which has field `0`, which is equal to 123 Actual: A(123), which has the wrong enum variant `A`
-
There is new optional support to ease integration with the proptest crate for property-based testing. See the crate-level documentation for more information. #246
-
The new matcher
char_count
matches string slices and owned strings with a given number of Unicode scalar values. It is analogous tolen
for containers. #247verify_that!("This string", char_count(gt(5)))
Other minor changes
- The description and match explanation of the
len
matcher now uses the word "length" rather than (the potentially misleading) "size". - The output for test failures when using the
#[googletest::test]
attribute macro has been improved somewhat. Instead of outputtingError: ()
, the test harness will now outputError: See failure output above
. #255
0.8.1
This release only ensures that the published crates googletest
and googletest_macro
each include a copy of the LICENSE
file. It includes no other changes compared to version 0.8.0.
This change is needed to import the crates googletest
and googletest_macro
into the Android Open Source Project.
0.8.0
API Changes
None
Major features and improvements
-
The performance of constructing a diff of the actual and expected values in the assertion failure message for matchers such as
eq
,contains_substring
,starts_with
,ends_with
, andeq_deref_of
has been greatly improved. -
The aforementioned diff output now compresses long sequences of equal lines, now showing only two lines of context around differences. This is similar to the standard
diff
tool. -
verify_that!
and related macros now support an abbreviated form for matching against containers withelements_are!
andunordered_elements_are!
. Namely:let value = vec![1, 2, 3]; verify_that!(value, [eq(1), eq(2), eq(3)])
is equivalent to
let value = vec![1, 2, 3]; verify_that!(value, elements_are![eq(1), eq(2), eq(3)])
Similarly,
let value = HashSet::from([1, 2, 3]); verify_that!(value, {eq(1), eq(2), eq(3)})
is equivalent to
let value = HashSet::from([1, 2, 3]); verify_that!(value, unordered_elements_are![eq(1), eq(2), eq(3)])
Bugfixes and other changes
-
The
matches_pattern!
macro now supports matching structs and enum variants without fields. For example, the following which would not compile previously now works fine:enum MyEnum { A } verify_that!(value, matches_pattern!(MyEnum::A))
-
The test assertion failure message for
matches_pattern!
now always includes the expected struct or enum variant. For example, the following code:enum AnEnum { A(u32), B(u32), } let value = AnEnum::B(123); verify_that!(value, matches_pattern!(AnEnum::A(eq(123)))
would previously produce the following test assertion failure message:
Value of: value Expected: has field `0`, which is equal to 123 Actual: AnEnum::B(123), which does not have field `0`
This was confusing, since the actual problem -- that the actual value had the wrong enum variant -- was not made clear. Now the failure message is as follows:
Value of: value Expected: is AnEnum :: A which has field `0`, which is equal to 123 Actual: AnEnum::B(123), which does not have field `0`
We plan to continue to polish this message in upcoming versions.
-
The aforementioned generated diff will now only show up to ca. 25 lines of difference. If the actual and expected debug strings differ on more lines, then the two are deemed unrelated and the diff output is suppressed.
0.7.0
API changes
-
The matcher
size
has been renamed tolen
to be more idiomatic in Rust.OLD:
let value = vec![...]; verify_that!(value, size(eq(1)))
NEW:
let value = vec![...]; verify_that!(value, len(eq(1)))
-
The extension traits
AndMatcherExt
andOrMatcherExt
have been removed, their methodsand()
andor()
folded intoMatcher
. In the vast majority of cases, it should suffice just to remove the imports ofAndMatcherExt
andOrMatcherExt
and instead importMatcher
(if not already done).OLD:
use googletest::matchers::{AndMatcherExt, OrMatcherExt}; #[test] fn should_work() { verify_that!(value, starts_with("Something").and(ends_with("else").or(contains_substring("another thing")))) }
NEW:
use googletest::matcher::Matcher; // or, recommended: use googletest::prelude::*; #[test] fn should_work() { verify_that!(value, starts_with("Something").and(ends_with("else").or(contains_substring("another thing")))) }
Importing all symbols in
googletest::prelude
causesMatcher
to be imported. -
The method
Matcher::explain_match
now returns just aString
. The previous structureMatchExplanation
has been removed. This has no effect on the uses of matchers, but does require some minor porting of implementations of theMatcher
trait.OLD:
fn explain_match(&self, actual: &Self::ActualT) -> MatchExplanation { MatchExplanation(format!("which ...")) }
NEW:
fn explain_match(&self, actual: &Self::ActualT) -> String { format!("which ...") }
New features and other changes
-
GoogleTest Rust now works with rustc 1.59. Previously, the minimum required rustc version was 1.67.
-
The
expect_that!
andexpect_pred!
macros as well as theand_log_failure()
extension method will now panic if they are invoked without having used thegoogletest::test
attribute. Previously, it was all too easy to forget to annotate the test with#[googletest::test]
when using theexpect_*
family of assertions. The result was that the assertions would not do anything! Now, the test will immediately panic in that situation.The assertions will also now panic if invoked in a thread other than that in which one is running the test.
-
The output of the actual value in test assertion failure messages will no longer pretty-print if the value's debug output is a single line of at most 60 characters. This should reduce visual clutter. For example, a value of
Some(123)
previously would be output:Actual: Some( 123 )
Now it is output:
Actual: Some(123)
-
Assertion failures now have a newline between the debug output of the value and the further explanation of why an actual value did not match.
-
String comparisons now print a diff output when both the actual and expected values have more than one line. This should make finding the difference between two strings much easier. For example, the following assertion:
let value = "The first line\nThe second line"; verify_that!(value, eq("The first line\nThe second lines"))
yields the following diagnostic output:
Value of: value Expected: is equal to "The first line\nThe second line" Actual: "The first line\nThe second line" which is not equal to "The first line\nThe second line" Difference: The first line +The second line -The second lines
This not only works with
eq
but also with the other string comparison matchersstarts_with
,ends_with
, andcontains_substring
. It does not work with regular expression matchers, nor with string matchers on which one has applied additional configuration such asignore_leading_whitespace()
ortimes(...)
. -
It is now possible to create composed matchers inside functions without running into problems with inner matchers being dropped too early. For example, previously, the following did not compile:
fn create_a_matcher(value: u32) -> impl Matcher<ActualT = Vec<u32>> { contains_each![eq(value), gt(value)] }
Now this and other functions of this sort should compile and work.
-
The matcher
displays_as
now displays a full match explanation of its inner matcher rather than just showing how the actual value displays. In particular, it will now show a diff if the display value has multiple lines and is matched with one of the string matchers.
0.6.0
API changes
-
Changed the way the
Matcher
trait is generic with respect to the type of the actual value from a type parameter to an associated type.This should not break any code using matchers, but does affect how matchers are written. First, the
Matcher
implementation block must now use the associated type.OLD:
impl Matcher<ActualType> for MyMatcher { fn matches(&self, actual: &ActualType) -> MatcherResult {...} }
NEW:
impl Matcher for MyMatcher { type ActualT = ActualType; fn matches(&self, actual: &ActualType) -> MatcherResult {...} }
When the matcher is generic over the actual type (as is common), then the concrete matcher type must also reference the actual value type. This will often require the use of
PhantomData
in the struct body.OLD:
struct MyMatcher {...} impl<ActualT> Matcher<ActualT> for MyMatcher { fn matches(&self, actual: &ActualT) -> MatcherResult {...} }
NEW:
struct MyMatcher<ActualT> { ... phantom: PhantomData<ActualT>, } impl<ActualT> Matcher for MyMatcher<ActualT> { type ActualT = ActualT; fn matches(&self, actual: &ActualT) -> MatcherResult {...} }
Why did we make this change? This forces the concrete matcher type always to carry the type against which it matches. Doing so solves problems which we discovered where the compiler is unable to perform type inference on certain combinations of matchers due to missing information about that type (see below).
Bug fixes
-
The
and()
andor()
methods now work with strings. Previously, using them with strings would cause compilation to fail due to problems with type inference.verify_that!("A string", starts_with("A").and(ends_with("string")))
New features
-
The new
prelude
module makes it easier to include all core functionality and all matchers in one import statement:use googletest::prelude::*; #[test] fn should_work() -> Result<()> { verify_that!(123, eq(123)) }
-
The
eq
matcher now outputs a diff of debug output of the actual and expected values when the assertion fails due to their not being equal, if each value is more than one line. -
The new matcher
eq_deref_of
works likeeq
but takes a reference to the expected value. This is useful when one only has a reference to the expected value and it cannot or should not be cloned.
Other changes
- Many fixes to documentation examples. Examples corresponding to real code should now be correct.
- Doctests are now enabled on all examples where it makes sense to do so.
- The module import setup has been simplified, making things easier for external contributors.
0.5.0
New additions
-
The pattern used in
matches_pattern!
can now accept method invocations:impl MyStruct { fn get_foo(&self) -> u32 {...} } verify_that!(value, matches_pattern!(MyStruct { get_foo(): eq(5) }))
-
The
unordered_elements_are!
,contains_each!
, andis_contained_in!
macros now support map data structures such asHashMap
andBTreeMap
:let value = HashMap::from_iter([(1, "One"), (2, "Two")]); verify_that!(value, unordered_elements_are![(eq(2), eq("Two")), (eq(1), eq("One"))])
-
The
pointwise!
matcher now explicitly supports closures, and allows supplying up to three containers:verify_that!(value, pointwise!(|v| near(v, 0.1), [1.0, 2.0, 3.0]) verify_that!(value, pointwise!(near, [1.0, 2.0, 3.0], [0.01, 0.001, 0.1])
-
There is now support for easily mapping errors from the anyhow crate to test results:
#[test] fn invokes_fallible_function() -> Result<()> { a_fallible_function().into_test_result()?; ... }
Other improvements
- Async tests should now work correctly with the
googletest::test
attribute (see below). googletest::test
should now be compatible with other test attributes such astokio::test
.- The syn dependency has been upgraded to major version 2.
API changes
-
The attribute macro
google_test
has been renamed totest
:OLD:
#[googletest::google_test] fn should_work() -> Result<()> {...}
NEW:
#[googletest::test] fn should_work() -> Result<()> {...}
Downstream tests do not currently have to update their code. The old
google_test
name has been retained as an alias, but is marked deprecated.