Preparing to Use Blitz

Implementing the IOperative Interface

The actual execution of test case commands is carried out by individual operatives, each of which is an object that implements the blitz.main.IOperative interface. The implementation has total freedom to do whatever is needed to complete the commands specified by the test case. To satisfy the requirements of the interface, all you need to do is implement two methods:

  1. public void prepareForExecution(Properties properties, List<String> commandList, String expectedResultFileName, String actualResultFileName)

    This method performs the initialization steps prior to actually executing the test. It uses the given properties to prepare the environment; it does whatever preprocessing it needs to do on the given commandList; and it stores the given names of the two result files for use during execution.
     
  2. public void execute(IMatcher matcher, IOutcome outcome)

    This method performs the actual execution of the commands that were provided to the prepareForExecution() method. The given matcher can be used to compare the contents of the actual result file to the contents of the expected result file, in order to determine the success or failure of the test case. The outcome is then recorded on the given outcome object.

NOTE: you can only record one outcome at a time, regardless of how many commands were actually processed in the command list. So, for example, if you really want to record an outcome for each command, you should separate each command into its own test case, and then assemble all the test cases into a single test suite.

TOP

Creating an Agency

An Agency is a Java "factory" class that can create and return initialized instances of operatives – i.e., instances of objects that implement the IOperative interface. Once created, this class can be referenced in a test case, test suite, or test scenario XML file via the className element inside an agency element.

In order to qualify as a legitimate agency, the class must have public visibility, and it must have one public static factory method with the following signature:

public static IOperative getOperative(List<String> argumentList)

The argument list itself is an instance of java.util.List, and each element in the list will be an instance of java.lang.String, to be interpreted according to the discretion of the factory method.

The method must return an initialized instance of the IOperative; however, the factory class is free to return a singleton instance if that sort of implementation makes sense.

NOTE: If the singleton approach is used, you must ensure that the IOperative implementation is completely thread-safe, as Blitz may in fact be executing multiple tests against this operative in different threads.

TOP

Using Matchers and/or Filters

Matchers and filters provide the ability to compare actual result output with expected result output. A filter can be used to pre-process the contents of each file (for example, by removing unwanted text, such as dates, times, page numbers, etc.) before being examined by the matcher.

Blitz provides several matchers that you can use (all of these are contained in the package blitz.matcher):

  • SimpleMatcher: a matcher that compares strings and file contents and returns an empty string if they are equal to each other, or a non-empty string otherwise.
  • Differentiator: a matcher that compares two strings (or file contents) and returns a string that describes the differences between them, or an empty string if there are no differences.
  • NullMatcher: a matcher that does "nothing" by assuming that all strings are equal to each other and all files are equal to each other.

The NullMatcher is used by default whenever a test does not explicitly declare a matcher or inherit one from a higher-level test. Whether or not you actually use the matcher is decided by your implementation of the IOperative interface.

Blitz also provides filters (all contained in package blitz.filter) that can be assigned to any matcher:

  • RegularExpressionFilter: a filter that uses a collection of arbitrarily complex regular expressions to process an input string. To use this filter, you must specify it in the filter sub-element of the matcher element, along with an appropriate list of arguments. Arguments are organized into groups of two or three, depending on the kind of action required. If the only action is to “match” a particular string, then there will be two arguments in the group; if the action is to “replace” one string with another string, then there will be three arguments in the group. The first argument in each group is considered a regular expression “command”, and may be one of the following:
    • match: if the input string matches the argument, allow the string to pass through unchanged
    • matchIgnoreCase: if the input string matches the argument, disregarding differences in case, allow the string to pass through unchanged
    • replaceFirst: if the input string matches the first argument, replace the first occurrence of the first argument with second argument and return the altered result
    • replaceFirstIgnoreCase: if the input string matches the first argument, disregarding differences in case, replace the first occurrence of the first argument with second argument and return the altered result
    • replaceAll: if the input string matches the first argument, replace all occurrences of the first argument with second argument and return the altered result
    • replaceAllIgnoreCase: if the input string matches the first argument, disregarding differences in case, replace all occurrences of the first argument with second argument and return the altered result

    For example, suppose your test case included the following filter arguments:

         <argument>match</argument>
         <argument>Line</argument>
         <argument>replaceFirstIgnoreCase</argument>
         <argument>ine</argument>
         <argument>inguine</argument>

    This would be treated as a two-phase filtering process. The match instruction requires that the input string contain the character sequence "Line" exactly as spelled. This would match "Line" and "Lineage" but not "spline". Whatever passes through on the first pass is then subject to the second matching rule, replaceFirstIgnoreCase, which says to replace the first occurrence of the character sequence "ine" (disregarding case differences) with the sequence "inguine".

    The matching and replacing arguments can be regular expressions that conform to the standard rules originally stipulated by the Perl language. See the Java API documentation for additional details.

    You can specify as many argument groups as you like. Bear in mind that the rules you create apply to all of the lines in a text file.
     

  • NullFilter: a filter that does "nothing" by returning its input string without alteration.

The NullFilter is used by default whenever a matcher is not explicitly configured with one. Whether or not you actually use the filter can be decided either by your matcher or your implementation of the IOperative interface.

If you wish to create your own matcher, all you need to do is write a Java class that implements the IMatcher interface; similarly you can create your own filter by writing a Java class that implements the IFilter interface.

TOP