Exact Verification with Formatted Results

Going back to our example from Listing 7-1 with the describeAddition() method, even our Perl example left us with completeness, ordering, and localization issues. While these are less severe issues than the ones we started with, the increasing global reach and rapid pace of development make them suboptimal.

Let’s recap what we have considered. Containment is weak and prone to false successes. Regular expressions provide a little more robustness but still have completeness and ordering issues. We could use constants instead of our literal strings, but this would not solve the outstanding problems if we only applied it to the joining fragments of the result.

But what if we consider a constant that can represent the entire result? Just like the URL parameters in the previous section, the text of the resulting message is not private, nor are the ways the parameters are inserted into the text. What if we could represent the entire result string with placeholders for the values we want to insert? That technology has existed at least since the C language libraries defined printf format strings. What if we refactored our method to take advantage of format strings as in Listing 7-10?

Listing 7-10: Refactoring Listing 7-1 to use format strings

public static final String ADDITION_FORMAT
    = "The sum of %d and %d is %d";

public String describeAddition(int left, int right) {
  return String.format(ADDITION_FORMAT,
      left, right, left + right);
}

We have not yet solved the ordering issue, but we have addressed the completeness and false-positive weaknesses of both the containment and regular expression approaches. Our test would now look like Listing 7-11.

Listing 7-11: Format-based testing of Listing 7-10

public void testDescribeAddition() {
  int left = 3;
  int right = 5;
  String expectedResult = String.format(ADDITION_FORMAT,
    left, right, left + right);

  String actualResult = describeAddition(left, right);

  assertEquals(expectedResult, actualResult);
}

But what about the ordering problem? Some languages and libraries, especially those designed for internationalization, have extended the C-style printf formatting to include positional references; Java has such positional references. Let’s change the original implementation code as shown in Listing 7-12.

Listing 7-12: Changing the implementation in Listing 7-10 to address parameter order

public static final String ADDITION_FORMAT
  = "The sum of %1$d and %2$d is %3$d";

public String describeAddition(int left, int right) {
  return String.format(ADDITION_FORMAT,
      left, right, left + right);
}

The addition of the number followed by the dollar sign in the format string indicates the ordinal, 1-based index of the parameter in the argument list.

From this form, it is a small step to extract the format string to a localized resource file and make the constant the lookup key in the internationalization framework. Once these relatively simple changes are made, we have a test that can test our code regardless of the locale under which it is run.

Small changes in our implementation can make large differences in the maintainability and stability of our tests in the face of the inevitable evolution of our code base. We have gone from the weak verification of substring containment to a complete and change-resistant verification that even works in a multilanguage code base.3

3. Java has the advantage of natively working with UTF-16 strings. If you program in a language like C++ that requires use of a separate API for multibyte strings, the same techniques apply, but you will have to use the appropriate API, possibly convert representations, and maybe write some supplemental tools.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.104.183