Atom Feed SITE FEED   ADD TO GOOGLE READER

A helper method for unit testing Comparators

For the poker game I'm not writing, I wrote a Comparator to rank the player's hands.

Now to write a unit tests for that Comparator. Generally I find that it's hard to write test cases for Comparators. You end up having to puzzle over whether to use < 0 or > 0, and the orders of the arguments is significant:
public void testFlushIsAboveStraight() {
PokerHand flush = PokerHand.fromString(" 2c 5c 6c 10c Qc");
PokerHand straight = PokerHand.fromString(" 7c 8d 9h 10s Jh");
assertTrue(new PokerHandComparator().compare(flush, straight) > 0);
}
Another problem with this test is that when it fails, the error message isn't particularly useful:
junit.framework.AssertionFailedError
at PokerEngineTest.testFlushIsAboveStraight(PokerEngineTest.java:14)


Recently I created a Comparator test that I think is quite natural and human readable:
void testSortingHands() {
assertElementsOrderedLikeThis(
PokerHand.fromString(" 3h 4h 4s Kc As"), // low pair
PokerHand.fromString(" 3h 4h 6s Ac As"), // high pair
PokerHand.fromString(" 3d 4d 4h 9c 9s"), // two pairs
PokerHand.fromString(" 4h 6d 10s 10c 10d"), // three of a kind
PokerHand.fromString(" 7c 8d 9h 10s Jh"), // straight
PokerHand.fromString(" 2c 5c 6c 10c Qc") // flush
);
}


This code uses a helper assert method I wrote for testing comparators. This method can be used to test any Comparator (or Comparable) in a human-readable way:
private <T> void assertElementsOrderedLikeThis(
Comparator <? super T> comparator, T... elements) {
List<T> expectedOrder = Arrays.asList(elements);

List<T> shuffledAndSorted = new ArrayList<T>(expectedOrder);
Collections.shuffle(shuffledAndSorted, new Random(0));
Collections.sort(shuffledAndSorted, comparator);
assertEquals(expectedOrder, shuffledAndSorted);

List<T> reversedAndSorted = new ArrayList<T>(expectedOrder);
Collections.reverse(reversedAndSorted);
Collections.sort(reversedAndSorted, comparator);
assertEquals(expectedOrder, reversedAndSorted);
}
Another nice thing about this approach is that in the event of a test failure, the error message includes the expected and actual values.