# Lecture 8

## Testing and Debugging

Burkay Genç, Ahmet Selman Bozkır, and Selma Dilek

26/04/2023

• dictionaries

## TODAY

• testing and debugging
• how to make sure your code runs
• how to check for existence of errors
• how to track sources of errors

## LIFE CAN BE UGLY

• Life is never perfect
• Internet fails to work
• Phone gets disconnected
• You team loses
• Viruses kill people
• We need to test things before using them
• Check internet signal
• Check phone signal
• Training sessions
• Examine virus in lab

## What if something fails?

• If something fails we need to fix it
• But to fix something, you need to know why it was broken in the first place
• In real life
• Check internet cable, diagnose drivers, restart modem
• Check airplane mode, move around the house, restart phone
• Change tactics, change players, check equipment quality
• Extract genome, test with animals, computer simulations

Problem Fixing

## WHAT IF CODE FAILS?

• Code sometimes always fails
• Even code written by experts can fail
• It is not possible to foresee every possible scenario
• You do not expect to write code in one run

## SOME WISDOM

Program testing can be used to show the presence of bugs, but never to show their absence!

Edsger Dijkstra

No amount of experimentation can ever prove me right; a single experiment can prove me wrong.

Albert Einstein

^^^ One sentence summary of the “scientific method”

## WHEN ARE YOU READY TO TEST?

• ensure code runs
• remove syntax errors
• remove static semantic errors
• Python interpreter can usually find these for you
• have a set of expected results
• an input set
• for each input, the expected output

## TESTING APPROACHES

• intuition about natural boundaries to the problem
• can you come up with some natural partitions?
def is_bigger(x, y):
""" Assumes x and y are ints
Returns True if y is less than x, else False """
• if no natural partitions, might do random testing
• probability that code is correct increases with more tests
• better options below
• black box testing
• explore paths through specification
• glass box testing
• explore paths through code

## BLACK BOX TESTING

def sqrt(x, eps):
""" Assumes x, epsilon floats, x >= 0, epsilon > 0
Returns res such that x-epsilon <= res*res <= x+epsilon """
• designed without looking at the code
• can be done by someone other than the implementer to avoid some implementer biases
• testing can be reused if implementation changes
• paths through specification
• build test cases in different natural space partitions
• also consider boundary conditions

## BLACK BOX TESTING

def sqrt(x, epsilon):
""" Assumes x, epsilon floats, x >= 0, epsilon > 0
Returns res such that x-epsilon <= res*res <= x+epsilon """

## GLASS BOX TESTING

• use code directly to guide design of test cases
• called path-complete if every potential path through code is tested at least once
• what are some drawbacks of this type of testing?
• can go through loops arbitrarily many times
• missing paths
• guidelines
• branches
• exercise all parts of a conditional
• for loops
• loop not entered
• body of loop executed exactly once
• body of loop executed more than once
• while loops
• same as for loops
• cases that catch all ways to exit loop

## EXAMPLE

def isPrime(x):
""" Assumes x is a nonnegative int
Returns True if x is prime; False otherwise """
if x <= 2:
return False
for i in range(2, x):
if x % i == 0:
return False
return True
• What should we test for?

## EXAMPLE

def isPrime(x):
""" Assumes x is a nonnegative int
Returns True if x is prime; False otherwise """
if x <= 2:
return False
for i in range(2, x):
if x % i == 0:
return False
return True

isPrime(0) # expected value: False
## False
isPrime(2) # expected value: True
## False
• Oops! For x = 2, the answer should have been True!
• We know we should test this because we could see the code.

## GLASS BOX TESTING

def abs(x):
""" Assumes x is an int
Returns x if x>=0 and –x otherwise """
if x < -1:
return -x
else:
return x
• a path-complete test suite could miss a bug
• path-complete test suite: 2 and -2
• but abs(-1) incorrectly returns -1
• should still test boundary cases

## GENERAL GUIDELINES

• Exercise both branches of all if statements.
• Make sure that each except clause (we will learn later) is executed.
• For each for loop, have test cases in which
• The loop is not entered (e.g., if the loop is iterating over the elements of a list, make sure that it is tested on the empty list),
• The body of the loop is executed exactly once, and
• The body of the loop is executed more than once.
• For each while loop,
• Look at the same kinds of cases as when dealing with for loops.
• Include test cases corresponding to all possible ways of exiting the loop.
• For recursive functions, include test cases that cause the function to return with
• no recursive calls,
• exactly one recursive call, and
• more than one recursive call.

## BUGS

• When bugs enter electric equipment, they may break it
• When virtual bugs enter software, they may break it
• Except, virtual bugs cannot crawl into software
• You put them there!
• Debugging is the act of finding and removing bugs from software