DEV Community

Masafumi Saito
Masafumi Saito

Posted on

Python Testing and Debugging for beginners

Python Testing and Debugging

Today, I want to share some thoughts on errors and debugging that we encounter all the time when writing programs, plus some strategies to prevent them.


Specifications, Testing, and Debugging

First, let's clarify some terms.

Specification

A specification is what you want to achieve by writing your program.

Testing

Testing means actually running your program to see if it meets the specification. The input and expected output pairs you use for testing are called test cases.

Debugging

Sometimes when you test your program, it doesn't work as specified. We call these issues bugs, and the process of fixing them is called debugging.

Development Flow

  1. Analyze the specification
  2. Write the program
  3. Test it
  4. Debug it
  5. Test again...

You keep repeating steps 1-4 in a loop.


Useful Statements for Debugging

assert Statement

The assert statement is super useful for testing and debugging.

It declares that the condition following assert should be True. If it's false, you get an AssertionError.

Here's what happened when I triggered an AssertionError in my terminal:

Terminal showing AssertionError when assert condition fails

The assert statement stays quiet when conditions are met, but throws an error when they're not. This makes it perfect for checking preconditions in your program.

print Statement

The print statement is your next best friend.

It's super handy for checking what's happening inside functions during execution. Local variables (variables defined inside functions) can't be accessed from outside the function, so print statements help you peek inside.

Let's look at an example with a function that takes x, y, z arguments and swaps x and y:

Terminal output showing variable values using print statements for debugging

The AssertionError tells us something's wrong, but it's hard to figure out exactly what. That's where print statements come to the rescue.

Using print statements, we can see that after the first if statement, the local variable values got messed up.

By adding a local variable, we can get the intended behavior and make the AssertionError disappear.


Types of Errors

There are basically three types of errors.

Syntax Errors

Syntax errors happen when your code doesn't follow Python's rules.

Common examples:

  • Forgetting to close quotes or brackets

Python SyntaxError: EOL while scanning string literal - missing quote

  • Forgetting colons

Python SyntaxError: invalid syntax - missing colon after if statement

  • Messed up indentation

Python IndentationError: expected an indented block

Syntax errors don't happen during program execution - they prevent the program from running at all.

Runtime Errors

Runtime errors occur when you're actually running the program.

Examples include:

  • Using undefined variables or functions → NameError
  • Trying to reference a local variable as if it were global → UnboundLocalError
  • Dividing by zero → ZeroDivisionError

Runtime errors have specific, descriptive names. Reading the error messages carefully often helps you fix them.

Logic Errors

Logic errors happen when your program runs fine but doesn't do what you intended. This isn't really an error with the program itself - it's a mistake made by the programmer.

Most bugs are actually logic errors.

This is where assert statements shine again. By adding assertions to check preconditions, you can convert logic errors into AssertionErrors, making them easier to spot.

Combining assert and print statements gives you the basics of debugging.


Keep struggling (and enjoying) your Python learning journey!

See you later! 👋

Top comments (0)