The following is a trick I don’t use very often, but when I do need it, it comes in very handy. It’s a trick that many developers aren’t aware of, even though it’s been possible to do with JUnit at least since version 3.
Sometimes you want to have a lot of tests that are almost the same, but that contain different arguments. For example, for a yahtzee calculator, you might want to have the following tests:
checkRollScoredAsCategoryGives(1, 2, 3, 4, 5, "straight", 15);
checkRollScoredAsCategoryGives(1, 2, 3, 4, 4, "straight", 0);
checkRollScoredAsCategoryGives(3, 3, 3, 4, 4, "full house", 17);
checkRollScoredAsCategoryGives(1, 2, 3, 4, 4, "full house", 0);
checkRollScoredAsCategoryGives(4, 4, 4, 4, 4, "full house", 0);
This is possible with JUnit, but a little trick. You have to construct a test suite manually and add special subclasses of TestCase to it:
public static Test suite() {
TestSuite suite = new TestSuite(
YahtzeeScoreTest.class.getName());
suite.addTest(checkRollScoredAsCategoryGives(
1, 2, 3, 4, 5, "small straight", 15));
suite.addTest(checkRollScoredAsCategoryGives(
1, 2, 3, 4, 4, "small straight", 0));
suite.addTest(checkRollScoredAsCategoryGives(
3, 3, 3, 4, 4, "full house", 17));
suite.addTest(checkRollScoredAsCategoryGives(
1, 2, 3, 4, 4, "full house", 0));
suite.addTest(checkRollScoredAsCategoryGives(
4, 4, 4, 4, 4, "full house", 0));
return suite;
}
private static Test checkRollScoredAsCategoryGives(
int die1, int die2, int die3, int die4, int die5,
final String category, final int expectedResult) {
final int[] dice = new int[] { die1, die2, die3, die4, die5 };
return new TestCase("Rolling for " + category) {
@Override
public void runTest() throws Throwable {
YahtzeeScoreboard board = new YahtzeeScoreboard();
board.scoreRoll(category, dice);
assertEquals(expectedResult, board.getTotalScore());
}
};
}
The code creates an anonymous inner subclass of TestCase that instead of calling all methods annotated with @Test just executes our specific test. These tests are collected in a normal JUnit TestSuite.
The test is plain JUnit and will run in Maven or your favorite IDE, just as any other tests. The fact that the suite is named after the test class will let Eclipse know where to go when you double click on the test from the test runner.
This trick can be very useful for tests of logic that calculates a results or validates input.