Notes on “Building a Pragmatic Unit Test Suite”
Tags: testing
Published: 2022-11-06 20:55:24

---
title: Notes on “Building a Pragmatic Unit Test Suite”
published: true
date: 2022-11-06 20:55:00 UTC
tags: testing
canonical_url: https://www.rockyourcode.com/notes-on-building-a-pragmatic-unit-test-suite/
cover_image: https://images.unsplash.com/photo-1517971071642-34a2d3ecc9cd?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=420&w=1000
---

Here are some notes on the course “Building a Pragmatic Unit Test Suite” by Vladimir Khorikov.

## Goals and Guidelines

Unit tests help with _confidence_: you know that changes don't break functionality.

Not all unit tests are equal.

Coverage metrics are problematic: you can work around them, for example, by writing assertion-free unit tests.  
Coverage metrics are a good negative indicator, but 100% test coverage is impractical.

Test are code, and you also have to pay a maintenance cost for your tests.

What makes a unit test valuable?

- carefully choose code to test
- use the most valuable tests only

A good unit test:

- has a high chance of catching a regression error
- has a low chance of producing a false positive
- provides fast feedback
- has low maintenance cost

_Testing trivial code is not worth the cost._

Decouple tests from implementation details as much as possible.

Spend most of the time on testing business logic.

## Styles of Unit Testing

- output-based verification (functional style)
- state verification
- collaboration verification (uses _test doubles_)

### Hexagonal Architecture

![hexagonal architecture](https://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Hexagonal_Architecture.svg/768px-Hexagonal_Architecture.svg.png)
_image from [Wikipedia](https://en.wikipedia.org/wiki/Hexagonal_architecture_(software))_

## Implementation Detail

Public API is the surface area that you can access from outside a class.

What are the requirements?

- address an immediate goal of the client code
- address that goal completely

Look at the client code: if it uses more than 1 operation to achieve a single goal, the class is leaking implementation details.

Note: Neighboring classes might be aware of implementation details.  
Example: the Root Entity of an _Aggregate_ (Domain Driven Design) might know about implementation details of the Entities.

Communication inside a hexagon is implementation detail.  
Between hexagons a public API of the hexagon exist (contract).

### Styles

- functional style: has no state, easy to maintain, offers the best protection against false positive
- state verification: should verify through public API, reasonable maintenance cost
- collaboration verification: within the hexagon lots of false positives; between hexagons more stable

### Black-Box Testing Vs. White-Box Testing

- black-box testing: testing without knowing the internal structure
- white-box testing: testing the internal structure

Adhere to black-box testing as much as possible.

### Business Requirements

Does the test verify a business requirement?

* view your code from the end user's perspective
* verify its observable behavior

## Integration Tests

- test data cleanup: wipe out all data _before_ test execution

## Unit Testing Anti-Patterns

- private methods: if needed expose the hidden abstraction by extracting a new concept
- expose state getters: test the observable behavior only
- leaking domain knowledge to tests: use property-paced testing, or verify end result
- code pollution (introduce additional code just to enable unit testing)
- overriding methods in classes-dependencies: violates single-repository-principle, instead split functionality into different pieces
- non-determinism in tests: try to avoid testing async code (separate code into async/sync), use Tasks

## Links

* [Building a Pragmatic Unit Test Suite][pluralsight]

[pluralsight]: https://pluralsight.com/courses/pragmatic-unit-testing