Effective Testing - Show What's Important, Hide the Rest

written in builder, effective-testing-series, testing, tests

What we include in a test is as important as what we leave out. Having the right amount of information helps us understand what the test is doing at a glance.

Let’s say we need to check our Restaurants are behaving correctly. We want to validate two things:

  1. That a restaurants can only cook a Recipe if they have all the necessary ingredients.
  2. That vegan restaurants do not serve non-vegan food

This works fine, but writing a new Recipe for every single test gets repetitive pretty fast. More importantly, most lines of the test are spent creating the Recipe object. By having to spell out every single property, we lose track of what’s important for each specific test.

Luckily, we can use Kotlin default arguments to make the tests better. We could introduce default values directly on the Recipe class, but that would mean we’d have to pick sensible defaults for Recipes in production. We probably don’t want to allow for this flexibility, as we want to force users to specify those properties for each recipe defined. Instead, we will write a helper function with default arguments to handle the Recipe creation. We’ll make it private so that it’s only accessible in the test class.

Now we can re-write our tests to make use of the helper function:

On each test, we only specify the property that the test cares about and leave out all the other ones. This way, somebody glancing at the test can immediately identify what we’re checking, and it’s not distracted by the details on how to create a Recipe object.

Note that this is a simplified example. In real life, the object being created could have multiple nested objects and require many steps to be initialized. All that code would be hidden in our helper function instead of bloating every test.

We could have written the test for vegan recipes without specifying any property, and it would still pass.

By default isVegan is true, so we’re not required to define it. However, we opted for explicitly specifying it in the test, just so that somebody reading the test would know that the value of isVegan is important for this test. As an extra benefit, the test will not break if, in the future, somebody decides to change the default value for isVegan.

This post is part of the Effective Testing Series.