Background Image
Table of Contents Table of Contents
Previous Page  428 / 478 Next Page
Information
Show Menu
Previous Page 428 / 478 Next Page
Page Background

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