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.
# posted by Jesse Wilson
on Friday, April 27, 2007
0 comments
post a comment
A PDF Printer for Mac OS X
Some applications don't use the built-in print dialog on Mac OS X, which usually means no PDF printing. Fortunately, some kind soul has created a
PDF printer that is easily installed on Mac OS X.
Its mechanics are similar to
PDF 995 for Windows:
- install the virtual printer
- print a document to the virtual printer
- a PDF file of the printout shows up on your desktop!
I used this tool with CorelDraw 11's print-merge functionality to prepare a hundred pages of personalized invitations. This was a slight bit faster than printing 100 pages and then scanning them!
# posted by Jesse Wilson
on Monday, April 16, 2007
2 comments
post a comment
Subversion and case-insensitive filesystems
My Mac's filesystem is
case-insensitive. It thinks
Foo
and
foo
are the same file.
Subversion's filesystem is case-sensitive. It thinks Foo
and foo
are different files.
As you can imagine, this mismatch has hilarious consequences. If your repository contains a directory with both Foo
and foo
, then svn crashes hard when you try to checkout that directory:
svn: In directory 'project/src/com/publicobject'
svn: Can't copy 'project/src/com/publicobject/.svn/tmp/text-base/Foo.svn-base' to 'project/src/com/publicobject/Foo.tmp': No such file or directory
The solution for me was to:
- checkout the directory on a case-sensitive filesystem (ie. a linux machine)
- delete one of the offending files
- commit the delete
Bonus Material: how did I get myself in this situation?I renamed a file from
OpenFileInIntelliJ.java
to
OpenFileInIntellij.java
. Subversion cannot actually rename a file. Instead, it fakes it by creating a copy and then deleting the original. As you can imagine, this doesn't work too well on a case-insensitive file system...
# posted by Jesse Wilson
on Sunday, April 15, 2007
1 comments
post a comment
CodeSearch-Plugin M9
Today's update is pretty sparse - I cleaned up the new intersect & union features so that you can kick off a new query to intersect and union against. I also drew up some
custom icons for union and intersection.
My next tasks include a lot of polishing:
making the tabs closeable by middle click and via a context menu
making the results openable with F4
cleaning up handing of local files
# posted by Jesse Wilson
on Sunday, April 15, 2007
0 comments
post a comment
Debugging HTTP? Get Charles
Charles is an amazing tool that every web developer should have in their toolchest. It records the HTTP conversations between your browser and the web and lets you analyze them. It can even record HTTPS conversations and remove the encryption.
Some questions that Charles will quickly answer:
- what cookies are we sending to the browser?
- which POST parameters are coming from the browser?
- how many AJAX requests is my form sending?
- why is this webpage slow?
Charles tool is fully-capable shareware, so you can try it out before you pony up the necessary $50.
# posted by Jesse Wilson
on Thursday, April 12, 2007
0 comments
post a comment
CodeSearch-Plugin M8
Today's update of
CodeSearch-Plugin allows you to intersect the results of one query with another query. This allows you to search for code that contains both
spline
and
Graphics2D
, neither of which is particularly useful on its own.
I've also fixed the preflight dialog's handling of ENTER etc., which was quite annoying to some users!
# posted by Jesse Wilson
on Thursday, April 12, 2007
0 comments
post a comment
CodeSearch-Plugin M7
The newest CodeSearch-Plugin remembers what you searched for last time (including file-types & case-sensitivity), so you can search for it again. Unfortunately, this version has an unfortunate bug - when you change and then tab out of any of the text fields, it tends to kick off your query early. Hopefully I fix this tomorrow!
The problem is that JComboBox's setAction() method is essentially useless because it doesn't differentiate between an edit and pressing 'enter'. I'll have to investigate to find a workaround. Perhaps I can install the action on the inner text field?
# posted by Jesse Wilson
on Wednesday, April 11, 2007
0 comments
post a comment
CodeSearch-Plugin M6
CodeSearch-Plugin now has options in the preflight search dialog to select the
Google Code Search filetype and package. For
command line search, you can now add extra arguments from the preflight dialog.
I've also fixed the renderers so that the filename shows up on the left, and its path on the right. This works especially well when the search results panel is narrow because the most important text is also the most visible.
# posted by Jesse Wilson
on Tuesday, April 10, 2007
0 comments
post a comment
CodeSearch-Plugin M5
I've made 2 new updates to the
CodeSearch-Plugin.
Multiple tabs
Expand All, Collapse All, Next, Previous buttons
I've also come up with a very interesting feature - 'Intersect With' to combine multiple searches in an interesting way.
# posted by Jesse Wilson
on Sunday, April 08, 2007
0 comments
post a comment
CodeSearch-Plugin M4
I've added some fixes to my codesearch-plugin project:
whole words only, a convenient way to focus your regex
search field is populated with the selected text
search terms are remembered
settings are application-wide
You can install the plugin right in IntelliJ - instructions are here.
# posted by Jesse Wilson
on Sunday, April 08, 2007
0 comments
post a comment