1

Imagine I have a class representing a percentage. This class provides self validation through exceptions by not allowing values less than 0 or greater than 100 respectively.

When following TDD the functionality of a method/class should be apparent from the test that are testing the part of the code. Should a test in this case include a range?

Pseudocode:

testNegativeValuesAreNotAccepted() {
    try {
        Percentage::withValue(Integer.random(Integer.MIN, -1));

        Assert.fail("Percentage MUST NOT accept negative values.");
    } catch (InvalidPercentageValue e) {
    }
}

testPercentageIsCreatedWithCorrectValue() {
    Integer value = Integer.random(0, 100);

    Percentage percentage = Percentage::withValue(Integer.random(0, 100));

    Assert.equals(true, value.equals(percentage.value()));
}

testValuesOver100AreNotAccepted() {
    try {
        Percentage::withValue(Integer.random(101, Integer.MAX));

        Assert.fail("Percentage MUST NOT accept values over 100.");
    } catch (InvalidPercentageValue e) {
    }
}

Would this give the developer of the Percentage class enough information for him to program the class? Is there perhaps too much information for them? How could this range problem be solved in a different way?

  • 1
    So you're writing the tests and someone else is separately implementing it? What do you mean "too much information"? Are the test names not sufficient context? – jonrsharpe Jul 25 '17 at 11:35
  • 12
    I'm not a fan of using 'random' in a test, because your test is not reproducible anymore, and you may end up with it sometimes failing, and sometimes working. If testing the whole range is unfeasible, pick a few 'representative' values (minimum, midpoint, maximum) and work with those instead. – Eternal21 Jul 25 '17 at 11:38
  • 2
    If you are doing TDD, why do you have more than 1 test that makes the result RED? The second test should not have been written until the first test passed. – Bart van Ingen Schenau Jul 25 '17 at 12:02
  • 2
    @DavidPacker "It can happen a different person implements a class someone else had written a unit test for." If you're doing TDD (as you stated) this "other person" is your pairing partner and therefore sits next to you. In any other case you're not doing TDD... – Timothy Truckle Jul 25 '17 at 12:55
  • 2
    @TimothyTruckle Isn't that extreme programming? :) – Andy Jul 25 '17 at 13:01
3

If you want to test a range, then inline some data for the test. I'm using Xunit here, but similar techniques apply for other frameworks.

    [Theory]
    [InlineData(0)]
    [InlineData(20)]
    [InlineData(100)]
    public void HappyPathPercentage(int input)
    {
          //Arrange
          //Act
          //Assert
    }

    [Theory]
    [InlineData(-1)]
    [InlineData(101)]
    public void FailPathPercentage(int input)
    {
          //Arrange
          //Act
          //Assert
    }
  • much better than random numbers!!! – Ewan Jul 25 '17 at 15:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.