---
# System prepended metadata

title: Jam 03 - Exercise 2 - Basic Debugging Tools
tags: [jam03, debugger, print debugging, "3 \U0001F9EA in testing", debugging, "4 \U0001F973 done"]

---

---
title: "Jam 03 - Exercise 2 - Basic Debugging Tools"
tags: 
  - 3 🧪 in testing
  - 4 🥳 done
  - jam03
  - debugging
  - print debugging
  - debugger
---
<!-- markdownlint-disable line-length single-h1 no-inline-html -->
<!-- markdownlint-configure-file { "ul-indent": { "indent": 4 }, "link-fragments": {"ignore_case": true} } -->

{%hackmd dJZ5TulxSDKme-3fSY4Lbw %}

# Exercise 2: Basic Debugging Tools

## Overview - Exercise 2

In this exercise, you'll learn two fundamental approaches to debugging: print statements and using IntelliJ's debugger. We'll start with the simpler print debugging approach and then progress to using the debugger's more powerful features.

## The Problem - Exercise 2

When working with regular expressions, it's often hard to understand why a pattern matches or doesn't match just by looking at the output. We need to be able to:

- See what input is being tested
- Watch how the pattern matching process works
- Understand why matches succeed or fail

Let's learn two different approaches to solving this problem.

## Required Steps - Print Debugging

### 1. Print Debugging

Let's start with the simplest debugging approach - adding print statements to see what's happening in our code:

1. Open `PatternMatcher.java`
2. Find the `testPattern` method
3. Add the following print statements exactly as shown. Notice each debug line has a special comment `// DEBUG-LINE` - we'll use this later to clean up our code:

    Note: Make sure to add the print statements exactly as shown and every added line ends with a `// DEBUG-LINE` comment!

    You are only adding the print statements.  The lines that do not state // DEBUG-LINE are to help you find *where* to add the statements

```java
static void testPattern(String testType, Pattern pattern) {
// 1. Add this line at the start of the method
System.out.println("\nTesting " + testType + " with print debugging:"); // DEBUG-LINE
```

---

```java
String input = test[0];
String expected = test[1];
// 2. Add this line after getting the input
System.out.println("\nInput: " + input); // DEBUG-LINE
```

---

```java
Matcher matcher = pattern.matcher(input);
// 3. Add this line after creating the matcher
System.out.println("Before matches(): " + matcher); // DEBUG-LINE
```

---

```java
boolean matches = matcher.matches();
// 4. Add this line after matches()
System.out.println("After matches()/find(): " + matcher); // DEBUG-LINE
```

---

```java
boolean found = matcher.find();       
// 5. Add this line after find()
System.out.println("Result: " + (found ? "valid" : "invalid")); // DEBUG-LINE
```

Run your program and you should see output like this:

```text= !
Testing phone numbers with print debugging:

Input: (123) 456-7890
Before matches(): java.util.regex.Matcher[pattern=<<your pattern here>> region=0,14 lastmatch=]
After matches()/find(): java.util.regex.Matcher[pattern=<<your pattern here>> region=0,14 lastmatch=(123) 456-7890]
```

This output helps us see:

- What input we're testing
- The state of the matcher before and after trying to match
- The final result of the match attempt

Try running this with your patterns and observe how the output changes for different inputs. Pay special attention to:

- How the matcher's state changes after calling `matches()` or `find()`
- What information is shown in the matcher's string representation
- The differences between valid and invalid inputs

:::warning
🔧 **Cleaning Up Debug Statements**

After you're done debugging, use IntelliJ's Find and Replace with regex to remove all the debug print statements:

