Skip to content

v0.12.0

Pre-release
Pre-release
Compare
Choose a tag to compare
@bjacotg bjacotg released this 02 Aug 13:58
· 165 commits to main since this release

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, since Actual is now a generic type parameter.
  • ActualT can be passed as value if it implements Copy, which solved #351.
  • When ActualT is a reference, the Matcher 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 & to actual 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 both actual and expected. 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