TotT: Making a Perfect Matcher
October 5th, 2009 | Published in Google Testing
In the previous episode, we showed how Google C++ Mocking Framework matchers can make both your test code and your test output readable. What if you cannot find the right matcher for the task?
Don't settle for anything less than perfect. It's easy to create a matcher that does exactly what you want, either by composing from existing matchers or by writing one from scratch.
The simplest composite matcher is Not(m), which negates matcher m as you may have guessed. We also have AnyOf(m1, ..., mn) for OR-ing and AllOf(m1, ..., mn) for AND-ing. Combining them wisely and you can get a lot done. For example,
EXPECT_THAT(new_code, AnyOf(StartsWith(“// Tests”)),
Not(ContainsRegex(“TODO.*intern”))));
Expected: (starts with “// Tests”) or
(doesn't contain regular expression “TODO.*intern”)
Actual: “/* TODO: hire an intern. */ int main() {}”
MATCHER(IsEven, “”) { return (arg % 2) == 0; }
You can put any code between {} to validate arg, as long as it returns a bool value.
The empty string “” tells Google C++ Mocking Framework to automatically generate the matcher's description from its name (therefore you'll see “Expected: is even” when the match fails). As long as you pick a descriptive name, you get a good description for free.
You can also give multiple parameters to a matcher, or customize its description. The code:
// P2 means the matcher has 2 parameters. Their names are low and high.
MATCHER_P2(InClosedRange, low, high, “is in range [%(low)s, %(high)s]”) {
return low
}
...
EXPECT_THAT(my_age, InClosedRange(adult_min, penalty_to_withdraw_401k));
Expected: is in range [18, 60]
Actual: 2
You may wonder why we haven't seen any types in the examples. Rest assured that all the code we showed you is type-safe. Google C++ Mocking Framework uses compiler type inference to “write” the matcher parameter types for you, so that you can spend the time on actually writing tests – or finding your perfect match.
Toilet-Friendly Version