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

Q&A about working at Codeborne with our HR and a developer

We often get asked what it’s really like to work at Codeborne - how pair programming works, how flexible our office hours are, and what the day-to-day feels like. In this Q&A, our HR manager and a recently joined developer share honest answers to the questions we hear most from candidates.

Who are the Codeborne type of people?

Every now and then, Codeborne is looking for new employees. And often these new potential employees wonder “Am I the Codeborne type?” or “What type of people Codeborne is looking for?”

Codeborne 15 - interview with our CEO Toomas

To celebrate 15 years of Codeborne, we sat down with Toomas Talts, the CEO and one of the co-founders of Codeborne, to reflect on the journey, the values that shaped the company, and the unique culture that has defined company's success.