A brief example¶
description
Just so that you know what we're talking about
Try to find the bug in the following piece of code:
class Employee(object):
def __init__(self, name, position, employee_no=None):
self.name = name
self.position = position
self.employee_no = employee_no
salaries = {0: 12000,
1: 4000,
2: 8000,
3: 4000}
def print_salary(employee):
if employee.employee_no:
salary = salaries.get(employee.employee_no, 0)
print "You make EUR %s." % salary
else:
print "You're not an employee currently."
Found it yet? Did you have to spend more than a few seconds thinking about it? Any developer could have written that code and not seen the problem. Furthermore, the bug is an edge case that you may not have tested using manual/through-the-web testing.
Let us write a test (actually, a doc/unit test) for this code. Don’t worry too much about how this is set up and executed just yet.
Employee w/o an employee number is ignored:
>>> print_salary(Employee('Adam', 'Developer'))
You're not an employee currently
Employee w/o a known employee number earns nothing:
>>> print_salary(Employee('Berta', 'Designer', 100))
You make EUR 0.
Employee w/ a valid employee number is found properly:
>>> print_salary(Employee('Chris', 'CTO', 2))
You make EUR 8000.
Zero is a valid employee number:
>>> print_salary(Employee('Devon', 'CEO', 0))
You make EUR 12000
As it happens, the last test would fail. It would print You are not an employee currently., unless we fixed the code:
class Employee(object):
def __init__(self, name, position, employee_no=None):
self.name = name
self.position = position
self.employee_no = employee_no
salaries = {0: 12000,
1: 4000,
2: 8000,
3: 4000}
def print_salary(employee):
if employee.employee_no is not None:
salary = salaries.get(employee.employee_no, 0)
print "You make EUR %s." % salary
else:
print "You're not an employee currently."
The moral of the story?
- you rarely catch problems like these with manual testing
- put the time you waste catching silly bugs and typos into writing tests
- with decent test coverage, you end up saving lots of time when you refactor