Skip to main content
1 of 2
ianmandarini
  • 2.8k
  • 14
  • 26

In TDD, should I add unit tests to refactored code?

While refactoring my code using Test Driven Development (TDD), should I keep making new test cases for the new refactored code I am writing?

This question is bases on the following TDD steps:

  1. Write just enough of a test for code to fail
  2. Write just enough code for the test to pass
  3. Refactor

My doubt is in the refactor step. Should new unit test cases be written for refactored code?

To illustrate that, I will give a simplified example:


Suppose I am making a RPG and I am making a HPContainer system that should do the following:

  • Allow the player to lose HP.
  • HP should not go below zero.

To answer that, I write the following tests:

[Test]
public void LoseHP_LosesHP_DecreasesCurrentHPByThatAmount()
{
    int initialHP = 100;
    HPContainer hpContainer= new HPContainer(initialHP);
    hpContainer.Lose(5)
    int currentHP = hpContainer.Current();
    Assert.AreEqual(95, currentHP);
}
[Test]
public void LoseHP_LosesMoreThanCurrentHP_CurrentHPIsZero()
{
    int initialHP = 100;
    HPContainer hpContainer= new HPContainer(initialHP);
    hpContainer.Lose(200)
    int currentHP = hpContainer.Current();
    Assert.AreEqual(0, currentHP);
}

To satisfy the requirements, I implement the following code:

public class HPContainer
{
    private int currentHP = 0;

    public void Reputation(int initialHP)
    {
        this.currentHP = initialHP; 
    }

    public int Current()
    {
        return this.currentHP;
    }

    public void Lose(int value)
    {
        this.currentHP -= value;
        if (this.currentHP < 0)
            this.currentHP = 0;
    }
}

Good!

The tests are passing.

We did our job!


Now let's say the code grows and I want to refactor that code, and I decide that adding a Clamper class as following is a good solution.

public static class Clamper
{
    public static int ClampToNonNegative(int value)
    {
        if(value < 0)
            return 0;
        return value;
    }
}

And as a result, changing the HPContainer class:

public class HPContainer
{
    private int currentHP = 0;

    public void Reputation(int initialHP)
    {
        this.currentHP = initialHP; 
    }

    public int Current()
    {
        return this.currentHP;
    }

    public void Lose(int value)
    {
        this.currentHP = Clamper.ClampToNonNegative(this.currentHP - value);
    }
}

The tests still pass, so we are sure we did not introduce a regression in our code.

But my question is:

Should unit tests be added to the class Clamper?


I see two opposing arguments:

  1. Yes, tests should be added because we need to cover Clamper from regression. It will ensure that if Clamper ever needs to be changed that we can do that safely with test coverage.

  2. No, Clamper is not part of the business logic, and is already covered by the test cases of HPContainer. Adding tests to it will only make unnecessary clutter and slow future refactoring.

What is the correct reasoning, following the TDD principles and good practices?

ianmandarini
  • 2.8k
  • 14
  • 26