T is for Testable

Illustration of a school girl with a score of B on her quiz.  It is good enough.
Tests don't end in school. Image from Midjourney v8.2

One of the most critical areas of success in technology is delivering valuable outcomes for your partners. If you cannot provide value, you are wasting time and money. Over the last six weeks, I have focused on the INVEST method of story writing. This technique helps technology teams deliver that value consistently. The final quality of a good product backlog item is testability, and today we will cover why it matters.

A user story must be testable. We do not meet the standard of care the customer expects if we cannot test it. A test can be as simple as loading a web page or as complex as running a series of regression tests once the software is built. What matters is that when someone asks you whether the software works as expected, you can confidently say yes.

Your software's testability lives in the acceptance criteria. In this example, we want to return weather information in both Fahrenheit and Celsius. The story looks as follows:

As a user, I want to view local temperature information in both Fahrenheit and Celsius so that I can dress appropriately for the weather.

We came up with some acceptance criteria like this:

#1
Given I visit the site
When I look up the temperature
Then the temperature is displayed in Fahrenheit
And the temperature is displayed in Celsius

#2
Given I visit the site
When I look up the temperature
And the local temperature is below freezing
Then the temperature is displayed in Fahrenheit
And the temperature is displayed in Celsius
And the font color is blue to signify freezing temperatures

In the world of infographics and web development, requests like this are common.

If you use Gherkin to create acceptance criteria, plenty of tools can convert them into unit tests. I also feel that many Artificial intelligence tools are good at creating unit tests.  Here is an example in Python from Google Gemini:

import unittest
  def fahrenheit_to_celsius(fahrenheit: float) -> float:
    return (fahrenheit - 32) * 5 / 9
class TestTemperatureConversion(unittest.TestCase):
  def test_freezing_point(self):
  # assertAlmostEqual handles potential floating-point precision issues
  self.assertAlmostEqual(fahrenheit_to_celsius(32), 0.0, places=5)
  
if name == "main":
  unittest.main()

Here is the same example in C#

using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TemperatureConverterTests
{
    [TestMethod]
    public void FahrenheitToCelsius_32Fahrenheit_ReturnsZeroCelsius()
    {
        double result = TemperatureConverter.FahrenheitToCelsius(32);
        // Delta specifies allowable floating-point deviation
        Assert.AreEqual(0.0, result, 0.00001);
    }
}

Once the code is written, either of these two tests can execute, and you can prove the system can accurately convert temperatures for customers. Testable user stories make it easy to prove the code works as expected. It provides peace of mind for stakeholders and for you, the developer.

Any product backlog item that is independent, negotiable, valuable, estimable, small, and testable is more likely to meet customer expectations and have fewer defects. It lets you demonstrate outcomes, a key ingredient for a successful technology career. I hope this was helpful, and that you can leverage this knowledge in your agile practice.

Until next time.

Edward J Wisniowski

Edward J Wisniowski

Ed Wisniowski is a software development veteran. He specializes in improving organization product ownership, helping developers become better artisans, and attempting to scale agile in organizations.
Sugar Grove, IL