Multiple asserts are bad and that's the hill I'll die on
Tags: testing, tdd, unittesting
Published: 2022-04-26 21:11:31

---
title: Multiple asserts are bad and that's the hill I'll die on
published: true
description: Why multiple asserts per test are bad and how to eliminate them
tags: testing, TDD, unittesting
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/spmjfyrv3v8cy4x9jopv.jpg
---

> Photo by Jørgen Håland on [Unsplash](https://unsplash.com/photos/4yOgRb_b_i4)

## Context

When writing an automated test, sometimes multiple things happen and sometimes we want to check (i.e. assert) all of them and *sometimes* we want to do that in *one* test.

Like this:

{% embed https://gist.github.com/mbjelac/c7f04bfeaa86d96a4ce3ed56716a623b %}

## Don't do it!

Reasons:

1. Readability is lower: the assertion is the center of the test (thus should always be written *first* but that's another article) and having more than one disorients the reader
2. The test framework will stop on first failure, meaning the failure report will be partial - you'll never know which output was incorrect and which correct, except the first incorrect one (and all the correct ones before it, provided you know by heart which ones went before)
3. The test name is either weirdly composed of multiple parts which makes it long and hard to follow (like in the Gist) or describes just part of the scenario, i.e. it is *lying*

## How to do it differently?

### Method A: Assertion Structure

In a simple-enough case, when all the asserted data is in-fact closely related (domain-wise), we can lump the actual data in one structure, the expected data in another (of the same type) and assert the structures' equality.

Like this:

{% embed https://gist.github.com/mbjelac/8d67d549e45e4ed196e70df4eb121e3e %}

For simple matters, arrays (or any collection in other languages, e.g. `List`s in Java/Kotlin) will suffice.

For more complex stuff and much greater readability use custom data objects:

{% embed https://gist.github.com/mbjelac/c48cda617f64b684f989f91e2a42c5d9 %}

The increased readability is apparent in code, but much more so in the test failure report!

### Method B: Multiple Tests

When the data isn't *that much* related to each other domain-wise, you should have multiple tests with one assert each:

{% embed https://gist.github.com/mbjelac/237ee2f375aefba0b056807c27c21c3b %}

The duplication of arrange (given) and act (when) steps can be solved in a number of ways, but can also be left duplicated - these are tests after all and DRY holds much weaker here: readability is much more important.

## In the end...

When you see a test with multiple asserts, or are starting to make one, ask yourself:

> What is the point of this test?

Then try to see which of the above methods should be applied.

## But what if we use...

...a soft assertion library (which executes *all* multiple asserts and the failure report displays all results)?

That works, but I dislike those because:

1. They usually require the developer to finally call `.assertAllOfUs()` in the end and this can be forgotten which results in the most evil thing there is: A TEST THAT *NEVER* FAILS 💣
2. I have to learn how yet another library and it's API work 🙄

### Next-morning Addition

A thing one remembers when walking one's dog in the morning: [AssertK](https://github.com/willowtreeapps/assertk) has the "soft" assertions solved with their [multiple assertions feature](https://github.com/willowtreeapps/assertk#multiple-assertions), which avoids the bad point 1. but still kind of leaves point 2. Also, allows people to complicate test code, especially when using multiple assertions *within* a multiple assertion. 🤯

Also the lib is for Kotlin only ... but everyone should be writing Kotlin anyway. 😛