Refactoring on @Ignore

how-to
Apr 4, 20092 mins

Doing the Code Dojo at Oslo XP meetup last Monday, I realized a new concept that I’ve been using unconsciously for a while: I only add to the structure of my system when I have a test that cannot be satisfied by the current design. The rules of test-driven development tells me to wait to create a more advanced design until I have a reason to do so. And that reason should be a failing test. However, the rules of refactoring require all tests to be green during a refactoring. So the failing test must be Ignored during the refactoring.

I revisited these ideas last Wednesday in my second Code Dojo this week in form of the problem of Yahtzee.

If you start solving the scoring rules for the game of yahtzee using the simple examples of “ones”, “twos” and so on, you will run into a problem as you approach, say full house. A full house in yahtzee is scored for example, when you roll three fours and two fives on your five dice. That is:

assertEquals(18 + 10, scoreFor(YahtzeeCategory.FULL_HOUSE, 5, 6, 6, 5, 6))

When I first solved this kata, the test for full house meant I had to take a step back. My solution was to come up with the design of creating a method to calculate the frequency of each die value. This could for example be represented as an array, so that

assertEquals(new int[] { 0, 2, 1, 0, 2, 0 },
                  calculateDieFrequency(2, 3, 5, 2, 5))

This refactoring also changes the implementation of ones, twos, etc:

public int scoreForOnes(int[] dice) {
    return calculateDieFrequency(dice)[<b>1</b>];
}

Clearly, I don’t want my tests to fail while I execute this refactoring. This means that the test for “full house” must be @Ignored (or commented out) during this change. Moreover, the existence of the test for “full house” is the very reason I want to introduce this more advanced design.

Thus: Only refactor to more a more complex design while you have an @Ignored test that cannot pass with the current design.