I had an interesting application requirement: Take an integer (or long) and convert it into a text representation of a number. For example, the method accepts the number 1 and returns “One” and so on. The goal is to convert any positive integer (including zero) into its text representation. In C#, as of this writing, an int maxes out at 2,147,483,647.
Test Driven Development (TDD) applies very nicely to this problem. The solution to this problem may not be obvious at first glance (and in some cases, a bit overwhelming). Might I recommend a “divide and conquer” approach and we can leverage TDD to ensure our re-factoring didn’t break anything.
Spoiler alert!
If you are comfy coding and with TDD, stop here and hammer out some code. If you are new to TDD, let me try to walk you through the process.
- Create a class which will handle the integer two text magic, let’s say “Int2Text.” Add a method string Convert(int number). Convert will take one number and return the text representation of the number.
- Start simple. Create a test case for a single digit number. Then write code to pass that test case.
- Add another test for another single digit number. Write some code and get that case to work. Did you break the previous test case? If so, refactor your code until both test cases are working.
- Create a couple more test cases that are below 20.
- Are all the tests passing? If so, look at your code. Do you see any code segments that are repeated or very similar to other sections? Can you refactor it? After refactoring, do your tests still pass?
- Do not continue on until you are confident your code can display text for 0 to 19 and all your tests are passing (note, this doesn’t mean you need 19 test cases and they all pass).
- Do you have 19 if statements? Or did you use 19 case statements in a switch? If so, think about refactoring.
- With all your tests passing, let’s think about the next step: Notice a pattern with numbers 20 and above (up to 99)? No? Do you notice a pattern when counting by 10, starting from 20? (such as 20, 30, 40, 50…) Don’t think about the numbers between the tens, like 21, 22, 23 – just ignore those and think about the tens – 20, 30, 40, 50.
- Add a test case for 20. Then write only the bare minimum to get this test to pass.
- Did it pass? Try 30. Create a test for 30 first. Then add code. Run your tests. Did any tests fail? If so, go back and fix your code so all tests pass.
- Can your code count from 20 to 90 by counting by tens? If so, can you refactor your code to simplify it? If you used switch or if statements for each tens number, you might think about refactoring.
- To count to 100, we need to be able to print the numbers between the tens, like 21, 22, 23, … 28, 29 and so on. Is there a pattern here? Your code knows how to display 1-9 and it knows how to display 20. Isn’t 21 just a combination of the word “twenty” and “one”? Your code knows how to display these. Can you use recursion to display 21? First create a test for 21 and then try writing some code. If the test passes, remember to try refactoring and testing your changes. Then add more test cases to try out different numbers. Think about some additional test cases to try out. Does 99 work?
- By this point, your code should be able to count from 0 to 99. How about 100? Make a test case for 100 and add code to get this to work.
- Notice that 100 to 119 look a bit like 0 to 19? Add some tests to try these number and add enough code to make these new tests pass without failing your old tests.
- How about counting to 200? 500? 999?
- If you made it this far, try 1000. 10,000. 100,000. 999,000. Can you simplify your code and use recursion?
- How about 1,000,000? 999,999,999? Have you tried 0?