Unit Tests - Wasted Time?
Developers are frustrated by spending more time on maintaining Unit Tests rather than writing code. When they change code, they have to "fix" broken Unit Tests. Why? How to solve this problem?
📢 My next Live Q&A Session is next Wednesday 19th March 17:00. Only Paid Members can join:
If you’re a Free Member, you can upgrade to attend the Live Q&A:
Many developers are writing one unit test per class, and mocking out everything else. They complain because:
They have to write so many tests. Sometimes they ask themselves whether they need to write a test for this class, or whether it’s a waste of time.
The tests break during refactoring. E.g. if the developer decides to split a class, move methods, or update the method signature, so many tests break. It’s a horrible experience. They spend more time “fixing“ the broken tests, rather than writing code. Unit Testing feels like a big waste of time because they’re spending more time on maintaining the Unit Tests rather than writing code!
I’ve experienced that problem, I’ve seen it across the teams where I did technical audits & technical coaching, and many developers have expressed their concerns.
So… is the problem with Unit Tests… or is the problem that we’re writing Unit Tests the wrong way?
How wide should our Unit Tests be?
During our previous Live Q&A, I answered Alessandro’s question (video). Since this is a very popular question I get, I decided to also write an article with an expanded answer.
The original question that Alessandro wrote was:
Hi Valentina, what about unit test scope.
It's clear that we Need to bind tests to behaviour and not implementation detail.
I see that testing through the HA ports Is the right way, but this way we have broad tests.
In a TDD context this could lead to a "slower" feedback in the sense that It take more time to make the test pass.
Perhaps I can use more narrow tests to drive me and then delete them?
When a broad test broke It Is more difficult understand Where the code doesn't work.
Before I answer this question, let’s compare the different types of writing Unit Tests, and then we’ll apply it to Hexagonal Architecture too.
History: Sociable vs Solitary Unit Tests
We generally agree that unit tests are low-level and fast-running tests.
However, there are differences in the span of unit tests.
Fowler distinguished two types of Unit Tests:
Sociable Unit Tests - we test a class with real instances of its dependencies (mocking out only if there’s an I/O dependency).
Solitary Unit Tests - we test a class with “mocked“ instances of its dependencies (we mock out all dependencies, irrespective of whether they are in-memory or I/O)
In that article, Fowler attributes those two test types as originating from the different schools of TDD:
“Two schools of xunit testing developed, which I call the classic and mockist styles. One of the differences between the two styles is that mockists insist upon solitary unit tests, while classicists prefer sociable tests.“ - Martin Fowler (Unit Test)
Note:
“Blue“ class contains only Business Logic (no I/O)
“Grey“ class contains I/O communication
Most Solitary Unit Tests are a waste of time.
As I’ve reviewed many codebases in companies across the world, I’ve seen Solitary Unit Tests as the most dominant style used.
I’ve seen those teams were struggling with unit tests, complaining that they are too expensive to maintain, that they’re spending more time on tests rather than code…
It’s not surprising that James Copelien wrote “Why Most Unit Testing is Waste“.
The way that most teams write Unit Tests is indeed a waste of time!
I am not surprised that many developers had bad experiences with Unit Tests, why they are against Unit Tests, and why they abandon Unit Tests altogether! It’s all caused due to the nightmare experience they’ve had in writing zero-value expensive-to-maintain Unit Tests!
Why I switched to Sociable Unit Tests?
When I was a beginner, I only knew about Solitary Unit Tests. It was because those were the only test types that I came across when reading unit test tutorials. I thought it was “the“ only way to do unit tests.
When I worked as a Technical Coach, every team I coached had only written and seen Solitary Unit Tests, and were shocked when I showed them Sociable Unit Tests. They asked: “So is that a unit test? We thought a unit test was small, one unit test per class.”
Now I’m going to share my story: Why did I switch to Sociable Unit Tests?
It’s not just me. I found the same story here:
Why does Vladimir Khorikov prefer Sociable Unit Tests?
Why did Google Engineers switch to Sociable Unit Tests?
Why does Uncle Bob advocate Sociable Unit Tests? ⬇️⬇️⬇️