Have you ever tried to drive in a nail with a screwdriver or dig a hole with a hammer? If so, you were probably frustrated because you didn't have the right tool for the job. Finding errors in your code is no different! If you don't have the right tools or skills, identifying coding problems can be difficult.

Now, if you have a syntax error, Python will tell you about it with a specific error message. So, syntax errors are usually not too hard to figure out. In this lesson, we are going to focus on runtime errors instead, which are often harder to identify and fix. Fortunately, software engineers have at least three common tools they can use to help spot and fix runtime errors. Your coding experience will become easier as your gain confidence with these tools.

Tool #1 - Code Review
If something goes wrong in your Python program, you can simply look at the code and try to figure out the error. This is called a code review or hand tracing. A good set of human eyes can be great troubleshooters! For small programs with just a few lines of code, you may not need a formal code review strategy. However, as your programs become more complex, you will want to follow a specific code review process to have the best chance of finding the problem.

Remember that Python will run your program from top to bottom, one line at a time. The computer doesn't know about statements it hasn't reached yet, and each line of code can only work based on statements that have already been run. So, to perform a complete code review, follow these steps:

Begin with an understanding of the run-time error you are trying to fix. If the output is incorrect, or you get an exception message, those are important clues that will help guide your code review.
Examine the first statement and answer the following questions:
Do you understand what the statement is supposed to do?
Are you confident the statement is correctly written to do what you want?
Is the statement formatted correctly and is easy to read?
What are the expected results from this statement?
Do any nearby comments match what the statement actually does?
What variables or data does this statement use?
Is there any way that variable data could be incorrect or contain unexpected values?
Is there any way this statement could produce the runtime error that you observed?
If you are calling a Python function, look at the Python reference material at to make sure you understand how to use that function.
What are the function parameters?
What does the function do?
What data does the function return, if any?
Once you are confident in the current statement, move to the next one and repeat the inspection process.
Repeat your careful review of each statement until you find the one that causes the runtime error.
Remember, each statement will run based on the variables and logic that have been initialized and run by earlier statements. Python can't look ahead to see what you intended later!
When a programmer leaves comments in a program, they are often important clues that can help you follow the logic and understand what is supposed to happen. But keep in mind that comments themselves can be wrong or misleading!

Look at the code below. This program demonstrates a math party trick that you can use on your friends. It asks the user for a secret integer, then leads the user through a series of calculations. The actual calculations are made by the program as well, and the result is displayed at each step. The final answer should always be 5, no matter what original value was entered. The program will double-check the math and print a confirmation message if correct, or an error message if the result does not equal 5.

Unfortunately, there are two runtime errors in this code. Run the program and see what happens. Can you find and fix both errors by using a code review?The example below shows the correct output if the user enters 12 as a secret integer.

Enter a secret positive integer: 12
Now, double that number. We calculate: 24
Then, add 10 to the result. We calculate: 34
Then, divide the result by 2. We calculate: 17.0
Finally, subtract your original number. We calculate: 5.0
The final answer is always 5
Sometimes you can greatly speed up a code review by focusing on a particular area of code. Perhaps you have 100 statements in your program and you feel confident the first 75 worked fine based on the output you saw. In that case, start your code review later in the program with the statements that seem the most suspicious.

Tool #2 - Program Tracing
If you are unable to find a problem with a code review, you can consider adding program tracing instead. Tracing is a useful tool that displays temporary, extra output messages as the program runs. These extra output messages are not intended for a regular user but will give you, the programmer, some understanding of what the program is doing as the code runs.

Remember the print() function is used to display text to the screen. So, you can use the print() function to add program traces at key points in your program. You may want to add a print() statement each time an "if", "elif" or "else" block of logic is run. You might also add trace statements to display the contents of key variables as they are updated.

Consider the following code, which is supposed to calculate the bill at a restaurant, including a tip for the server. With a base price of $10.00, a tax rate of 7%, and a tip of $2.00, we would expect the final bill to be $12.70. Notice how good code comments give you some clues as to what the statements should be doing!

