CS 261 Lab C - Debugging

Due Wed Sep 17 at 3:00pm

Overview

"If debugging is the process of removing software bugs, then programming must be the process of putting them in." - Edsger Dijkstra

Finding and removing errors in programs ("debugging") is probably the most common, most important, and most difficult task in implementing computer programs. Luckliy, there are plenty of tried and true methods to help identify errors, and Eclipse is able to offer further support.

This lab will walk you through the debugging process and how to use the Eclipse debugger, and give you a chance to practice and experiment with it. Note that while you may be able to find and fix the bugs on your own, you should try and use the debugger so that you are familiar with the Eclipse tools (which will incredibly helpful later!).

This lab will be completed in pairs. Partner assignments for this lab can be found on Moodle

Objectives

Necessary Files

You will need to download the copy of the zipped source files and import them into Eclipse (see previous lab for instructions). These files contain SampleProgram.java, a set of sample code to practice using the Debugger; StringProcessor.java a somewhat buggy class that you will need to fix; and StringProcessorTester, the beginnings of a tester class for you to fill in. I've also provided a bugger PrimeFactorization class as an extension.

Background: Test Cases

The first step to fixing a program that doesn't work is realizing that the the program doesn't work. We do this by testing the program. Testing has 3 steps:

  1. Figure out what the result of the program should be
  2. Run the program
  3. Check if the result of the program matches step 1

Step 1 is really important--do not skip it! In order to know if a program works, you need to know what it is supposed to do. Think about this beforehand--work through a program in your head or on paper, so that you know what the answer is supposed to be.

In order to test that a particular method works, you want to create a number of test cases. A test case is a specific input you will give to a program (e.g., what values you will pass as parameters) as well as the expected output of the program. For example, if we had an add() method that added two numbers together, then we might have test cases such as:

Input: add(1, 1); Expected Output: 2

Testing a program involves coming up with a list of test cases, writing a Tester class that runs those cases, and then seeing if they work or not. If a test input didn't produce the output you expected, then you have found an error! For example, if we ran our method add(1, 1) and got 3 as the output, then we know there is a problem.

The trick is to come up with good test cases, so you can be sure your program works no matter what the input is. One way to write good test cases is to be sure and test boundary conditions. These are the "edge cases" where things may be different. For example, our add method might test when we have two positive numbers, two negative numbers, one positive and one negative, and where one or both of the numbers are 0. We also might test with really small numbers and really big numbers, in each spot. The key is to get good coverage of all the possibly inputs to our method.

Your goal is to try your darndest to break the program. If you succeed, you've found a bug and are a winner!

Background: Print Statements for Debugging

"The most effective debugging tool is still careful thought, coupled with judiciously placed print statements." - Brian Kernighan, "Unix for Beginners" (1979)

The above quote from Brian Kernighan (one of the inventors of the C language) remains true in Java--print statement debugging can be one of the most effective methods of debugging a program. Or at least one of your professors' favorite methods. The basic idea is thus: in order to figure out whether a program is working, we need to know what the program is doing. Which means we want to know things like the value of variables at any particular time, whether or not we've gotten into a particular method or loop, etc. This can be fairly intuitive process--basically if you want to know about something your program is doing, just put a print statement to tell you!

Some hints for doing print-statement debugging

Part 1: The Eclipse Debugger

The main goal of using print statement debugging is to be able to "inspect" the current state of the program as it is running--to get a sense for what code is being executed when and how often, and what the values of variables are at any particular moment.

However, this kind of inspection can be automed with Eclipse's Debugger, a tool built into the IDE.

Despite the name, the debugger won't actually fix bugs for you--instead, it is a tool that helps you to "walk" through your program running each line of code one at a time, in order to inspect what the code and variables are doing at any particular moment. The debugger will not locate the logical error for you. You need to be able to understand the code and its intention, using the debugger to observe the program's behavior. That said, the debugger can be a very handy tool!

Your first task will be to follow a tutorial and learn how to use Eclipse's debugger. Because we are interested in re-use in CS, I am going to re-use a tutorial written by Deb Deppeler at UW-Madison. This tutorial can be found at:

http://pages.cs.wisc.edu/~cs302/?r=labs&labNumber=7

You should follow the tutorial and complete the step labeled "Task 1: Learning How Eclipse Helps do Debugging". You will need to use the SampleProgram code that you downloaded with the lab files.

Part 2: Testing and Debugging

Once you understand how the Debugger works, your second task is to debug the included StringProcessor class. This class has 4 methods--plus the getter, setter, and constructor. Most if not all the methods have bugs (usually more than one!).

You should debug this class using the following procedure:

  1. Write a test case for the StringProcessor inside the StringProcessorTester. This test case should call one of the methods and print out the expected and actual result of the method.
    • Be sure and check all the boundary conditions you and your partner can think of, so you can be sure and catch all the errors!
  2. When you identify an error, use the Eclipse Debugger to inspect the code as it is running, setting appropriate break points as needed
    • While you may be able to fix the bugs with print statements or even just by considering the error, I highly recommend you practice with the debugger. While it may seem a tad overkill for this lab, it will quickly become helpful in the future.
  3. Once you have identified the error, fix the bug!
  4. Re-run your StringProcessorTester class and confirm that the bug is fixed!
    • DO NOT DELETE TESTS THAT PASS! Leave all tests in your StringProcessorTester, so that ypou can confirm that methods continue to work even if you change other parts of the class. This will also allow us to see what test cases you use (which is part of the lab grade).
    • If things get messy, you can always comment out your test cases momentarily, or refactor them into individual methods that get called from main (e.g., public static void testMethod1())
  5. Return to step 1 and repeat until you have thoroughly tested the class.

Try to catch all the bugs--there are a lot (and some are more tricky than others). Gotta catch 'em all! Extra credit will be given to the pair that finds the most bugs.

Extensions

If you finish early, you might try debugging the PrimeFactorization class found in the lab files. It isn't necessarily harder to fix, just another thing to try to make sure you're really comfortable with the tool.

Submission

Make sure both your names are on the StringProcessor and the StringProcessorTester. Once you're finished, upload the src code to the LabC submission folder on hedwig. One partner should to upload the code--we will only grade one partner's copy of the program. Make sure you upload your work to the correct folder! The lab is due at the start of class the day after lab.

After you have submitted your solution, log onto Moodle and submit the Lab C Partner Evaluation. Both partners need to submit evaluations.

Grading

This assignment will be graded out of 24 points: