The Clean Code Talks - Unit Testing
This Google tech talk is about the benefit of unit tests. It starts out asking one fundamental question: how do you write hard to test code? Despite most developers(myself included) being good at writing hard-to-test code, most aren’t quite sure how to do it. The speaker describes some of these ways; mixing the ‘new’ operator in business logic, looking for things, doing work in the constructor, global state, and deep inheritance, among others. All of these make it hard to isolate specific parts of the code to test - in the deep inheritance case, you’re also testing superclasses; in the other cases, you can’t isolate one function from all the other functions. It’s also hard to test purely procedural code - there are no ’seams’ that can be exploited to isolate specific parts.
The speaker then describes the progression of levels of testing. The highest level are scenario tests. These test the whole application, doing something a user would do and ensuring the correct thing happens. These test the whole app, which makes them slow; if the test fails, it’s also hard to know precisely where the test failed; you generally have to trace through with a debugger in order to find the specific place.
The next level of testing are functional tests. These test specific subsystems, with simulators for external parts. These are much faster than scenario tests, and you have a better idea of what failed. However, you still don’t know precisely what went wrong - If you’re testing a radio and it doesn’t work, you don’t have much of an idea why. You still have to use a debugger to isolate the point of failure.
This leads to the bottom level of testing: unit tests. These test individual classes in isolation from one another. They are very fast - the speaker suggests running them whenever you save. If all your unit tests pass, you have a high confidence that the class in question is OK, even though you are unsure about the interaction between class. It’s also very easy to figure out what precisely went wrong.
The speaker stressed that this is a continuum of tests; you shouldn’t have only unit tests or only scenario tests - you should have both, although unit tests are more important. It’s also important to have ’seams’, where you can inject the class’s dependencies in order to mock out their behaviour. This is done using dependency injection, where a class asks for its dependencies in the constructor. Going back to before, a class should be either in the business of construction or finding objects, or doing actual work - it’s easy to test either of these methods, just hard to test a method that mixes the two.
Tags: google tech talk