Page 170 -
P. 170

Test-Driven Development
                          Test-driven development means that the unit tests are created before the code is built. Before
                          a programmer begins to build a new object, she must first create the test case that verifies
                          that object. By the time the test case is finished, she has defined all of the expected inputs,
                          outputs, boundary cases, and error conditions for the object, and she has a test case that
                          verifies that it works. As she builds each part of the object, she can run its unit tests to ver-
                          ify the code that has just been built. Many defects found by testers or users have to do
                          with unexpected inputs or error conditions; since the programmer has already planned
                          out all of the ways that the object might fail, she will catch many more of these the first
                          time she builds the software.
                          Test-driven development also helps programmers understand the requirements better. It’s
                          possible—and often tempting—to begin coding with only a partial understanding of what
                          it is that the code is supposed to do. It is not uncommon for a programmer to “go off half-
                          cocked” and begin coding before really taking the time to understand the behavior of the
                          code. This is understandable; it’s more fun to write code than it is to sit and pore through
                          requirements documents. It’s even more tempting when there are no requirements docu-
                          ments. If the programmer has to build the software simply based on notes from some con-
                          versations and a vague understanding of the scope, it’s much more fun to just jump in and
                          start coding! Taking the time to write the unit tests really firms up the requirements in the
                          programmer’s mind, and often helps her to see exactly where she is missing information.
                          There are several important benefits of test-driven development. The most obvious one is
                          that it guarantees that unit tests are always written. When a team is under pressure to
                          release, it’s very tempting to release the code that seems to work. And when the unit tests
                          are the last thing that the team has to do, a senior manager facing a deadline will often
                          decide to release the build as is. Without the unit tests, the code will have more defects.
                          These defects will have to be fixed later, often after the programmers have moved on to
                          other projects and this code is no longer fresh in their minds.

                          Another important benefit of test-driven development is that the unit tests have a very
                          positive influence on the design of the code and the object model. Many design problems
                          stem from the fact that when an object is built, the programmer makes a decision about

                          the interface that later turns out to make that interface difficult to use. By the time she
                          writes code that uses that interface, the object is already written, and it may be difficult to
                          rewrite it to accommodate the way it really needs to be used. The unit test forces her to
                          start by writing code that uses the object; many poor interface decisions immediately
                          become apparent, before the code for the object is written.

                          A complete suite of unit tests also makes it much easier to refactor the software. The unit
                          test suite can be run after each refactoring, helping the programmers to immediately iden-
                          tify any defects that they might have accidentally injected. Running unit tests after each
                          refactoring removes most of the risk and ensures that the refactoring really does not alter
                          the behavior of the software.




                   162  CHAPTER SEVEN
   165   166   167   168   169   170   171   172   173   174   175