behaviour driven unit test design in Java

Writing unit tests is not that hard but writing good unit tests which, when they fail, tell you exactly and verbosely why and where it did not go right is not as trivial as it seems.

Let’s say we have a class that represents a square. The only operations we can perform on a square are: getting its surface and doubling the side length.

public class Square {

  private int sideLength;

  public Square(int sideLength) {
    this.sideLength = sideLength;
  }

  public int getSurface() {

    return this.sideLength * this.sideLength;

  }

  public void doubleSideLength() {

    this.sideLength = this.sideLength * 2;

  }

}

To test that piece of code, we could probably write a unit test that will look like:

public class SquareTest {

  public void testSurfaceWhenSideLengthIsDoubled() {

    Square a = new Square(5);
    Square b = a; b.doubleSideLength();

    assertEquals(a.getSurface(), b.getSurface() / 4);

  }

}

From a programmer’s point of view the code above perfectly makes sense but – even if the example is rather simple – it does not really tells us what scenario we want to test here. If this piece code would be read by a product manager, she would probably not understand it (oh well, in that case she probably will but unit tests can be a lot more complex than that).

What about making the code a little bit clearer and telling us a story? There are frameworks for that you could argue (like JBehave) but do we need a framework – and all the configuration, XML files that come with – for everything really? What if we just rewrite the test class so it is more narrative?

public class SquareTestEnhanced {

  private Square square;

  public void test_side_length_x_2_gives_surface_x_4() {

    when_doubling_is_done_on(new Square(5));
    then_surface_must_be_multiplied_by_4();

  }

  private void when_doubling_is_done_on(Square s) {

    this.square = s;

  }

  private void then_surface_must_be_multiplied_by_4() {

    Square s = this.square; s.doubleSideLength();
    assertEquals(this.square.getSurface() * 4, s.getSurface());

  }

}

Isn’t it enough? Can my product manager understand what we are testing between lines 5 and 10?

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Spam Protection by WP-SpamFree

Proudly powered by WordPress
Theme: Esquire by Matthew Buchanan.