Most people in the software industry have heard of test-driven development — it has become a buzzword with several possible meanings.
One of the more negative associations is the notion of unit testing. Unit testing traditionally involves writing a test for each and every routine in a unit or class, to ensure that it does what it claims. This practice has, of late, declined in popularity — mostly because of the sheer mindlessness of maintaining complete coverage of an ever-growing API.
Another form of testing is to write tests for components of a system, ensuring functionality on a higher level than that of the routine. Tests of this kind tend to encapsulate use cases, which are far more closely related to the way in which clients (actual users or other software) make use of an API. Naturally, use cases for extremely low-level components will end up testing individual routines, just as unit testing does.
Writing the component tests is not tedious and, in fact, helps tremendously in determining whether a piece of software is complete or not. They can be viewed as software implementations of the requirements documents or specifications. Proper application of Component-based Design makes it quite simple to build tests for the majority of an application's functionality.
A far better tool for ensuring consistency at the lowest level, where unit testing traditionally comes into play, is Design by Contract. This practice involves including verification mechanism directly in the software, so that violations of software contracts can be pinpointed and quickly repaired.
The most important element of any testing strategy is to stick with it. When a defect is found, the first step is to create a test to replicate the problem. The next is to fix the error so the problem no longer occurs, but all the other tests still work. Finally, any missing contracts that may have helped pinpoint the problem sooner should be added.
Once the test suite runs through without problems, the software is ready for release testing.
Automated testing is a fantastic way of guaranteeing baseline software quality, but it is not the last step before releasing a product. For server software or software with a command-line interface only, the test suite can provide an extremely high-level of coverage (approaching 100%). Software which interacts with humans, however, requires a manual testing regimen to verify that the software funtions as desired for all forms of input. Whichever parts of the testing chain cannot be automated (UI testing is notoriously difficult) should be documented in detail to ensure reproducability between releases.