The power of XMLUnit with google Predicate

I have been interested in XMLUnit and google collections predicate system for awhile now and recently wrote the following as part of a test.  I have removed some of the test and left just the bits that illustrate this point.

The test needs to perform a check that the result of transforming some xml is correct.  A reference file is available so we can use XMLUnit to perform a difference.  In my file there is a seconds attribute and because seconds vary with each parse we choose to ignore the value.  There are other ways to achieve this, but its more complex and uses more XMLUnit code. Using a google predicate simplifies this check.

First produce your output file and load the sample and output into strings. Normally for a test I produce a smaller sample xml file. Then using XMLUnit difference engine get all differences.

    Diff d = new Diff(expectedAsString, outputAsString);
    DetailedDiff dd = new DetailedDiff(d);
    List listOfDifferences = dd.getAllDifferences();

Next call a function to check that the only differences found are within the seconds attribute. This uses a predicates from google to perform the matching.

    assertTrue(onlyDiffsMatchThisAttributeName("seconds",listOfDifferences));
    }

    private static boolean onlyDiffsMatchThisAttributeName(final String attrName, Iterable it) {

    Iterable filtered = Iterables.filter(it, new Predicate() {

        @Override
        public boolean apply(Difference input) {

                final NodeDetail testNodeDetail = input.getTestNodeDetail();
                if (nodeDetail == null) return false;

                final Node node = nodeDetail.getNode();
                if (node == null) return false;

                final String nodeName = node.getNodeName();
                if (nodeName == null) return false;

                return !nodeName.equals(attrName);
            }
        });
        return (newArrayList(filtered).isEmpty());
    }

Note that what is happening here is the predicate is filtering away all the seconds matches. If anything remains in the list false is returned. Neat huh! :-)

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Hamcrest Collection Matching with Junit 4.8

Sometime back I wrote about some testing anti-patterns.  Recently I came back to the project and made some trivial changes.  I fixed a bug upgraded spring and junit and migrated the test assertions to hamcrest fluid style.  The full project is available on git.

I find hamcrest to be a much cleaner way of writing assertions.  This test demonstrates the use of its fluid interface with some simple collection assertions.  There are newer versions of Hamcrest and the collection package may have moved into core, but the version I use here (1.0) was available on maven.  Note the integration with Junit.  The hasItem and hasItems methods are sourced from Junit 4.8.1.

package org.testpatterns.hamcrestexamples;

import java.util.Arrays;
import org.junit.Test;
import static org.hamcrest.collection.IsArrayContaining.hasItemInArray;
import static org.junit.matchers.JUnitMatchers.*;
import static org.junit.Assert.assertThat;

public class CollectionExamples {

  //Hamcrest with Collections and Arrays:
  static final String[] array = { "A", "B", "C" };
  static final List<String> list = Arrays.asList(array);

  @Test
  public void oneThingInArray () {
    assertThat(array, hasItemInArray("A"));
  }

  @Test
  public void arrayOfItemsInList () {
  String[] expected = { "A", "B", "C" };
    assertThat(list, hasItems(expected));
  }

  @Test
  public void itemInAList () {
    assertThat(list, hasItem("A"));
  }

  @Test
  public void itemsInAList () {
    assertThat(list, hasItems("A", "C"));
  }

}
Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

When you can’t avoid an out parameter

We all know its a good idea to avoid using out variables in Java. In almost every case the code can be split up to avoid the situation. Its bad semantics because when reading the code its not obvious which object passed, if any will get mutated.  So the reader is forced to open the method to find out what it does. In Robert C Martin’s Clean Code Book he calls this forcing a double take, and suggests some ways to avoid the problem.  Rarely you find a case where you can’t avoid it, or to be more accurate, avoiding it leads to worse problems.

Take a look at this interface.  If I find this populate method, I am likely to have to open implementations.  I don’t know if it populates one map from the other or both maps.

import java.util.Map;

public interface NastyPopulator {

void populate(Map<String, String> driver, Map<String, String> driverHolder);

}

The problem is the semantics of map are that you can read from maps or you can write to them.  I think this is a slightly better approach below.

I have used ImmutableMap.Builder.  The semantics of this are that it is used to build things.  I will call build() on the object later to get a map.  Next its an ImmutableMap.  So not only am I declaring that the two parameters are likely to be used to build something, that thing will ultimately be Immutable so in effect the signature declares that I am not expected to make modifications later.  Finally the method name is unambiguous buildMaps, which pretty much says what its going to do.

import com.google.common.collect.ImmutableMap;

public interface LessNastyPopulator {

void buildMaps(ImmutableMap.Builder<String, String>  driver, ImmutableMap.Builder<String, String> driverHolder);

}

Feels like a stronger declaration to me. If ImmutableMap is awkward you could define your own static builder and pass that in, at least your still declaring up front, that this method is builds the two maps. If the method is reading from one map and building others, how about passing an iterator and a builder?

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Neat multiset in google collections API

This good thing was so small that I almost did not bother to blog it

But the devil is in the detail so here it is anyway.

I have this multi threaded application. One of the problems with integration testing it is, you can’t guarantee the order that messages will be written to a stream. So during the test I have to go to some trouble to split and order the lines written out. If I don’t do this the test fails sometimes. It depends on which thread writes first. The output though is correct, order is not important. Not exactly rocket science.

Here is the method I was using to massage the string.

 public List<String> getSortedLines(String expectedString) {

        String[] splitExpectedResultLines = expectedString.toString().split("\n");
        List<String> resultLines = new ArrayList<String>();
        for (String messageLine : resultLines) {
            resultLines.add(messageLine);
        }

        Collections.sort(resultLines);
        return resultLines;
    }

There is nothing particularly wrong with the method. It takes a string, splits it into lines, loads a List, sorts and returns it. Thus when its used in an assertion later the expected and actual lists are the same.

With google collections its just three lines! The HashMultiset is designed to be used in equals methods. Its equal even if the order of the elements in collections being compared is different. From the API documentation: An extension of Collection that may contain duplicate values like a List, yet has order-independent equality like a Set. One typical use for a multiset is to represent a histogram.

Its possible to use the HashMultiSet.create static factory method, passing in an Iterable. i.e a Collection. So from the original code, both the loop and the Collections.sort are no longer required.

   public HashMultiset<String> getOrderAgnosticCollection(String expectedString) {

        String[] splitExpectedResultLines = expectedString.toString().split("\n");
        Iterable<String> resultLines = Arrays.asList(splitExpectedResultLines);
        HashMultiset<String> orderAgnosticResultLines =
                                              HashMultiset.create(resultLines);

        return orderAgnosticResultLines;
    }

If there was something that performed the split, but returned an Iterable the method would be perfect! ;-)

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)