How to refactor tests in tdd?

I am doing this exercise TDD kata: http://osherove.com/tdd-kata-1

I produced the following code (points 1 to 5 in this exercise - I have unit tests for it):

public class StringCalculator { private readonly string[] _defaultSeparators = { ",", "\n" }; public int Add(string numbers) { // Parser section (string to list of ints) var separators = _defaultSeparators; var isSeparatorDefinitionSpecified = numbers.StartsWith("//"); if (isSeparatorDefinitionSpecified) { var endOfSeparatorDefinition = numbers.IndexOf('\n'); var separator = numbers.Substring(2, endOfSeparatorDefinition - 2); numbers = numbers.Substring(endOfSeparatorDefinition); separators = new[] { separator }; } var numbersArray = numbers.Split(separators, StringSplitOptions.RemoveEmptyEntries); var numbersArrayAsInts = numbersArray.Select(int.Parse).ToArray(); // Validator section var negativeNumbers = numbersArrayAsInts.Where(c => c < 0).ToArray(); if (negativeNumbers.Any()) { throw new Exception(string.Format("negatives not allowed ({0})", string.Join(", ", negativeNumbers))); } return numbersArrayAsInts.Sum(); } } 

Now I want to reorganize the code to something like this:

 public int Add(string numbers) { var numbersAsInts = CalculatorNumbersParser.Parse(numbers); CalculatorNumbersValidator.Validate(numbersAsInts); return numbersAsInts.Sum(); } 

How should I plan refactoring to properly reorganize my code and unit tests?

I think that I need to transfer some of the tests to the newly created implementation class classes (CalculatorNumbersParserTests and CalculatorNumbersValidatorTests), modify some existing tests and add tests to run Parse and Validate.

But what is the right way to do this without breaking the tests?

+3
source share
2 answers

I would advise you not to transfer the tests as if you were doing it, then your tests are tied to the implementation, which means that they are very fragile, so you have to change your tests every time you want to change your implementation. This can quickly become costly when you have a large code base and can become an obstacle when making changes.

Your existing tests should indicate the behavior of your string calculator, and you can reorganize your implementation to anything as long as you maintain the desired behavior.

I tend to think that a unit is a β€œunit of behavior,” and it may take several classes to implement it.

Things can change if you want to place some classes in a different assembly, after which you probably want to do some new tests next to the new assembly to ensure that the behavior of these components will not change unexpectedly, but in this case, I doubt that you do it.

Things can also change if you start reusing classes in several places, after which you may want separate tests to determine the behavior of classes regardless of their use in places.

+4
source

I think @Sam Holder has covered most things. The only thing I would like to add is that when you rephrase your code, you should mark any classes that you create and do not want to write specific tests as internal (I assume you are using .net), so that they not visible outside the assembly in which they are contained.

I tend to think that public classes should be tested on their own, as they can be easily implemented with other code by referencing your assembly. While internal classes, on the other hand, can be seen as implementation details and can usually be tested through the open assembly interface. Of course, there are exceptions to this, depending on what you are doing / code complexity, etc., but this is my general rule.

+3
source

All Articles