1. Press `Cmd+Shift+R` (Mac) or `Ctrl+Shift+R` (Windows) to open Find and Replace
2. Click the regex button (.*) in the find dialog
3. In the find field, enter: `.*// DEBUG-LINE.*\n`
4. Leave the replace field empty
5. You should have 5 matches as shown in the screenshot below (if you don't, make sure you added the debug print statements exactly as shown)
6. Click "Replace All"

This will remove all lines that end with `// DEBUG-LINE`, cleaning up your code in one step!
![Clean up Debug Prints](https://hackmd.io/_uploads/ryeCNjZY1l.png)
:::

### 2. Introduction to the Debugger

While print debugging is simple and useful, IntelliJ provides a more powerful tool - the debugger. Let's learn how to use it:

1. What is a debugger?
   - A tool that lets you pause your program
   - Examine the current state
   - Step through code line by line
   - Watch how values change

2. Key Concepts:
   - Breakpoints: Places where the program will pause
   - Variables window: Shows current values
   - Step controls: Move through code
   - Call stack: Shows where you are in the program

Let's start by setting our first breakpoint.  A breakpoint tells the debugger "stop here and let me look around." Let's set our first breakpoint:

1. Open `PatternMatcher.java` in IntelliJ
2. Find the line `String input = test[0];` in the `testPattern` method
3. Click in the left margin next to this line (the gutter)
   - A red dot will appear
   - This is your breakpoint!
   ![Breakpoint](https://hackmd.io/_uploads/BkjQ-qWFkl.png)

:::info
🔑 **What is a Breakpoint?**
Think of a breakpoint like a pause button for your code. When your program reaches a line with a breakpoint:

- The program stops
- You can see all the current values
- You can control what happens next

:::

### 3. Using the Debugger

Now that we have a breakpoint, let's run our program in debug mode:

1. Find the green bug icon in the toolbar
   - It looks like a little beetle/ladybug
   ![Debug icon](https://hackmd.io/_uploads/r12OW9Wtkl.png)

2. Click the bug icon
   - Your program will start running
   - It will stop at your breakpoint
   - A new pane will appear
   ![Debug Pane](https://hackmd.io/_uploads/Bk4AZcWFkx.png)

### 4. Understanding Debug Windows

The debugger shows several important windows:

1. Variables: Shows all current variable values
   ![Variables](https://hackmd.io/_uploads/HyFVGqZKke.png)
   - IntelliJ also shows variable values directly in your code:
   ![IntelliJ Variable Comments](https://hackmd.io/_uploads/ByhNSqWYJg.png)
   - These inline values update as you step through your code!

2. Threads: Shows the execution stack and where your code is running
   ![Threads](https://hackmd.io/_uploads/SkZIGcZt1l.png)

3. Console: Shows program output
   ![Console](https://hackmd.io/_uploads/ry-Tz9-KJe.png)

4. Debug Controls: Tools for stepping through code
   ![Debugger](https://hackmd.io/_uploads/HkmFfqWFkl.png)

### 5. Basic Debugging Controls

When stopped at a breakpoint, you have several ways to control program execution:

1. Step Over (F8) ![Step Over](https://hackmd.io/_uploads/rJZXXqWYyg.png):
   - Executes the current line
   - Moves to the next line
   - Use this most of the time

2. Step Into (F7) ![Step Into](https://hackmd.io/_uploads/HytV7q-tJe.png):
   - Goes inside method calls
   - Shows you what happens inside methods
   - Use this to see how `matches()` and `find()` work

3. Step Out (Shift + F8) ![Step Out](https://hackmd.io/_uploads/SkD-N9WY1x.png):
   - Finishes executing the current method
   - Returns to where it was called
   - Use this when you're done debugging inside a method

4. Resume (F9) ![Resume](https://hackmd.io/_uploads/By9HQqZtyl.png):
   - Continues running until the next breakpoint
   - Or until the program ends
   - Use this to skip to the next interesting part
   - Best way to move to the next loop iteration if your breakpoint is inside a loop

Try each of these controls now:

1. Use Step Over (F8) to execute the line getting the input
2. Look in the Variables window to see what `input` contains
3. Step Over a few more times to see how the values change
4. When you're done examining this test case:
   - Use Resume (F9) to run until the next breakpoint
   - Or move your breakpoint to a different location

### Debug Task 1: Examining Pattern Matching

To copy variable values from the Variables window:

1. Right-click on the variable
2. Select "Copy Value" from the menu
![image](https://hackmd.io/_uploads/Hk6fI9-tJx.png)

Add your answers to the following questions in `answers.txt`:

>[!Important] **Debug Task 1 Questions**
>
>(Q2.1) What is the value of `input` when testing the first phone number?
>
>(Q2.2) What happens to the `matcher` object *after* calling `matches()` (after means after running that line of code, e.g. it's no longer highlighted as the active line)?
>
>(Q2.3) What changes in the Variables window when you step over the line boolean matches = matcher.matches(); or boolean found = matcher.find(); depending on which case you are in?

### Wrapping Up Basic Debugging

Before moving on to the next exercise:

1. Verify that you can:
   - Add and remove print statements
   - Set and remove breakpoints
   - Use the basic debugging controls (Step Over, Step Into, Resume)
   - Complete Debug Task 1

2. Stop your debugging session:
   - Click the red square Stop button or press `Cmd+F2` (Mac) / `Ctrl+F2` (Windows)
   - The debugger will close and your program will stop running

## Save Your Work - Exercise 2

Verify what files are uncommitted:

```bash
git status
```

:::warning
🔧 **Check Your Debug Lines**

If you see uncommitted changes in `PatternMatcher.java`, it might mean some debug print statements weren't removed. This can happen if:

- The `// DEBUG-LINE` comment wasn't added exactly as shown
- There were typos in the comment
- Extra spaces were added before or after the comment

If any debug lines remain, just remove them manually - it's often quicker than trying to fix the comments and run Find and Replace again.
:::

Stage your changes:

```bash
git add src/main/java/jam03/answers.txt
```

Commit your work:

```bash
git commit -m "jam03: Complete basic debugging exercises"
```

Your working directory should now be clean.
