And Unit Tests Drive Good Design
But perhaps more importantly than any of this, remember the lesson from
Chapter 19 .Going through the process of writing good, isolated unit tests can help us drive out
better designs for our code, by forcing us to identify dependencies, and encouraging us
towards a decoupled architecture in a way that integrated tests don’t.
The Problems with “Pure” Unit Tests
All of this comes with a huge “but”. Writing isolated united tests comes with its own
hazards, particularly if, like you or I, we are not yet advanced TDD’ers.
Isolated Tests Can Be Harder to Read and Write
Cast your mind back to the first isolated unit test we wrote. Wasn’t it ugly? Admittedly,
things improved when we refactored things out into the forms, but imagine if we hadn’t
followed through? We’d have been left with a rather unreadable test in our codebase.
And even the final version of the tests we ended up with contain some pretty mind-
bending bits.
Isolated Tests Don’t Automatically Test Integration
As we saw a little later on, isolated tests by their nature only test the unit under test, in
isolation. They won’t test the integration between your units.
This problem is well known, and there are ways of mitigating it. But, as we saw, those
mitigations involve a fair bit of hard work on the part of the programmer—you need to
remember to keep track of the interfaces between your units, to identify the implicit
contract that each component needs to honour, and you need to write tests for those
contracts as well as for the internal functionality of your unit.
Unit Tests Seldom Catch Unexpected Bugs
Unit tests will help you catch off-by-one errors and logic snafus, which are the kinds of
bugs we know we introduce all the time, so in a way we are expecting them. But they
don’t warn you about some of the more unexpected bugs. They won’t remind you when
you forgot to create a database migration. They won’t tell you when the middleware
layer is doing some clever HTML-entity escaping that’s interfering with the way your
data is rendered … something like Donald Rumsfeld’s unknown unknowns?
Mocky Tests Can Become Closely Tied to Implementation
And finally, mocky tests can become very tightly coupled with the implementation. If
you choose to use
List.objects.create()
to build your objects but your mocks are
400
|
Chapter 22: Fast Tests, Slow Tests, and Hot Lava