An example of a non-brittle test

For the TDD course, I’ve been iterating through the course material; implementing it as a I go through each lesson.

In the most recent example, I wanted to show how a test could go from failing to passing, without changing any test code; and without changing the API.

Now, this is normal in TDD. The API is what the end consumer of your process will see (whether that’s another process or an external consumer).

For instance; here is the API for my budget right now:

Budget b = new Budget("name", startDate: new DateTime(2020,05,01));

the API for my budget takes in two things for its creation:

1. A name (how will you refer to this?)
2. A date the budget should start

The Budget exposes two operations:

b.Add(new BudgetItem(/*...*/));
b.CumulativeSpent(effectiveDate: new DateTime(2020,07,01).Date));

1. Adding a budgetItem to the budget with a .Add() method
2. Telling me how much as been spent as of a certain date (The “effectiveDate” in this example).

Now, here’s the test, and the test didn’t change from when it was failing (and it has been failing for a few days, I ignored it because I got ahead of myself in writing it) until when it was passing:

public void BudgetShouldAccountForTotalsAcrossMonths()
  BudgetItem i = new BudgetItem("b1", 1.23M, new DateTime(2020, 05, 01).Date, new OncePerMonth(), new DateTime(2020, 05, 01).Date);
  Budget b = new Budget("Budget That Shows across Months", new DateTime(2020,1,1).Date);
  var totalSpent = b.CumulativeSpent(new DateTime(2020, 07, 01).Date);
  Assert.That(totalSpent, Is.EqualTo(3.69M));

Ignore the BudgetItem’s API for now. It’s hideous and going to be refleshed out (that’s where the next LiveStream will focus on, using what I’ve learned about the domain and the APIs I’ve created to create better APIs)

So how did I make the test pass?

By making a one line change inside the .CumulativeSpent() call:

Importantly, and the takeaway from this email, this is how change happens. Not by affecting what the consumer of your code does to execute your code — we don’t want to change tests. If we have to change tests when we change code it’s a sign our tests are too coupled to how the code does its job. We don’t care if there’s a mechanical turk manually adding up each budgetItem, all we care is that it gives us the cumulative spent.

In short, this change had me like:

P.S. If you aren’t already a member of the course list, and watching the livestream (or getting more updates on the course, like this one) interests you, add your email to the list at I’ll send out an email to that list when I’m about to start the livestream (it’ll be either this weekend or early next week, since my wife is still working on finishing grad school in the evenings).

Leave a Reply