Andrei Solntsev
29 Oct 2010

Unit-test evolution

This is an example of unit-test evolution which I presented on recent devclub.eu workshop.Let’s consider 3 revisions of the same unit-test class.This is the first revision of this class:


public class ReferenceNumberTest {
  @Test
  public void testValidate() {
    assertFalse( ReferenceNumber.validate("1234567890123") );
    assertFalse( ReferenceNumber.validate("1234567") );
    assertTrue( ReferenceNumber.validate("12345678") );
  }
}

We call it a typical unit-test.At some moment, some developer decides to apply some TDD best practices and split this test-method into 3 with some meaningful names.This is what he got:


public class ReferenceNumberTest {
  @Test
  public void testTooLong() {
    String len13 = "1234567891111";
    assertEquals(len13.length(), 13);
    assertEquals(ReferenceNumber.validate(len13), false);
  }


  @Test
  public void testTooShort() {
    String len7 = "1234567";
    assertEquals(len7.length(), 7);
    assertEquals(ReferenceNumber.validate(len7), false);
  }


  @Test
  public void testOk() {
    String len8 = "12345678";
    assertEquals(len8.length(), 8);
    assertEquals(ReferenceNumber.validate(len8), true);


    String len12 = "123456789111";
    assertEquals(len12.length(), 12);
    assertEquals(ReferenceNumber.validate(len12), true);
  }
}

We call it good unit-test.After some time, some developer decides that even this good unit-test is not human-readable and does not provide enough information about how class ReferenceNumber should work. He continued splitting and renaming.This is what he got at the end:


public class ReferenceNumberTest {
  @Test
  public void nullIsNotValidReferenceNumber() {
    assertFalse(ReferenceNumber.validate(null));
  }


  @Test
  public void referenceNumberShouldBeShorterThan13() {
    assertFalse(ReferenceNumber.validate("1234567890123"));
  }


  @Test
  public void referenceNumberShouldBeLongerThan7() {
    assertFalse(ReferenceNumber.validate("1234567"));
  }


  @Test
  public void referenceNumberShouldContainOnlyNumbers() {
    assertFalse(ReferenceNumber.validate("1234567ab"));
    assertFalse(ReferenceNumber.validate("abcdefghi"));
    assertFalse(ReferenceNumber.validate("---------"));
    assertFalse(ReferenceNumber.validate(" "));
  }


  @Test
  public void validReferenceNumberExamples() {
    assertTrue(ReferenceNumber.validate("12345678"));
    assertTrue(ReferenceNumber.validate("123456789"));
    assertTrue(ReferenceNumber.validate("1234567890"));
    assertTrue(ReferenceNumber.validate("12345678901"));
    assertTrue(ReferenceNumber.validate("123456789012"));
  }
}

We call it BDD style specification.And finally, the most interesting part. During preparing for the workshop, I have discovered that I haven’t copied the original source code of the class ReferenceNumber being tested. Panic! One day left! I had to urgently re-create it from scratch!Now look at these 3 test-classes, and imagine, which of them helped me to create class ReferenceNumber.

Our recent stories