\chapter{Test driven development}
\label{lec-tdd}

\section{Modules, files and the \pythoninline{import} statement}

You have already used (without explanation) an \pythoninline{import}
statement. What does an \pythoninline{import} statement do? Well it
imports all or part of a Python \myidx{module}. And what is a module,
I hear you ask? A module is simply a Python file that contains
definitions (usually function definitions). As programs get large, it
makes sense to separate the program into different modules. This
allows the programmer to minimize the complexity of the programming
task. Typically, similar functionality or related functions are
grouped into a single module and separate modules are as independent
of each other as possible. Creating your own modules is as easy as
creating a Python script with definitions in it.

The Python standard library contains a very large number of modules
for many different tasks. It is worthwhile browsing the library just
to get a feel for all the useful things it can do. The current
documentation can be accessed at:
\myurl{http://www.python.org/doc/current/library/index.html}, or by
choosing \menu{Help \rarr Python Docs ...} in IDLE. We will
look at the \pythoninline{doctest} module later in this lecture, and
throughout the course, several other modules will be introduced.

There are three ways of using \pythoninline{import} to import a module
and subsequently use what was imported. We will use the
\pythoninline{math} module to illuminate:

\begin{enumerate}

\item

\begin{python}
import math
print math.cos(math.pi/2.0)
\end{python}
This method imports everything from the \pythoninline{math} module,
and members of the module are accessed using dot notation.

\item

\begin{python}
from math import cos
print cos(3.14159265/2.0)
\end{python}
This method imports only the definition of \pythoninline{cos} from the
\pythoninline{math} library. Nothing else is imported.

\item

\begin{python}
from math import cos, pi
print cos(pi/2.0)
\end{python}
This method imports only the definitions of \pythoninline{cos} and
\pythoninline{pi} from the math library. Nothing else is imported.
\item

\begin{python}
from math import *
print cos(pi/2.0)
\end{python}
This method also imports everything from the \pythoninline{math}
module, the difference being that dot notation is not needed to access
module members.

\end{enumerate}
%
%Also, do you need/want to include the Restart between each example, otherwise the previous import is still imported.
It is more common to use the first or second method than the last.
The first method has the advantage of avoiding naming conflicts (two
different modules defining \pythoninline{cos} for example), at the
cost of lengthier function invocations. The second method has the
opposite advantages and disadvantages.

\section{Programming with style}
Readability is very important to programmers, since in practice
programs are read and modified far more often then they are
written. All the code examples in this book will be consistent with
the \emph{Python Enhancement Proposal 8} (PEP 8), a style guide
developed by the Python community.
We'll have more to say about style as our programs become more
complex, but a few pointers will be helpful already:
\begin{itemize}
\item use 4 spaces for indentation
\item imports should go at the top of the file
\item separate function definitions with two blank lines
\item keep function definitions together
\item keep top level statements, including function calls, together at
  the bottom of the program
\end{itemize}

\section{Triple quoted strings}
In addition to the single and double quoted strings we first saw in
Lecture \ref{lec-variables}, Python also has \emph{triple quoted strings} :
\begin{pythonInteractive}
>>> type("""This is a triple quoted string using 3 double quotes.""")
<type 'str'>
>>> type('''This triple quoted strings uses 3 single quotes.''')
<type 'str'>
>>>
\end{pythonInteractive}
Triple quoted strings can contain both single and double quotes inside
them:
\begin{pythonInteractive}
>>> print '''"Oh no", she exclaimed, "Ben's bike is broken!"'''
"Oh no", she exclaimed, "Ben's bike is broken!"
>>>
\end{pythonInteractive}
Finally, triple quoted strings can span multiple lines:

\noindent
\begin{minipage}{\textwidth}
\begin{pythonInteractive}
>>> message = """This message will
... span several
... lines."""
>>> print message
This message will
span several
lines.
>>>
\end{pythonInteractive}
\end{minipage}

\section{Unit testing with \pythoninline{doctest}}
\label{sec-doctest}
It is a common best practice in software development these days to
include automatic \myidx{unit testing} of source code. Unit testing
provides a way to automatically verify that individual pieces of code,
such as functions, are working properly. This makes it possible to
change the implementation of a function at a later time and quickly
test that it still does what it was intended to do.
Python has a built-in doctest module for easy unit testing. Doctests
can be written within a triple quoted string on the \emph{first line}
of the body of a function or script. They consist of sample
interpreter sessions with a series of inputs to a Python prompt
followed by the expected output from the Python interpreter.
The doctest module automatically runs any statement beginning with
$>$$>$$>$ (followed by a space) and compares the following line with the output from the
interpreter.
To see how this works, put the following in a script named
\myurl{first\_doctest.py}:
\begin{python}
def is_divisible_by_2_or_5(n):
    """
      >>> is_divisible_by_2_or_5(8)
      True
    """


if __name__ == '__main__':
    import doctest
    doctest.testmod()
\end{python}

The last three lines are what make doctest run. Put them at the bottom
of any file that includes doctests. 
Running the script will produce the following output:
\begin{pythonOutput}
**********************************************************************
File "myfunctions.py", line 3, in __main__.is_divisible_by_2_or_5
Failed example:
    is_divisible_by_2_or_5(8)
Expected:
    True
Got nothing
**********************************************************************
1 items had failures:
   1 of   1 in __main__.is_divisible_by_2_or_5
***Test Failed*** 1 failures.
\end{pythonOutput}

This is an example of a \emph{failing test}. The test says: if you
call \pythoninline{is\_divisible\_by\_2\_or\_5(8)} the result should
be \pythoninline{True}. Since 
\pythoninline{is\_divisible\_by\_2\_or\_5} as written doesn't return
anything at all, the test fails, and doctest tells us that it expected
\pythoninline{True} but got nothing.

We can make this test pass by returning True:
\begin{python}
def is_divisible_by_2_or_5(n):
    """
      >>> is_divisible_by_2_or_5(8)
      True
    """
    return True


if __name__ == '__main__':
    import doctest
    doctest.testmod()
\end{python}

If we run it now, there will be no output, which indicates that the
test passed. Note again that the doctest string must be placed
immediately after the function definition header in order to run. To
see more detailed output, add the keyword argument
\pythoninline{verbose=True} to the \pythoninline{testmod} method call
\begin{python}
doctest.testmod(verbose=True)
\end{python}
and run the module again.  This will produce output showing the result
of running the tests and whether they pass or not.
\begin{pythonOutput}
Trying:
    is_divisible_by_2_or_5(8)
Expecting:
    True
ok
1 items had no tests:
    __main__
1 items passed all tests:
   1 tests in __main__.is_divisible_by_2_or_5
1 tests in 2 items.
1 passed and 0 failed.
Test passed.
\end{pythonOutput}

While the test passed, our test suite is clearly inadequate, since
\pythoninline{is\_divisible\_by\_2\_or\_5} will now return
\pythoninline{True} no matter what argument is passed to it. Here is a
completed version with a more complete test suite and code that makes
the tests pass:

\noindent
\begin{minipage}{\textwidth}
\begin{python}
def is_divisible_by_2_or_5(n):
    """
      >>> is_divisible_by_2_or_5(8)
      True
      >>> is_divisible_by_2_or_5(7)
      False
      >>> is_divisible_by_2_or_5(5)
      True
      >>> is_divisible_by_2_or_5(9)
      False
    """
    return n % 2 == 0 or n % 5 == 0 


if __name__ == '__main__':
    import doctest
    doctest.testmod()
\end{python}
\end{minipage}
Run the module again and see what you get.

\brenNote{Lecture a bit short - need a case study. Actually a decent
example will chew up a fair bit of time, I think this would be
worthwhile. The more examples they get of a programmer actually doing
programming, the better it's going to be.}

\section{Test-driven development demonstrated}

At this point in the lecture, the lecturer will demonstrate how
test-driven development should be used. We will use the extension
exercise from Lecture \ref{lecture-fruity} as our example.

\section{Glossary}
\begin{description}
\item[module:] A python file that contains definitions.
\item[\pythoninline{import}:] The keyword that allows modules to be
used within a particular Python session or file.
\item[unit testing:]An automatic procedure used to validate that
  individual units of code are working properly. Python has doctest
  built in for this purpose.
\end{description}

\newpage
\section{Laboratory exercises}
All of the exercises below should be added to a file named
\myurl{doctest\_ex.py} that contains the following at the
bottom:
\begin{python}
if __name__ == '__main__':
    import doctest
    doctest.testmod(verbose=True)
\end{python}

After completing each exercise in turn, run the program to confirm
that the doctests for your new function pass.
\begin{enumerate}
\item Write a compare function that returns \pythoninline{1} if
\pythoninline{a $>$ b}, \pythoninline{0} if \pythoninline{a == b},
  and \pythoninline{-1} if \pythoninline{a $<$ b}.
\begin{python}
def compare(a, b):
    """
      >>> compare(5, 4)
      1
      >>> compare(7, 7)
      0
      >>> compare(2, 3)
      -1
      >>> compare(42, 1)
      1
    """
    #  Your function body should begin here.
\end{python}
Fill in the body of the function so the doctests pass.
\item Use incremental development to write a function called
hypotenuse that returns the length of the hypotenuse of a right
triangle given the lengths of the other two sides as parameters. Record
each stage of the incremental development process as you go.
\begin{python}
def hypotenuse(a, b):
    """
      >>> hypotenuse(3, 4)
      5.0
      >>> hypotenuse(12, 5)
      13.0
      >>> hypotenuse(7, 24)
      25.0
      >>> hypotenuse(9, 12)
      15.0
    """
\end{python}
When you are finished add your completed function with the doctests to
\myurl{doctest\_ex.py} and confirm that the doctests pass.

\item Write a body for the function definition of
\pythoninline{fahrenheit\_to\_celsius}
designed to return 
the integer value of the nearest degree Celsius for a given temperature
in Fahrenheit. Use your favourite web search engine to find the
equation for doing the conversion if you don't already know it.
(\emph{hint:} you may want to make use of the built-in
function, \pythoninline{round}. Try typing \pythoninline{help(round)}
in a Python 
shell and experimenting with round until you are comfortable with how
it works.)
\begin{python}
def fahrenheit_to_celsius(t):
    """
      >>> fahrenheit_to_celsius(212)
      100
      >>> fahrenheit_to_celsius(32)
      0
      >>> fahrenheit_to_celsius(-40)
      -40
      >>> fahrenheit_to_celsius(36)
      2
      >>> fahrenheit_to_celsius(37)
      3
      >>> fahrenheit_to_celsius(38)
      3
      >>> fahrenheit_to_celsius(39)
      4
    """
\end{python}
\item Add a function body for \pythoninline{celsius\_to\_fahrenheit}
to convert from Celsius to Fahrenheit. 
\begin{python}
def celsius_to_fahrenheit(t):
    """
      >>> celsius_to_fahrenheit(0)
      32
      >>> celsius_to_fahrenheit(100)
      212
      >>> celsius_to_fahrenheit(-40)
      -40
      >>> celsius_to_fahrenheit(12)
      54
      >>> celsius_to_fahrenheit(18)
      64
      >>> celsius_to_fahrenheit(-48)
      -54
    """
\end{python}
\end{enumerate}

\submitreminder
