So you think you write unit tests? Think again.
Here's another thing that gets under my skin: the term "unit test". Not that I have anything against them, they can be a fine tool (and at some future date I'll flesh out my developer test philosophy a bit more). No, what bothers me is that I see and hear the term misused all the time, and it causes a lot of confusion.
Where I work, developers frequently claim to have written "unit tests" for their code, when really they haven't. More often than not, what they've really written is an integration test. Don't get me wrong -- both kinds of tests are very useful, but they are not synonyms for each other. It's important to distinguish between them, because unit tests have an entirely separate set of goals, techniques, and best practices which do not apply to integration tests or other sorts of tests.
Here's a quick list of some of the different kinds of tests. It's not a complete list, but it should cover a lot of common terms you'll often see tossed around at work or in the literature. As you can see, there can be some overlap between the terms: for example, you may have a developer test which is also a unit test which may also be a checkin test as well. But keep in mind they are all orthogonal concepts, and can vary independently.
- Unit test: tests a function or class in complete isolation from other code in the system. If the item under test has dependencies, those dependencies are replaced by fake ("mock") objects. If it touches the filesystem, hits a database, access a network, or displays UI, it's not a unit test. Unit tests have practically no setup and run extremely fast.
- Integration test: tests the interaction of two or more classes and functions working together. Multiple layers are usually involved. Whereas unit tests ensure that the "bricks" in your system are square, solid, and uniform, integration tests ensure that they are stacked up correctly and glued together the right way. A test that verifies data entering one end of a pipeline will come out the other end is an integration test. So is a test that verifies that data is unchanged when round-tripped through a reversible process.
- Characterization test: tests unknown or "legacy" code for response to stimuli. Often used during refactoring to ensure that the behavior of the code is unchanged. Characterization tests are often written in total ignorance of the inner workings of the code, and the expected results are often completely unknown as well.
- Developer test: any sort of test (unit test, integration test, acceptance test, stress test) written by a developer as a design and development aid, as opposed to a QA engineer ensuring the correct operation of the code after the it has been "thrown over the wall" to Test.
- Automated UI test: a test that simulates a fixed series of user interactions, such as mouse clicks and key presses, and the resulting UI is then compared to an expected result.
- Regression test: a test which ensures that bugs that get fixed stay fixed.
- Checkin test: a series of tests used to verify that the product is not accidentally broken by new features or bugfixes, prior to the change being submitted. Checkin tests do not exhaustively test everything (they still need to run in a reasonable amount of time), but they should give good coverage over certain areas. Checkin test suites are usually mostly unit tests, because unit tests execute so quickly. But integration tests and regression tests can be good candidates for inclusion as well.