CS101: Documentation, Testing, and Debugging

Copyright © 1996-97 Kenneth J. Goldman

Documentation is textual information within a program that helps convey the meaning of the program to human readers who need to understand, modify, or debug the program.

Forms of Documentation

(See also the CS101 Style Guide.)

In CS101, we will concentrate on the first 3 forms of documentation. You will see examples of external documentation in CS101, and may begin writing some of your own external documentation in CS102. All of your code in CS101 should conform to the CS101 Style Guide.

Principles of Testing

Testing is a comprehensive organized effort to exercise all aspects of a software system for possible failure.
  1. Successful testing is not a proof of correctness (unless you try every input exhaustively), but it can provide useful reassurance.
  2. Design test cases. Testing should not be "random."
  3. Know what the expected results of your tests should be. Otherwise, you might not recognize an incorrect result.
  4. Always be aggressive about testing. If you test gingerly, you won't uncover as many errors. Remember, the objective in testing is to find errors.
  5. Save your test program (and the expected results) so you can run it again later. Whenever modifying a program to fix one problem, there is a risk that you might have caused a different problem, so it's best to repeat all the tests.

Taxonomy of Program Errors

Correcting Compiler Errors

The compiler reports the approximate location of the error and a vague description of it. In Emacs, use the middle mouse button (if there's no middle mouse button, click both mouse buttons simultaneously) to click on the highlighted portion of the error message to find that location in the code. Then study that line, as well as a few previous lines, for the error. Check any procedure call on that line for proper number, order, and types of arguments.

Note: Errors may cause the compiler to go "off course." Try correcting the first few errors and running the compiler again.

Correcting Run-time Errors (Debugging)

  1. Avoid it. Taking the time to write a correct and well-documented program from the outset will pay back many times over. Finding and correcting bugs takes a lot of time, and it can be frustrating, especially if documentation is insufficient. However, nobody writes perfect software all the time.
  2. Debug on a small scale. Thoroughly test each component of an application (each method of each object) piece by piece, correcting errors as you go. This is much easier than finding errors in a large program.
  3. Understand the symptom. Before changing a program, understand the error and where in the program it occurred. Look at what the program tried to do and where it went wrong.
  4. Reason about each error, trying to understand how it could have arisen. This is an important problem-solving task. Form several hypotheses about how the error might have arisen and explore them.
  5. Find the source of the error. Don't waste time making "random" changes to your program. After reasoning about the error, you can start searching back through the execution of your program to see where things went wrong. A debugger can help.
    1. Examine the call stack and the values of parameters and local variables. See if it matches your expectation of what the program "should" do.
    2. Trace through an execution of your program by hand and with a debugger, stopping at certain points in the execution and/or printing out values along the way.
  6. Correct the error and test thoroughly.

Using a Debugger

Debugging is best when you don't have to do it, but knowing how to use a debugging tool can make the debugging process a lot less painful. In CS101, we will use the debugger built into the Emacs JDE, but most debuggers provide similar functionality. However, try to think first before entering the debugger.