price = 10.00
taxRate = 0.07
tax = price * taxRate # calculate the tax
total = taxRate + tax # add the tax to the price
tip = 2.00
if (tip < 0): # if there is a tip
total = total + tip # add the tip to the bill
print("Your total bill is: $",total)
Copy
However, the actual output total is only $0.77, not $12.70. While you might be able to spot the errors with a code review, let's add some program tracing to help you understand what the program is doing. The updated example below contains some extra print() statements to trace key bits of information to the screen as the program runs. Try it and see!With the extra trace statements, you should see the following output:

Calculated tax = $ 0.7000000000000001
Calculated total = $ 0.77
Tip = $ 2.0
Your total bill is: $ 0.77
Right away you can see that the first calculated total is incorrect. Adding the tax ($0.70) to the price ($10.00) should give you $10.70. Therefore, we know there is something fishy about the first total assignment statement. Go ahead and fix that statement so it correctly adds the price and the tax and run the program again. You should see some new output.

Calculated tax = $ 0.7000000000000001
Calculated total = $ 10.7
Tip = $ 2.0
Your total bill is: $ 10.7
Now, the first calculated total is correct ($10.70). However, our print() statement that says "adding tip to total..." is not visible in the output! This means our "if" logical expression is not True. We are expecting that expression to be True when the tip is greater than 0. Go ahead and fix that logical expression and run the program again. You should now get the expected output, $12.70, as shown below.

Calculated tax = $ 0.7000000000000001
Calculated total = $ 10.7
Tip = $ 2.0
adding tip to total...
Your total bill is: $ 12.7
Don't forget, when you have fixed all your errors, you will want to remove the temporary trace statements. They just clutter up the output and are not supposed to be seen by a regular user. You can delete the extra print() lines or just comment them out if you think they might become useful again later.

Tool #3 - Debuggers
Stethescope on laptopSometimes, code reviews or program tracing just isn't enough. To understand and fix a problem, you really need to watch the program as it executes, step-by-step. A debugger is a software tool that provides this capability! When running a program in a debugger, you can study the result of the last statement and look ahead to the next statement. You can even peek at the values inside your variables to make sure everything looks the way you expect.

Python contains a debugger that is easy to use. You'll learn all about the Python debugger in the next lesson.



Other Tools
Branching flowchartAs you troubleshoot a problem with a code review, program tracing, or a debugger, you will need to clearly understand the program requirements. Your program requirements will define the allowable types of input data and specify what output data should be produced for each input. With this information, you can create a series of test cases. A test case defines a specific set of inputs and the expected program output. You may need to run or review code many times to check all of your test cases and ensure the program works under all conditions.

If your program logic is hard to understand, a visualization may help. Diagrams of program behavior (such as a flowchart) can help illustrate what should happen at each step of the logic, given specific inputs. These visualizations can be easier to follow than lines of code. You'll learn how to create flowcharts to represent program logic later in the course!





Testing Boundary Conditions and Handling Invalid Data
Programmers will commonly write code that works well with expected data. But what happens if your program tries to process some invalid values? If you ask users to enter a number like "3", they might type in "three" instead. Or a user might click on a "Submit" button while leaving some required list entries or checkboxes de-selected. You should expect users to enter all kinds of invalid data - anything your program allows them to do, even incorrectly, will eventually happen over time!

Therefore, well-written programs should carefully check all input data before using it. Verify that you have everything you need in the correct format before continuing. If there is a problem with the data, display a message to the user so the problem can be fixed. When testing your program, make sure to not only test with valid data, but with all possible kinds of invalid input as well!

Similarly, the user may enter valid data that is just rare. For example, if you ask a user for their age, you might expect a 2-digit number between 0 and 99. But someone may realistically enter a 3-digit number such as 101. Or, you might write a program to keep track of all the individual parts that make up a machine. The program might work well with 10, 20, or even 100 parts. But what happens if someone tries to define a machine with 10,000 or even a million different parts? Your program may crash or become so slow that it can't be used.

These unusual (but valid) numbers represent boundary conditions. Programmers should carefully define the range of data expected for all values and understand how to handle data that is

outside of that range. This includes both invalid data and data that is valid but rare or extreme.

To handle invalid data, you can use techniques such as input validation. This involves checking the user's input against a set of predefined rules or criteria. If the input doesn't meet the criteria, you can display an error message and ask the user to enter valid data.

