The Degrees of Unit Testing

Three Degrees of Unit Testing

I apologize for the length of this. I’m very passionate about this topic, and there is so much to say. The three styles of testing really are different, and explaining them does take some room!

Any amount of unit testing, done almost any way, adds value to a code base. Regardless of how and when the tests were written, as long as they are reliable and quick, and prove the code does what we think it does, I’m in favor of them. But that is not to say there are not degrees of goodness within the scope of unit testing, especially around when the tests are conceived.

My point in this post is to show how the benefits of unit testing increase the closer you get to letting the tests drive both the implementation and design of the code as it is written. For those of you who have never heard of Test Driven Development (TDD) or have never really tried it, I’m hoping this opens some eyes.

The Basics – Tests After Coding

For most people, this is what comes to mind when thinking about writing unit tests – I write my code, then I write tests for it. This activity, by definition, occurs after code has be written and is an extra task. Let’s look at an example:

// Calculator class
public String calculate(String calculation) throws Exception {
  calculation = calculation.trim();
  String[] pieces = calculation.split(" ");

  int first = Integer.parseInt(pieces[0]);
  int second = Integer.parseInt(pieces[2]);
  String operand = pieces[1].trim();

  switch(operand) {
    case "+" : return Integer.toString(first + second);
    case "-" : return Integer.toString(first - second);
    case "*" : return Integer.toString(first * second);
    case "/" : return Integer.toString(first / second);

  throw new Exception("No calculation found");

// Calculator tests
public void testCalculations() throws Exception {
  Calculator c = new Calculator();

  assertEquals("3", c.calculate("1 + 2"));
  assertEquals("1", c.calculate("2 - 1"));
  assertEquals("8", c.calculate("2 * 4"));
  assertEquals("2", c.calculate("8 / 4"));

  try {
  } catch(Exception e) {

Here we see a simple case of an isolated method, where testing after the code is written is easy. No dependencies, simple inputs and outputs, no problem. As the implementation gets more complicated, though, and dependencies creep in, and code gets longer, testing this code becomes much harder. Here, for example, is a simple Point of Sale system that uses an inventory system to retrieve information a barcode just scanned and a display to show the information retrieved. Here is that code along with a test I wrote. (note I had to fake out some of the complexity to make my point. I’ve seen each and every behavior mentioned in lots of production code, however!)

Display and Inventory classes

public class Display {
  public static Display getInstance() { return new Display(); }

  private Display() {}

  public void showError(String errorMessage) { DisplayService.showError(errorMessage); }
  public void displayItem(Item item) { DisplayService.displayItem(item); }

public class DisplayConfig {}

public class DisplayService {
  private static Item lastItem;

  public static void showError(String errorMessage) {}
  public static void displayItem(Item item) {
  // do the real stuff for displaying an item and save
  // the item so we can test this method
  lastItem = item;

  public static void configure(DisplayConfig config) {
    // configuration code

  // WARNING - testing only!!!
  public static Item getLastItem() { return lastItem; }
public class Inventory {
  public static Inventory getInstance() { return new Inventory(); }
  private Inventory() {}

  public Item getItem(String barcode) { return InventoryService.getItem(barcode); }

public class InventoryConfig {}

public class InventoryService {
  public static Item getItem(String barcode) {
    try {
    } catch (InterruptedException e) {}

    Item item = new Item();

    return item;

  public static void configure(InventoryConfig config) {
  // configuration stuff


public class Item {
  private String name;
  private String price;

  public String getName() { return name; }
  public void setName(String name) { = name;}
  public String getPrice() { return price; }
  public void setPrice(String price) { this.price = price; }


public class POS {
  public void doSale(String barcode) {
    if(barcode == null) {
      Display.getInstance().showError("Invalid barcode scanned");



public class POSTests {
  public void myTest() {
    DisplayConfig dConfig = new DisplayConfig();
    // 10 lines ofsetup code hidden

    InventoryConfig iConfig = new InventoryConfig();
    // 15 lines of setup code hidden

    POS pos = new POS();

    Item item = DisplayService.getLastItem();
    assertEquals("foo", item.getName());
    assertEquals("1.99", item.getPrice());

Now, testing becomes harder because the code was likely not written with testability in mind. The design doesn’t easily support testing small pieces, and there frequently aren’t hooks into the written code to allow it to be tested. So, instead of fixing the design to make things more testable, fewer tests are written and hacks are put into place to allow for testing. On top of that, the dependencies in the code require a lot more setup to let us test our little piece, and they also tend to make tests take longer to run and run less reliably.

However, this is the kind of testing most developers do, as it is what we’ve learned over our careers. It provides partial test coverage, usually of the happy-path cases, which is an improvement over not having tests at all. But since testing is done after the functionality is completed, it is viewed as an “extra activity”, which means it is the first thing dropped when time run short.

Test First Programming

In this style of development, a significant amount of up-front thought and design go into an implementation. Once the design is decided upon, the code is then written by creating a test before code, and repeating that until the implementation is complete.

This is completely identical, in terms of outcomes, to the Test After case, when the problem is very simple. But when the problem gets larger, with dependencies and more complicated coding, you tend to get more code and path coverage due to writing less code to satisfy each test. You also begin to use the tests as feedback into the quality of the design — as tests become harder to write as the code becomes more tightly coupled, which leads to design improvements along the way. The codebase grows as the tests grow, so you get coverage of happy path and error conditions as well. That’s a bonus for this kind of testing.

To start, this is a UML diagram I might have come up with as thinking about solving the same problem from above. The difference in who I might think about this is that making the design testable becomes a first-class design decision. So, instead of using singletons or static classes, I rely entirely on interfaces and the Dependency Inversion Principal to keep things loosely coupled.

Test First Design UML

To implement this, we might start with the concrete implementation of the real Display and Inventory classes, according to the contracts defined in their interfaces. Among the design choices we would make would be to avoid Singletons and static classes, because both make testing more difficult. As our first step for the Inventory class, for instance, we’d make a list of test cases we’d like to implement:

Inventory Test List

  • Will return an item when passed a valid barcode
  • Throws an exception when no item found for a valid barcode
  • Throws an exception when passed a null barcode
  • Throws an exception for an invalid barcode
  • Throws an exception of all information not available to construct an Item

That would be my first pass at a test list, knowing I might find more as I go. One interesting thing that did come up as I was building this is that I realized BarCode is an abstraction that probably needs to be written and have its own tests (validation on construction for the most part). Next step is to write our first test to implement the design we created above:


public void AppropriateItemRetrievedWhenGivenCorrectBarcode() {
  InventoryRepository repository = new InventoryRepository(connection);
  Item expectedItem = new Item("Coke", "$1.99");

  Item item = repository.getItem("validBarcode");

  assertEquals(expectedItem, item);

Before we write any application code, we write our test. This serves as an exploration of the interface and as documentation of how our class will work. In this case, I am using the Repository pattern to encapsulate database operations. I add a test object, use my repository to retrieve it, and make sure it is the same object. From just writing this test, I found I missed the addItem() method in my InventoryRepository and found my Item class needs an equality operator. Easy things to add!

After writing this test, we’d confirm our system won’t compile yet, since we haven’t written any application code yet (hence the TestFirst name). We’d write empty shells of all appropriate classes, adding just enough to make the test compile and fail for the correct reason of not having the appropriate code written yet.

Lastly, I’d repeat these tests for the rest of the InventoryRepository class and then PhysicalDisplay class, followed by the PointOfSale class, working from the bottom up. At this point, I’d expect to have three main application classes written, along with the POD class of Item, and tests for the three main classes. Each class would be thoroughly tested, as we designed our system to be testable and implemented each class one test at a time.

The downside with Test First is that you tend to stick to close to the original design as you’re incrementally writing tests. This means the learning and investigation in the construction process was still very front-loaded.

Test Driven Development

Now, I know I’ve been doing a great job of hiding my preference here, but I’m going to go ahead now and admit to it. I’m a TDD fan. I’ve been doing it since 1999 or so, it is the primary way I write any non-trivial code, and there is nothing better that I’ve found in my 30+ years in the software industry.

The thought process behind TDD is that every move you make while writing code is an experiment, an experiment of how you can satisfy an example through a small amount of code. And after each experiment completes successfully, you spend a few minutes ensuring the code remains simple, readable, and changeable, to support your next experiment. There’s really not any more to it.

What follows is a portion of a larger example of this, done in steps, because TDD is done in small steps. The complete example is available on github. In addition to the tests/experiments and code, there are also complete and explicit checkin comments for each step of the way.

The first thing to notice here is we’re not taking time up front to come up with a design. Part of the Test Driven approach is that you start with your first experiment, write code, and iterate to the minimal design that supports your code. While some believe this is an indication TDD is against design, it’s more true that TDD is a tool to allow design to evolve constantly rather than being concentrated up front.

To build our system, we’ll work outside-in, meaning we’ll look at our system as a whole and write our first experiment to implement a sliver of behavior from the entry-point of our application, then dig in and implement the internals one piece at a time.

Point of Sale Experiment List

  • Given a barcode, display the corresponding name and price
  • Given a different barcode, display the corresponding name and price
  • Given a null barcode, show the appropriate error
  • Given an invalid barcode, show the appropriate error

Thinking about shape of this problem, we need our PointOfSale class and someplace to display the output. This Display class is important, because it is how we’re going to tell our experiment is successful. Everything else will come from thinking about the design as we go.

PointOfSale tests

public class PointOfSaleTests {
  public void correctNameAndPriceShownWhenBarcodeScanned() { 
    Display display = new Display();
    PointOfSale pos = new PointOfSale(display);


    assertEquals("Coke", display.getDisplayedName());
    assertEquals("$1.99", display.getDisplayedPrice());

As we create the shells of our classes and start to implement the code to make this experiment a success, we’ll discover our Display class has a showItem(String name, String price) method our PointOfSale class calls, and also some testing-only methods to get the item details provided through showItem(). This drives out an interface over the Display class that holds just the application method, while the TestDouble we create will have the methods to get the item back for us to confirm. This sounds complicated, but let me show you the code for it.

PointOfSale implementation

public class PointOfSale {
  private DisplayIF display;

  public PointOfSale(DisplayIF display) { this.display = display; }
  public void doSale(String validBarCode) { display.showItem("Coke", "$1.99"); }

public interface DisplayIF {
  void showItem(String name, String price);

// This is a TestDouble, a class written only to allow your design to be tested
public class Display implements DisplayIF {
  private String displayedName;
  private String displayedPrice;

// Method called by application code, to be extracted to interface
  public void showItem(String name, String price) {
    displayedName = name;
    displayedPrice = price;

// Testing-only methods
public String getDisplayedName() { return displayedName; }
public String getDisplayedPrice() { return displayedPrice; }

Again, there is a lot more detail in GitHub, and there is even a lot more detail you can learn from someone who already knows how this technique works.

As you do this, as you create small experiments and implement the minimal code to satisfy them, your system will grow. Do this a hundred times, and you have a small system. Repeat it a thousand, and you have a larger one. And you can keep going, because this scales as large as you like. Since you keep things clean and simple after each experiment finishes, your code is always understandable and easy to change.

It’s just that simple.


At the end of the day, code with tests is better than code without tests. Testing after you write the code is likely to cover the happy paths and some of the error cases, but doesn’t do anything to improve the design. Writing tests before you write code lets you cover more of the error cases, but again generally doesn’t help you with the design. Going all the way to TDD, however, gets you clean code, nearly total test coverage, and a design and is simple and easy to maintain.

TDD is considered controversial by many. I’m really not sure why.

Agile 2016 – Requesting Help for Submissions

Agile2016 Submissions : Asking for Help

Submitting a session proposal for a major conference can be a daunting task, especially if it is your first time. You’re putting your thoughts and ideas out there, knowing that a team of experts will read your words and eventually come to a decision about whether your submission is selected for the final program.

Everyone on each track team knows exactly how you feel, because we’ve all done it, too. Fortunately for us, we were able to ask for feedback from experts and peers while we crafted our sessions. In many cases, that feedback was instrumental in creating a successful submission.

In keeping with the Agile principle of rapid feedback, we’d like you to know that you can get that very same kind of feedback on your submissions, too. All you have to do is ask!

Asking for Help

On the form where you create your proposal, you’ll find three large, colorful buttons used to submit your changes. These buttons represent the stages through which your submission can pass. These stages are important, because they define how the track team will treat your proposal.

In the Draft stage, you can incrementally create and improve their submission for as long as they want. You’re basically alone during this time, although you can still receive public comments on your content.

The Ask For Help stage is where you can ask members of your track team to review and give feedback on your content. The track team members are experts in the subject matter of their tracks and in knowing what it takes to create a great submission. They will answer questions, offer advice, and do anything you need to help make your submission as perfect as possible. One note – no feedback is offered until you Ask for Help!!!

Please use this help early and often in creating your submission. You have an entire team of people per track who are ready and willing to help you create a great session. All you have to do is ask them!

The final stage, Ready for Evaluation, is for sessions the author views as complete, well structured, and ready to be evaluated for inclusion in the final program. No help will be offered in this stage. Track team members may ask clarifying questions as they evaluate all submissions, but the assumption is that you’re ready for that evaluation.

Final Thoughts

Thanks for reading this far. Everyone involved with the program side of the conference truly wants our submitters to succeed. Help is there for each of you – all you have to do is ask.

For more information

Additional guidance and advice is available on the Agile 2016 Conference site. This will tell you about deadlines and expectations, and also show an example of a well-crafted submission.

Looks like I’m speaking at SQE East in Boston, November 12th, 2013!

My good friend Mitch Lacey had to take a step back from a speaking engagement, and he asked me to cover for him to give a half day tutorial on Getting Started With Agile: An Experiential Workshop at the Better Software Conference in November. I’m very excited about doing this talk, both because of the opportunity to speak at this venue and to this audience, and because this kind of talk is so much fun to give.

This session is described as experiential because this talk about Agile and Scrum is planned and execute using Agile and Scrum, With the audience as the stakeholders and me as their “team”, we go through an initial story-gathering process, writing user stories for questions, estimate the questions, put them into a backlog, track metrics, replan and refine, and so on, all while answering the questions posed by the audience.

Doing this talk requires a bit of knowledge and a LOT of courage on the speaker’s part, as the questions can cover literally anything involved with the subject. I’m very glad Mitch has the confidence in me to be able to stand in for him, as his are some very big shoes to fill. Mitch, I’ll do my best not to let you down 🙂

— bab