; TotT: Making a Perfect Matcher | Google Operating System News

Tuesday, 26 July 2011

TotT: Making a Perfect Matcher

TotT: Making a Perfect Matcher

by Zhanyong G. Mock Wan in Google Kirkland
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”))));
could generate a message like:

Expected: (starts with “// Tests”) or
          (doesn't contain regular expression “TODO.*intern”)
Actual: “/* TODO: hire an intern. */ int main() {}”
If the matcher expression gets too complex, or your matcher logic cannot be expressed in terms of existing matchers, you can use plain C++. The MATCHER macro lets you define a named matcher:

MATCHER(IsEven, “”) { return (arg % 2) == 0; }
allows you to write EXPECT_THAT(paren_num, IsEven()) to verify that paren_num is divisible by two. The special variable arg refers to the value being validated (paren_num in this case) – it is not a global variable.

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 <= arg && arg <= high;
}
...
EXPECT_THAT(my_age, InClosedRange(adult_min, penalty_to_withdraw_401k));
may print:

Expected: is in range [18, 60]
  Actual: 2
(No, that's not my real age.) Note how you can use Python-style interpolation in the description string to print the matcher parameters.
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.

No comments:

Post a Comment