For labs in CS 2, you must work in pairs. For this lab, both partners must do the setup separately to be ready for the rest of the term. The main point of lab is to act as a bridge between lecture and the projects. We aim to give you an “intermediary” programming assignment which will help with the project. For this reason, all labs will be collaborative, and your lab TAs will be extremely helpful. If you get stuck, you should immediately ask for help rather than floundering. Lab is only an hour, and we want you to optimize the time you spend for maximum learning.
To get credit for a lab, you must call over a member of course staff to “check off” that you were present at lab.
Register for the Lab
Register for the lab using grinch
: https://grinch.caltech.edu/register and clone the repository
as explained in the setup instructions.
Pair Programming
Since you are pair programming with another person, please quickly skim this page.
Goals and Outcomes
In this lab, you will enhance your code reading abilities by debugging an existing class called GradeHistogram
, debugging two common Java errors, and finding the
passwords to make a programmatic bomb not explode.
Afterwards, you will apply your code reading abilities to enhance your code debugging abilities by debugging a text adventure we have written. We’ll guide you through this process, but the intention is to make this a realistic debugging experience.
By the end of this lab, you will…
- be able to read test failure messages
- know how to approach debugging code
- have learned about some common Java bugs
- be able to use the IntelliJ debugger to help discover bugs
- be able to read stack traces
- be better able to approach debugging code
- get experience with more of the kinds of errors you’ll run into during this course
If you do not finish during lab, don’t panic! You are allowed to continue working on lab outside of the lab period. If you were on time to your lab section and your Gitlab tests all pass before Thursday @ 11:30 PM, you’ve been checked off and you’re good!
Grading in CS 2
In CS 2, labs and projects will be graded on a “letter grade” basis. We’ll explain this more later, but, for now, you should know that passing the tests on gitlab
is the only
metric we will use to grade your code. There are no “style points” in this course.
Part 1: Debugging GradeHistogram
For this part of the lab, we will approach debugging the code by trying to understand where the tests are failing. To do that, we have to run the tests. Make sure “D Tests” is selected at the top of IntelliJ and click the green play button. The JUnit tests that we have written should run (and all fail!). Your job in this part is to fix the code to make them all pass.
Task 1. While you can read the test code itself, we would recommend reading the test output instead. Click on the name of the first test (“Test add/get”) and read the resulting trace on the right. You should see that the code threw an exception, but where? The blue text will link directly to the line of code that caused the exception. Your first task is to fix this exception by determining what the error is.
After you believe you’ve fixed the error, go ahead and run the tests again. If you’re stuck, feel free to ask someone on course staff for help; it’s what we’re there for. If the tests no longer throw an exception, you’re ready to fix the next bug. Repeat this process until all the tests pass.
After the D
tests all pass, move on to the second part of this lab, below.
Part 2: Da Bomb!
Using the IntelliJ Debugger
Up until now, you may have practiced debugging by placing print statements throughout your code to monitor the values of certain variables. When strategically placed, the output from these print statements may make the bugs obvious or help narrow down their location. This method is called print debugging. Though print debugging is a valid technique, it can be tedious deciding what to print and cleaning up your code after you are done.
Interactive debugging is a technique by which one debugs by using an interactive tool, or a debugger. We will show you the basics of how to use IntelliJ’s built-in debugger.
Setting Breakpoints
Before starting the IntelliJ debugger, you should set a few breakpoints. Breakpoints mark places in your code where you can suspend the program during a debug session and examine its state. This allows you to examine the values of multiple variables without needing to write print statements, and moreover, breakpoints are ignored when the program is executed normally.
To set a breakpoint at a line or a method, click in the gray area next to the line number.
A red circle or diamond should appear where you clicked. When the debugger reaches this point in the program, it will pause before the execution of the line or method. If you click anywhere on a line of code that has a breakpoint, a lightbulb icon will appear on the left and you can click on it to find more options regarding that breakpoint.
Starting the Debug Session
Once you have set some breakpoints, you are ready to start a debugging session! Click on the icon in the top right of the IntelliJ interface. The selected program should run until it hits its first breakpoint. A debugger window should also appear on the bottom of the interface, where the console was.
Under “Frames”, you will be able to see all current method calls, and under “Variables”, you will be able to see the values of instantiated variables at this point in the program (they will also be shown in gray text in the editor). From here, you have a few options:
- Learn something from the displayed values and fix your bug! Click to stop the debug session.
- Click to resume the program (until it hits another breakpoint or terminates).
- Click to advance the program by one line of code ( does something similar, but it will step into any method called at the current line, whereas will skip over it).
More Breakpoint Options
Sometimes you may want to have your program pause only on certain conditions. To do so, create a breakpoint at the line of interest and open the “Edit breakpoint” menu (by clicking the lightbulb or right-clicking the breakpoint icon itself). There, you can enter a boolean condition such that the program will only pause at this breakpoint if the condition is true.
Another thing you can do is to set breakpoints for exceptions in Java. If your program is crashing, you can have the debugger pause where the exception is thrown and display the state of your program. To do so, click in the debugger window and press the plus icon to create a “Java Exception Breakpoint”. In the window that should appear, enter the name of the exception that your program is throwing.
If you are curious to learn more about IntelliJ’s debugger, you can find the help guide at https://www.jetbrains.com/help/idea/debugging-code.html.
Task 2.
The BombMain
class calls the phase
methods of the Bomb
class. Your job is to figure out what the passwords to each of these phases are by using the IntelliJ
debugger. Trying to run through the code by hand is guaranteed to not work, and you are forbidden from adding print
statements into the Bomb
code.
The point of this exercise is to get comfortable using tools that will help you a lot down the road. Please take it seriously!
Make sure the C and D tests pass locally at this point! From here on out, the tasks are related to the A Tests!
Part 3: Debugging the Text Adventure
Run the (broken) Game and the (failing) Tests
The very first thing you should do is run the main function in AdventureGame.java
. This will give you a sense of what the program you are debugging is actually
supposed to do. Then, after you’ve run the game, run the tests; they should fail on BirdCountingStage
which will lead you into debugging the first error below.
Debug BirdCountingStage
When a runtime error occurs in Java, a stack trace is printed to the console to provide information on where the error occurred and what steps the program took to get there. When running the tests for the first time, your stack trace will look like this:
The first thing to note is what kind of error occurred; this is shown at the first line of the stack trace. In this case, our code threw a NullPointerException
.
The lines beneath it represent the sequence of methods the program took to arrive at the error: the first line in the list is where the error occurred, and the line beneath it represents the line of code that called the method which threw the error, and so on.
Task 3.
Fix the NullPointerException
that occurs in BirdCountingStage
by analyzing the stack trace that the program gives you. In general, you can ignore lines the lines
with <XX internal calls>
: these are contained in the test code and usually won’t give insight to the error.
It turns out that this isn’t the only error in this class!
Task 4.
Fix the IndexOutOfBoundsError
that occurs in BirdCountingStage
.
Note: Ignore the grey links to Objects.java
and ArrayList.java
at the top of the stack trace. The grey links are almost always due to code that you didn’t write. In this case, they occur in Java’s libraries which are called from your code.
Debug PalindromeAnimalStage
Task 5.
Sometimes, IntelliJ will tell you something that it thinks is wrong. Hover over the orange highlights in the method with the bug. Does that give you any useful information? Use this feature to fix the error(s) in PalindromeAnimalStage
.
Still Broken :(
Task 6.
At this point, the first test should pass. That test is testing a correct input to the adventure game. The second test tests an incorrect input (meaning one that gets
something wrong at some point during the game). Go back to the SpeciesListStage
and find the bug. (Hint: Use what you learned in task 5.)
Submitting Your Code for Credit
Your code will be autograded when you submit it to gitlab
. You may submit to gitlab
as many times as you like, and only the last submission will be counted.
Committing and Pushing to the Repository
A “commit” is version control language for a chunk of changes that mean something when grouped together. Importantly, commits will only stay locally on your machine
until you push them to the gitlab
server.
Task 7.
To commit to the repository, click the green checkmark on the top-right of IntelliJ’s interface. A window will pop up and
ask you to type in a message. Choose some meaningful description of your feature, then click the little down arrow next to the “Commit” button on the bottom right of the dialog.
Choose “Commit and Push” in the little menu that pops up. If IntelliJ asks you if you’re sure you want to commit and push, say yes.
Checking the Results on gitlab
When you go to https://gitlab.caltech.edu, you should see your lab01
repository listed. Click on it. All the way on the right, there should be a red “X”,
an orange “pause” symbol, a blue “time” symbol, or a green “check” symbol. This symbol indicates the status of the automated tests which will
check the correctness of your code. Click on it. On the new page, you should see a table, and under “status”, there should be another symbol. Click on it. The new page will list
the “categories” of tests for this repository. These will be some combination of “A”, “B”, “C”, and “D”. These letters indicate what grade you earned on the assessment for
passing those tests. If you click on one of them, it will detail for you which sub-tests you passed and failed which might help you debug.
It is good practice to always check gitlab
after submitting a project or lab in this course.
Task 8. Check to make sure you are passing all the tests on gitlab.