A Patronizing Guide to What Makes a Good Unit Test ☃ Michael Hudson Launchpad Epic, Prague, July 2010 Launchpad has a lot of tests Not all of them are what one would call "good" Most of the bad ones are old, we're getting better! I'm aiming to (start to) provide a language which allows us to explain *why* a particular test is bad So here are some *Principles of Test Automation* 0. The code in your test method is almost unique in that it cannot be tested This means that it needs to be *obviously correct* Aside: all test code can be categorizes as Set up, Exercise, Verify or Tear Down 1. Each test should test one "thing" In particular, if you exercise, verify, exercise some more and verify again, you're violating this principle This is bad, because it can be unclear which things from the first "exercise" are important to the second "verify", and uncertainty about test code is the enemy of understanding 2. Be wary of implicit set up -- set up that runs before your test method Sample data is an extreme case of this Layers, too Implicit set up that aids test isolation is probably OK 3. Use automated tear down (i.e. addCleanup) Teardown is usually very boring 5. *Communicate intent*, particularly by being trigger-happy at writing test method with *intent revealing names* You can see this as building a domain specific language for your test It also helps keeping your test methods short, which helps with the "obviously correct" goal 6. Learn the difference between direct and indirect inputs and outputs Suppose we're testing a method An argument to the method is a *direct input* An attribute the method accesses is an *indirect input* The return value is a *direct output* An attribute the method sets is an *indirect output* A test that verifies a particular *direct input* leads to a particular *direct output* is the easiest kind of test to understand Structure your code to exploit this 7. Read (at least the first part of) "xUnit Test Patterns" by Gerard Meszaros 8. Some final words: *hamcrest* and *testtools.matchers* *behaviour verification* vs *state verification* *fakes* vs *mocks* vs *stubs*