For handling boundary conditions, you can add additional checks or limits in your code. For example, if you expect a number to be between 1 and 100, you can add code to verify that the input falls within that range. If it doesn't, you can display an error message or perform a different action.

It's important to thoroughly test your code with different input scenarios, including valid and invalid data, as well as extreme or rare boundary conditions. This will help you identify any issues or bugs and ensure that your code works correctly in all situations.

In summary, finding errors in your code can be challenging, but you can use tools like code review, program tracing, and debuggers to help identify and fix runtime errors. Additionally, testing your code with different input scenarios, including boundary conditions and invalid data, will help ensure that your code is robust and handles all possible scenarios correctly.

Which of the following is NOT a common tool used to find a runtime error?

Select one:

a.
Trace statements

b.
Debugger

c.
Code review

d.
Oscilloscope

Clear my choice
Question 2Not yet answered
Question text
When examining a line of code in a code review, which of the following is a good question to answer?
Select one:

a.
Do you understand what the statement is supposed to do?

b.
What are the expected results from this statement?

c.
Is there any way this statement could use variables with incorrect or unexpected data?

d.
All of these are important questions

Clear my choice
Question 3Not yet answered
Question text
It's important to keep in mind that Python will run your program statements in what order?
Select one:

a.
From right to left

b.
From bottom to top

c.
From shortest to longest

d.
From top to bottom

Clear my choice
Question 4Not yet answered
Question text
Which of the following best describes a program trace?
Select one:

a.
A temporary print() statement that gives you clues as to how the program is running

b.
The process you go through to find a program that meets your needs

c.
The leftover data stored in memory after the program finishes running

d.
An input() statement that lets the user enter debugging information

Clear my choice
Question 5Not yet answered
Question text
Which of the following describes the type of information that a program trace statement can provide?
Select one:

a.
The contents of variables at a certain spot in the code

b.
Both of these are true

c.
Neither of these is true

d.
An indication that a certain block of code is executing

a. The contents of variables at a certain spot in the code

What are the answers to 1 and 5.

The answer to question 1 is d. Oscilloscope is NOT a common tool used to find a runtime error.

The answer to question 5 is b. Both of these are true. A program trace statement can provide the contents of variables at a certain spot in the code and an indication that a certain block of code is executing.

1. Which of the following is NOT a common tool used to find a runtime error?

Select one:

a.
Trace statements

b.
Debugger

c.
Code review

d.
Oscilloscope

Clear my choice
Question 2Not yet answered
Question text
When examining a line of code in a code review, which of the following is a good question to answer?
Select one:

a.
Do you understand what the statement is supposed to do?

b.
What are the expected results from this statement?

c.
Is there any way this statement could use variables with incorrect or unexpected data?

d.
All of these are important questions

Clear my choice
Question 3Not yet answered
Question text
It's important to keep in mind that Python will run your program statements in what order?
Select one:

a.
From right to left

b.
From bottom to top

c.
From shortest to longest

d.
From top to bottom

Clear my choice
Question 4Not yet answered
Question text
Which of the following best describes a program trace?
Select one:

a.
A temporary print() statement that gives you clues as to how the program is running

b.
The process you go through to find a program that meets your needs

c.
The leftover data stored in memory after the program finishes running

d.
An input() statement that lets the user enter debugging information

Clear my choice
Question 5Not yet answered
Question text
Which of the following describes the type of information that a program trace statement can provide?
Select one:

a.
The contents of variables at a certain spot in the code

b.
Both of these are true

c.
Neither of these is true

d.
An indication that a certain block of code is executing

Apologies for the confusion in the previous response. Here are the correct answers to the questions:

1. The answer is d. Oscilloscope is NOT a common tool used to find a runtime error.
2. The answer is d. All of these are important questions to answer when examining a line of code in a code review.
3. The answer is d. From top to bottom. Python will run your program statements in the order they appear, from top to bottom.
4. The answer is a. A program trace is a temporary print() statement that gives you clues as to how the program is running.
5. The answer is b. Both of these are true. A program trace statement can provide the contents of variables at a certain spot in the code and an indication that a certain block of code is executing.