Lab 5: Debugging and Testing

In this lab, we will practice using Thonny’s debugger and writing tests in pytest. You must download four files for this lab: debugging.py, correct.py, buggy.py, and test.py.

The files purpose of the files is as follows:

  • debugging.py: you’ll complete the first activities in this file
  • test.py: this should contain the tests that you write for each function in correct.py/buggy.py
  • correct.py: this should contain correct implementations of each function that is tested in test.py
    • YOU SHOULD NOT EDIT THIS FILE!
  • buggy.py: this should contain buggy implementations of each function that is tested in test.py
    • YOU SHOULD NOT EDIT THIS FILE!

Debugging

The first activity will involve debugging a buggy function. The function is supposed to take a list of integers as input, add one to each number in that list, and return the updated list. Take a second to discuss with your partner: is this a mapping, filtering, or reducing function?

Activity 1: finding bugs in add_one

In this activity, you will debug the buggy implementation of add_one using Thonny’s debugger. First, open debugging.py and add a breakpoint on the line that includes item += 1. Now, click the bug button, which will run the debugging.py file in the debugger. Your code will stop on the line item += 1.

Click “step over” (big step) and answer the following questions as you go through the code. You only need to do this to understand what is happening, it will not be graded.

Before clicking “step over”
The value of item is:
The value of lst is:

After clicking “step over” twice
The value of item is:
The value of lst is:

After clicking “step over” four times
The value of item is:
The value of lst is:

After clicking “step over” six times
The value of item is:
The value of lst is:

Once you understand why this function doesn’t work, move on to the next activity!

Activity 2: fixing bugs in add_one

Now, rewrite add_one so that the output matches the expected output. There are at least two ways to approach this:

  • Create a new list at the start of the function, then use append to add each number + 1 to it in your loop (similar to examples that we have seen in class)
  • Use a range loop, and update the value at index i in lst to lst[i] + 1 as you go through the loop.

The result of doing these is somewhat different (we will discuss that later), but for the purposes of our current tests, either is fine!

Test that what you did worked by running debugging.py. If the actual output matches the expected output, submit to the autograder (you need to upload both debugging.py and test.py - don’t rename them). If you pass the Activity 2 tests, you are ready to move on to the next activity!

Writing Tests

Next, you’ll practice writing your own tests for two functions. Writing comprehensive tests is an important skill to build as you learn to program.

Activity 3: install pytest

This GIF displays how to download pytest. Make sure to run import pytest in the shell afterwards to confirm that it was installed successfully!

Gif showing how to download pytest

You might see a red warning message when you use pytest in Thonny. If you also see a number of tests that have passed/failed, you do not need to worry about this!!!

Activity 4: writing tests when a function is always incorrect

We’ll start by testing a recursive function that determines whether or not a string is a palindrome. There are two implementations of this function: the one in correct.py is implemented correctly, while the one in buggy.py does the exact opposite of what it is supposed to do.

You must have these four tests in your submission:

  • test_is_palindrome_base_0: tests the is_palindrome base case when the length of the string is 0
  • test_is_palindrome_base_1: tests the is_palindrome base case when the length of the string is 1
  • test_is_palindrome_recursive_true: tests the is_palindrome recursive case when the string is a palindrome
  • test_is_palindrome_recursive_false: tests the is_palindrome recursive case when the string is not a palindrome

The only thing that you need to update is the input strings in each function call. The first test is implemented for you as an example - so you get 12.5 free autograder points!

You should pass these tests when using the correct implementation. Once you’ve done that, switch to the incorrect implementation (by commenting/uncommenting the imports at the top of the test file) - these four tests should all fail.

Now, submit to the autograder (you need to upload both debugging.py and test.py - don’t rename them). The autograder checks that the arguments in your function calls match the specifications above for each test function. If you pass the Activity 4 tests, you are ready for the next (and final) activity.

Activity 5: writing tests when a function is sometimes correct

You’ve probably noticed by now that it’s pretty common to write a function that works in some cases, but doesn’t work in others. The has_positive function in buggy.py is one such function. It should return True if a list has any positive numbers and False otherwise, but it’s only sometimes correct.

  • test_has_positive_both_correct: tests the scenario in which both the correct and buggy functions return the same thing. You need to identify such a case by reading the functions in correct.py and buggy.py.
  • test_has_positive_buggy_wrong: tests the scenario in which the buggy function is wrong. You need to identify such a case by reading the functions in correct.py and buggy.py.

You should pass both tests when using the correct implementation. Once you’ve done that, switch to the incorrect implementation (by commenting/uncommenting the imports at the top of the test file) - the test_has_positive_both_correct should still pass, but the test_has_positive_buggy_wrong test should fail.

Check your results

When you get to this point, you should see a message “6 passed” when you import the correct code, and “5 failed, 1 passed” when you import the buggy code. If you don’t, go back and check over your work!

Submitting

Submit two files: debugging.py and test.py on gradescope. This time, you don’t need to rename the files (I need to be able to distinguish between the two). Make sure to add your partner to your submission.

Nice work! Hopefully you will find ways to apply your new debugging and testing skills to future assignments.