v0.12.0
Pre-releaseBreaking 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