Custom comparator

Allow a CustomComparator to provide a matches() implementation to compare expected and actual string representations:

public interface CustomComparator {
  /**
   * Compare two string representations, to determine whether the expected result matches
   * the actual result.
   * @param actual String representation of the actual result
   * @param expected String representation of the expected result
   * @return true if they match, false if they don't match
   * @throws Throwable if an exception or error is thrown, the throwable message is appended
   * to the failure output
   */
  boolean matches(String actual, String expected);
}
 
An example of a matches() implementation using the JSONAssert library to do matching of JSON objects could be:

  @Override
  public boolean matches(String actual, String expected) {
    try {
      JSONAssert.assertEquals(expected, actual, false);
      return true;
    } catch (JSONException e) {
      throw new RuntimeException(e.getMessage(), e);
    }
  }

Unlike Custom Type converters, Type information cannot be used to determine if a specific Custom Comparator should be used. Hence a comparator-specific prefix is needed to prefix the expected string. Since the matcher is used by FitNesse, not the Fixture, it cannot be registered by the Fixture as Custom Type converters are. Hence the Plugins mechanism should be used instead. So to register a Custom Comparator, a CustomComparators = <prefix>:<class name> entry is added to plugins.properties. An example plugins.properties for the JSON comparator would be

CustomComparators = json:test.JSONAssertComparator

Finally, a sample ScriptTable check action using the json comparator could look like this:
|script|Customer|
|check|get|cust1|json:{id:cust1,name:"John Doe"}|