summaryrefslogtreecommitdiff
path: root/slides
diff options
context:
space:
mode:
Diffstat (limited to 'slides')
-rw-r--r--slides/advanced_python/advanced_py.tex10
-rw-r--r--slides/advanced_python/oop_unittest.tex117
-rw-r--r--slides/advanced_python/slides/modules.tex66
-rw-r--r--slides/advanced_python/slides/oop.tex190
-rw-r--r--slides/basic_python/python_part2.tex291
-rw-r--r--slides/test_driven_development/tdd_simple.tex342
6 files changed, 948 insertions, 68 deletions
diff --git a/slides/advanced_python/advanced_py.tex b/slides/advanced_python/advanced_py.tex
index b15419e..0be43d6 100644
--- a/slides/advanced_python/advanced_py.tex
+++ b/slides/advanced_python/advanced_py.tex
@@ -50,4 +50,14 @@ showstringspaces=false, keywordstyle=\color{blue}\bfseries}
\include{slides/scipy}
\include{slides/modules}
+\section{Other packages}
+
+\begin{frame}{Very useful packages}
+ \begin{itemize}
+ \item \url{http://ipython.org/}
+ \item \url{http://sympy.org/}
+ \item \url{http://pandas.pydata.org/}
+ \end{itemize}
+\end{frame}
+
\end{document}
diff --git a/slides/advanced_python/oop_unittest.tex b/slides/advanced_python/oop_unittest.tex
new file mode 100644
index 0000000..b8e21bf
--- /dev/null
+++ b/slides/advanced_python/oop_unittest.tex
@@ -0,0 +1,117 @@
+\documentclass[12pt,presentation]{beamer}
+\usepackage[utf8]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage{fixltx2e}
+\usepackage{graphicx}
+\usepackage{longtable}
+\usepackage{float}
+\usepackage{wrapfig}
+\usepackage{soul}
+\usepackage{textcomp}
+\usepackage{marvosym}
+\usepackage{wasysym}
+\usepackage{latexsym}
+\usepackage{amssymb}
+\usepackage{hyperref}
+\tolerance=1000
+\usepackage[english]{babel} \usepackage{ae,aecompl}
+\usepackage{mathpazo,courier,euler} \usepackage[scaled=.95]{helvet}
+\usepackage{listings}
+\lstset{language=Python, basicstyle=\ttfamily\bfseries,
+commentstyle=\color{red}\itshape, stringstyle=\color{green},
+showstringspaces=false, keywordstyle=\color{blue}\bfseries}
+\providecommand{\alert}[1]{\textbf{#1}}
+
+\title{SEES: OOP and more testing}
+\author{FOSSEE}
+
+\usetheme{Warsaw}\usecolortheme{default}\useoutertheme{infolines}\setbeamercovered{transparent}
+
+\AtBeginSection[]
+{
+ \begin{frame}<beamer>
+ \frametitle{Outline}
+ \tableofcontents[currentsection]
+ \end{frame}
+}
+
+\begin{document}
+
+\maketitle
+
+\begin{frame}
+\frametitle{Outline}
+\setcounter{tocdepth}{3}
+\tableofcontents
+\end{frame}
+
+\include{slides/oop}
+
+
+\section{\texttt{unittest} framework}
+
+\begin{frame}[fragile]
+ \frametitle{\texttt{unittest}}
+ \begin{itemize}
+ \item \texttt{unittest} framework can efficiently automate tests
+ \item Easily initialize code and data for executing the specific
+ tests
+ \item Cleanly shut them down once the tests are executed
+ \item Easily aggregate tests into collections and improved reporting
+ \end{itemize}
+\end{frame}
+
+
+\begin{frame}[fragile]
+ \frametitle{\texttt{unittest}ing \texttt{gcd.py}}
+ \begin{itemize}
+ \item Subclass the \texttt{TestCase} class in \texttt{unittest}
+ \item Place all the test code as methods of this class
+ \item Place the code in \texttt{test\_gcd.py}
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile,allowframebreaks]
+ \frametitle{\texttt{test\_gcd.py}}
+\small
+\begin{lstlisting}
+import gcd
+import unittest
+
+class TestGcdFunction(unittest.TestCase):
+ def setUp(self):
+ # Called before each test case.
+ print "In setUp"
+
+ def tearDown(self):
+ print "In tearDown"
+
+ def test_gcd(self):
+ self.assertEqual(gcd.gcd(45, 5), 5)
+ self.assertEqual(gcd.gcd(45, 5), 5)
+
+ def test_gcd_correctly_handles_floats(self):
+ # Write appropriate tests here.
+ pass
+
+if __name__ == '__main__':
+ unittest.main()
+\end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{\texttt{test\_gcd.py}}
+ \begin{itemize}
+ \item \texttt{setUp} -- called before every \texttt{test\_*} method
+ \item \texttt{tearDown} -- called after every test
+ \item \texttt{setUp} and \texttt{tearDown} -- useful to perform common
+ operations, make a temporary directory, delete it when done etc.
+ \item \texttt{test\_gcd} -- actual test code
+ \item \texttt{assertEqual} -- compare actual result with expected one
+ \item Also see: \url{docs.python.org/2.7/library/unittest.html}
+ \end{itemize}
+\end{frame}
+
+
+
+\end{document}
diff --git a/slides/advanced_python/slides/modules.tex b/slides/advanced_python/slides/modules.tex
index d6de640..707c3b3 100644
--- a/slides/advanced_python/slides/modules.tex
+++ b/slides/advanced_python/slides/modules.tex
@@ -94,70 +94,4 @@
\end{lstlisting}
\end{frame}
-\section{Writing modules}
-
-\begin{frame}[fragile]
- \frametitle{GCD script}
- \begin{itemize}
- \item Function that computes gcd of two numbers
- \item Save it as \texttt{gcd\_script.py}
- \end{itemize}
- \begin{lstlisting}
- def gcd(a, b):
- while b:
- a, b = b, a%b
- return a
- \end{lstlisting}
- \begin{itemize}
- \item Also add the tests to the file
- \end{itemize}
- \begin{lstlisting}
- if gcd(40, 12) == 4 and gcd(12, 13) == 1:
- print "Everything OK"
- else:
- print "The GCD function is wrong"
- \end{lstlisting}
- \begin{lstlisting}
- $ python gcd_script.py
- \end{lstlisting} % $
-\end{frame}
-
-\begin{frame}[fragile]
- \frametitle{Python path}
- \begin{itemize}
- \item In IPython type the following
- \end{itemize}
- \begin{lstlisting}
- import sys
- sys.path
- \end{lstlisting}
- \begin{itemize}
- \item List of locations where python searches for a module
- \item \texttt{import sys} -- searches for file \texttt{sys.py} or
- dir \texttt{sys} in all these locations
- \item So, our own modules can be in any one of the locations
- \item Current working directory is one of the locations
- \end{itemize}
-\end{frame}
-
-\begin{frame}[fragile]
- \frametitle{\texttt{\_\_name\_\_}}
- \begin{lstlisting}
- import gcd_script
- \end{lstlisting}
- \begin{itemize}
- \item The import is successful
- \item But the test code, gets run
- \item Add the tests to the following \texttt{if} block
- \end{itemize}
- \begin{lstlisting}
- if __name__ == "__main__":
- \end{lstlisting}
- \begin{itemize}
- \item Now the script runs properly
- \item As well as the import works; test code not executed
- \item \texttt{\_\_name\_\_} is local to every module and is equal
- to \texttt{\_\_main\_\_} only when the file is run as a script.
- \end{itemize}
-\end{frame}
diff --git a/slides/advanced_python/slides/oop.tex b/slides/advanced_python/slides/oop.tex
index bdb983c..e1e96f8 100644
--- a/slides/advanced_python/slides/oop.tex
+++ b/slides/advanced_python/slides/oop.tex
@@ -13,6 +13,190 @@
\end{frame}
\begin{frame}[fragile]
+ \frametitle{Classes: the big picture}
+ \begin{itemize}
+ \item Lets you create new data types
+ \item Class is a template for an object belonging to that class
+ \item Note: in Python a class is also an object
+ \item Instantiating a class creates an instance (an object)
+ \item An instance encapsulates the state (data) and behavior
+ (methods)
+ \item Allows you to define an inheritance hierarchy
+ \begin{itemize}
+ \item ``A Honda car \alert{is a} car.''
+ \item ``A car \alert{is an} automobile.''
+ \item ``A Python \alert{is a} reptile.''
+ \end{itemize}
+ \item Programmers need to think OO
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Classes: what's the big deal?}
+ \begin{itemize}
+ \item Lets you create objects that mimic a real problem being
+ simulated
+ \item Makes problem solving more natural and elegant
+ \item Easier to create code
+ \item Allows for code-reuse
+ \item Polymorphism
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Class definition and instantiation}
+ \begin{itemize}
+ \item Class definitions when executed create class objects
+ \item Instantiating the class object creates an instance of the
+ class
+ \end{itemize}
+\footnotesize
+\begin{lstlisting}
+class Foo(object):
+ pass
+# class object created.
+
+# Create an instance of Foo.
+f = Foo()
+# Can assign an attribute to the instance
+f.a = 100
+print f.a
+100
+\end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Classes \ldots}
+ \begin{itemize}
+ \item All attributes are accessed via the \texttt{object.attribute}
+ syntax
+ \item Both class and instance attributes are supported
+ \item \emph{Methods} represent the behavior of an object: crudely
+ think of them as functions ``belonging'' to the object
+ \item All methods in Python are ``virtual''
+ \item Inheritance through subclassing
+ \item Multiple inheritance is supported
+ \item No special public and private attributes: only good
+ conventions
+ \begin{itemize}
+ \item \verb+object.public()+: public
+ \item \verb+object._private()+ \& \verb+object.__priv()+:
+ non-public
+ \end{itemize}
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Classes: examples}
+\begin{lstlisting}
+class MyClass(object):
+ """Example class (this is the class docstring)."""
+ i = 12345 # A class attribute
+ def f(self):
+ """This is the method docstring"""
+ return 'hello world'
+
+>>> a = MyClass() # creates an instance
+>>> a.f()
+'hello world'
+>>> # a.f() is equivalent to MyClass.f(a)
+... # This also explains why f has a 'self' argument.
+... MyClass.f(a)
+'hello world'
+\end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Classes (continued)}
+ \begin{itemize}
+ \item \texttt{self} is \alert{conventionally} the first argument for a
+ method
+ \item In previous example, \texttt{a.f} is a method object
+ \item When \texttt{a.f} is called, it is passed the instance \texttt{a} as
+ the first argument
+ \item If a method called \verb+__init__+ exists, it is called when
+ the object is created
+ \item If a method called \verb+__del__+ exists, it is called before
+ the object is garbage collected
+ \item Instance attributes are set by simply ``setting'' them in
+ \texttt{self}
+ \item Other special methods (by convention) like \verb+__add__+ let
+ you define numeric types:
+ {\footnotesize \url{https://docs.python.org/2.7/reference/datamodel.html}
+ }
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Classes: examples}
+\begin{lstlisting}
+class Bag(MyClass): # Shows how to derive classes
+ def __init__(self): # called on object creation.
+ self.data = [] # an instance attribute
+ def add(self, x):
+ self.data.append(x)
+ def addtwice(self, x):
+ self.add(x)
+ self.add(x)
+>>> a = Bag()
+>>> a.f() # Inherited method
+'hello world'
+>>> a.add(1); a.addtwice(2)
+>>> a.data
+[1, 2, 2]
+\end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Derived classes}
+ \begin{itemize}
+ \item Call the parent's \verb+__init__+ if needed
+ \item If you don't need a new constructor, no need to define it in subclass
+ \item Can also use the \verb+super+ built-in function
+ \end{itemize}
+\begin{lstlisting}
+class AnotherBag(Bag):
+ def __init__(self):
+ # Must call parent's __init__ explicitly
+ Bag.__init__(self)
+ # Alternatively use this:
+ super(AnotherBag, self).__init__()
+ # Now setup any more data.
+ self.more_data = []
+\end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Classes: polymorphism}
+\begin{lstlisting}
+class Drawable(object):
+ def draw(self):
+ # Just a specification.
+ pass
+\end{lstlisting}
+\mode<presentation>{\pause}
+\begin{lstlisting}
+class Square(Drawable):
+ def draw(self):
+ # draw a square.
+class Circle(Drawable):
+ def draw(self):
+ # draw a circle.
+\end{lstlisting}
+\end{frame}
+\begin{frame}[fragile]
+ \frametitle{Classes: polymorphism}
+\begin{lstlisting}
+class Artist(Drawable):
+ def draw(self):
+ for obj in self.drawables:
+ obj.draw()
+\end{lstlisting}
+\end{frame}
+
+
+
+\begin{frame}[fragile]
\frametitle{Example: Managing Talks}
\begin{itemize}
\item A list of talks at a conference
@@ -191,8 +375,10 @@
class Tutorial(Talk):
"""A class for the tutorials."""
- def __init__(self, speaker, title, tags, handson=True):
- Talk.__init__(self, speaker, title, tags)
+ def __init__(self, speaker, title, tags,
+ handson=True):
+ Talk.__init__(self, speaker, title,
+ tags)
self.handson = handson
def is_handson(self):
diff --git a/slides/basic_python/python_part2.tex b/slides/basic_python/python_part2.tex
new file mode 100644
index 0000000..9faddfd
--- /dev/null
+++ b/slides/basic_python/python_part2.tex
@@ -0,0 +1,291 @@
+\documentclass[12pt,presentation]{beamer}
+\usepackage[utf8]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage{fixltx2e}
+\usepackage{graphicx}
+\usepackage{longtable}
+\usepackage{float}
+\usepackage{wrapfig}
+\usepackage{soul}
+\usepackage{textcomp}
+\usepackage{marvosym}
+\usepackage{wasysym}
+\usepackage{latexsym}
+\usepackage{amssymb}
+\usepackage{hyperref}
+\tolerance=1000
+\usepackage[english]{babel} \usepackage{ae,aecompl}
+\usepackage{mathpazo,courier,euler} \usepackage[scaled=.95]{helvet}
+\usepackage{listings}
+\lstset{language=Python, basicstyle=\ttfamily\bfseries,
+commentstyle=\color{red}\itshape, stringstyle=\color{green},
+showstringspaces=false, keywordstyle=\color{blue}\bfseries}
+\providecommand{\alert}[1]{\textbf{#1}}
+
+\title{More Basic Python}
+\author[FOSSEE] {FOSSEE}
+\institute[IIT Bombay] {Department of Aerospace Engineering\\IIT Bombay}
+\date []{}
+
+\usetheme{Warsaw}\usecolortheme{default}\useoutertheme{infolines}\setbeamercovered{transparent}
+
+\AtBeginSection[]
+{
+ \begin{frame}<beamer>
+ \frametitle{Outline}
+ \tableofcontents[currentsection]
+ \end{frame}
+}
+
+\begin{document}
+
+\maketitle
+
+\begin{frame}
+\frametitle{Outline}
+\setcounter{tocdepth}{3}
+\tableofcontents
+\end{frame}
+
+\section{Using Python modules}
+
+\begin{frame}[fragile]
+ \frametitle{\texttt{hello.py}}
+ \begin{itemize}
+ \item Script to print `hello world' -- \texttt{hello.py}
+ \end{itemize}
+ \begin{lstlisting}
+ print "Hello world!"
+ \end{lstlisting}
+ \begin{itemize}
+ \item We have been running scripts from IPython
+ \end{itemize}
+ \begin{lstlisting}
+ In[]: %run -i hello.py
+ \end{lstlisting}
+ \begin{itemize}
+ \item Now, we run from the shell using python
+ \end{itemize}
+ \begin{lstlisting}
+ $ python hello.py
+ \end{lstlisting}
+\end{frame}
+
+
+\begin{frame}
+ \frametitle{Modules}
+ \begin{itemize}
+ \item Organize your code
+ \item Collect similar functionality
+ \item Functions, classes, constants, etc.
+ \end{itemize}
+\end{frame}
+
+\begin{frame}
+ \frametitle{Modules}
+ \begin{itemize}
+ \item Define variables, functions and classes in a file with a
+ \texttt{.py} extension
+ \item This file becomes a module!
+ \item The \texttt{import} keyword ``loads'' a module
+ \item One can also use:
+ \mbox{\texttt{from module import name1, name2, name2}}\\
+ where \texttt{name1} etc. are names in the module, ``module''
+ \item \texttt{from module import *} \ --- imports everything from module,
+ \alert{use only in interactive mode}
+ \item File name should be valid variable name
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Modules: example}
+ \begin{lstlisting}
+# --- foo.py ---
+some_var = 1
+def fib(n): # write Fibonacci series up to n
+ """Print a Fibonacci series up to n."""
+ a, b = 0, 1
+ while b < n:
+ print b,
+ a, b = b, a+b
+# EOF
+ \end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Modules: example}
+ \begin{lstlisting}
+>>> import foo
+>>> foo.fib(10)
+1 1 2 3 5 8
+>>> foo.some_var
+1
+ \end{lstlisting}
+\end{frame}
+
+
+\begin{frame}[fragile]
+ \frametitle{Python path}
+ \begin{itemize}
+ \item In IPython type the following
+ \end{itemize}
+ \begin{lstlisting}
+ import sys
+ sys.path
+ \end{lstlisting}
+ \begin{itemize}
+ \item List of locations where python searches for a module
+ \item \texttt{import sys} -- searches for file \texttt{sys.py} or
+ dir \texttt{sys} in all these locations
+ \item So, our own modules can be in any one of the locations
+ \item Current working directory is one of the locations
+ \item Can also set \texttt{PYTHONPATH} env var
+ \end{itemize}
+\end{frame}
+
+
+\begin{frame}[fragile]
+ \frametitle{Another example: GCD script}
+ \begin{itemize}
+ \item Function that computes gcd of two numbers
+ \item Save it as \texttt{gcd\_script.py}
+ \end{itemize}
+ \begin{lstlisting}
+ def gcd(a, b):
+ while b:
+ a, b = b, a%b
+ return a
+ \end{lstlisting}
+ \begin{itemize}
+ \item Also add the tests to the file
+ \end{itemize}
+ \begin{lstlisting}
+ if gcd(40, 12) == 4 and gcd(12, 13) == 1:
+ print "Everything OK"
+ else:
+ print "The GCD function is wrong"
+ \end{lstlisting}
+ \begin{lstlisting}
+ $ python gcd_script.py
+ \end{lstlisting} % $
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{\texttt{\_\_name\_\_}}
+ \begin{lstlisting}
+ import gcd_script
+ \end{lstlisting}
+ \begin{itemize}
+ \item The import is successful
+ \item But the test code, gets run
+ \item Add the tests to the following \texttt{if} block
+ \end{itemize}
+ \begin{lstlisting}
+ if __name__ == "__main__":
+ \end{lstlisting}
+ \begin{itemize}
+ \item Now the script runs properly
+ \item As well as the import works; test code not executed
+ \item \texttt{\_\_name\_\_} is local to every module and is equal
+ to \texttt{\_\_main\_\_} only when the file is run as a script.
+ \end{itemize}
+\end{frame}
+
+
+\begin{frame}[fragile]
+ \frametitle{Stand-alone scripts}
+Consider a file \texttt{f.py}:
+\footnotesize
+\begin{lstlisting}
+#!/usr/bin/env python
+"""Module level documentation."""
+# First line tells the shell that it should use Python
+# to interpret the code in the file.
+def f():
+ print "f"
+
+# Check if we are running standalone or as module.
+# When imported, __name__ will not be '__main__'
+if __name__ == '__main__':
+ # This is not executed when f.py is imported.
+ f()
+\end{lstlisting}
+\end{frame}
+
+
+\section{Exceptions}
+
+\begin{frame}{Motivation}
+ \begin{itemize}
+ \item How do you signal errors to a user?
+ \end{itemize}
+\end{frame}
+
+\begin{frame}
+ \frametitle{Exceptions}
+ \begin{itemize}
+ \item Python's way of notifying you of errors
+ \item Several standard exceptions: \texttt{SyntaxError}, \texttt{IOError}
+ etc.
+ \item Users can also \texttt{raise} errors
+ \item Users can create their own exceptions
+ \item Exceptions can be ``caught'' via \texttt{try/except} blocks
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Exception: examples}
+\begin{lstlisting}
+>>> 10 * (1/0)
+Traceback (most recent call last):
+ File "<stdin>", line 1, in ?
+ZeroDivisionError: integer division or modulo by zero
+>>> 4 + spam*3
+Traceback (most recent call last):
+ File "<stdin>", line 1, in ?
+NameError: name 'spam' is not defined
+>>> '2' + 2
+Traceback (most recent call last):
+ File "<stdin>", line 1, in ?
+TypeError: cannot concatenate 'str' and 'int' objects
+\end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Exception: examples}
+\begin{lstlisting}
+>>> while True:
+... try:
+... x = int(raw_input("Enter a number: "))
+... break
+... except ValueError:
+... print "Invalid number, try again..."
+...
+>>> # To raise exceptions
+... raise ValueError("your error message")
+Traceback (most recent call last):
+ File "<stdin>", line 2, in ?
+ValueError: your error message
+\end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Exception: try/finally}
+\begin{lstlisting}
+>>> while True:
+... try:
+... x = open("my_data.txt")
+... lines = x.readlines()
+... # Process the data from the file.
+... value = int(line[0])
+... except ValueError:
+... print "Invalid file!"
+... finally:
+... print "All good!"
+...
+\end{lstlisting}
+\end{frame}
+
+
+
+\end{document}
diff --git a/slides/test_driven_development/tdd_simple.tex b/slides/test_driven_development/tdd_simple.tex
new file mode 100644
index 0000000..ae57c69
--- /dev/null
+++ b/slides/test_driven_development/tdd_simple.tex
@@ -0,0 +1,342 @@
+\documentclass[12pt,presentation]{beamer}
+\usepackage[utf8]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage{fixltx2e}
+\usepackage{graphicx}
+\usepackage{longtable}
+\usepackage{float}
+\usepackage{wrapfig}
+\usepackage{soul}
+\usepackage{textcomp}
+\usepackage{marvosym}
+\usepackage{wasysym}
+\usepackage{latexsym}
+\usepackage{amssymb}
+\usepackage{hyperref}
+\tolerance=1000
+\usepackage[english]{babel} \usepackage{ae,aecompl}
+\usepackage{mathpazo,courier,euler} \usepackage[scaled=.95]{helvet}
+\usepackage{listings}
+\lstset{language=Python, basicstyle=\ttfamily\bfseries,
+commentstyle=\color{red}\itshape, stringstyle=\color{green},
+showstringspaces=false, keywordstyle=\color{blue}\bfseries}
+\providecommand{\alert}[1]{\textbf{#1}}
+
+\title{SEES: Test Driven Development}
+\author{FOSSEE}
+
+\usetheme{Warsaw}\usecolortheme{default}\useoutertheme{infolines}\setbeamercovered{transparent}
+
+\AtBeginSection[]
+{
+ \begin{frame}<beamer>
+ \frametitle{Outline}
+ \tableofcontents[currentsection]
+ \end{frame}
+}
+
+\begin{document}
+
+\maketitle
+
+\begin{frame}
+\frametitle{Outline}
+\setcounter{tocdepth}{3}
+\tableofcontents
+\end{frame}
+
+\section{Introduction}
+
+\begin{frame}
+ \frametitle{Objectives}
+ At the end of this section, you will be able to:
+ \begin{itemize}
+ \item Write your code using the TDD paradigm.
+ \item Use the nose module to test your code.
+ \end{itemize}
+\end{frame}
+
+\begin{frame}
+ \frametitle{What is TDD?}
+ The basic steps of TDD are roughly as follows --
+ \begin{enumerate}
+ \item<1-> Decide upon feature to implement and methodology of
+ testing
+ \item<2-> Write tests for feature decided upon
+ \item<3-> Just write enough code, so that the test can be run, but it fails.
+ \item<4-> Improve the code, to just pass the test and at the same time
+ passing all previous tests.
+ \item<5-> Run the tests to see, that all of them run successfully.
+ \item<6-> Refactor the code you've just written -- optimize the algorithm,
+ remove duplication, add documentation, etc.
+ \item<7-> Run the tests again, to see that all the tests still pass.
+ \item<8-> Go back to 1.
+ \end{enumerate}
+\end{frame}
+
+\section{First Test}
+
+\begin{frame}[fragile]
+ \frametitle{First Test -- GCD}
+ \begin{itemize}
+ \item simple program -- GCD of two numbers
+ \item What are our code units?
+ \begin{itemize}
+ \item Only one function \texttt{gcd}
+ \item Takes two numbers as arguments
+ \item Returns one number, which is their GCD
+ \end{itemize}
+\begin{lstlisting}
+c = gcd(44, 23)
+\end{lstlisting}
+ \item c will contain the GCD of the two numbers.
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Test Cases}
+ \begin{itemize}
+ \item Important to have test cases and expected outputs even before
+ writing the first test!
+ \item $a=48$, $b=48$, $GCD=48$
+ \item $a=44$, $b=19$, $GCD=1$
+ \item Tests are just a series of assertions
+ \item True or False, depending on expected and actual behavior
+ \end{itemize}
+
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Test Cases -- general idea}
+\begin{lstlisting}
+tc1 = gcd(48, 64)
+if tc1 != 16:
+ print "Failed for a=48, b=64. Expected 16. \
+ Obtained %d instead." % tc1
+ exit(1)
+
+tc2 = gcd(44, 19)
+if tc2 != 1:
+ print "Failed for a=44, b=19. Expected 1. \
+ Obtained %d instead." % tc2
+ exit(1)
+
+print "All tests passed!"
+\end{lstlisting}
+\begin{itemize}
+\item The function \texttt{gcd} doesn't even exist!
+\end{itemize}
+\end{frame}
+
+
+\begin{frame}[fragile]
+ \frametitle{Test Cases -- code}
+ \begin{itemize}
+ \item Let us make it a function!
+ \item Use assert!
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Test Cases -- code}
+\begin{lstlisting}
+# gcd.py
+def test_gcd():
+ assert gcd(48, 64) == 16
+ assert gcd(44, 19) == 1
+
+test_gcd()
+\end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Stubs}
+ \begin{itemize}
+ \item First write a very minimal definition of \texttt{gcd}
+ \begin{lstlisting}
+def gcd(a, b):
+ pass
+ \end{lstlisting}
+ \item Written just, so that the tests can run
+ \item Obviously, the tests are going to fail
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{\texttt{gcd.py}}
+\begin{lstlisting}
+def gcd(a, b):
+ pass
+
+def test_gcd():
+ assert gcd(48, 64) == 16
+ assert gcd(44, 19) == 1
+
+if __name__ == '__main__':
+ test_gcd()
+\end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{First run}
+\begin{lstlisting}
+$ python gcd.py
+Traceback (most recent call last):
+ File "gcd.py", line 9, in <module>
+ test_gcd()
+ File "gcd.py", line 5, in test_gcd
+ assert gcd(48, 64) == 16
+AssertionError
+\end{lstlisting} %$
+
+ \begin{itemize}
+ \item We have our code unit stub, and a failing test.
+ \item The next step is to write code, so that the test just passes.
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Euclidean Algorithm}
+ \begin{itemize}
+ \item Modify the \texttt{gcd} stub function
+ \item Then, run the script to see if the tests pass.
+ \end{itemize}
+\begin{lstlisting}
+def gcd(a, b):
+ if a == 0:
+ return b
+ while b != 0:
+ if a > b:
+ a = a - b
+ else:
+ b = b - a
+ return a
+\end{lstlisting}
+\begin{lstlisting}
+$ python gcd.py
+All tests passed!
+\end{lstlisting} %$
+ \begin{itemize}
+ \item \alert{Success!}
+ \end{itemize}
+\end{frame}
+
+
+\begin{frame}[fragile]
+ \frametitle{Euclidean Algorithm -- Modulo}
+ \begin{itemize}
+ \item Repeated subtraction can be replaced by a modulo
+ \item modulo of \texttt{a\%b} is always less than b
+ \item when \texttt{a < b}, \texttt{a\%b} equals \texttt{a}
+ \item Combine these two observations, and modify the code
+\begin{lstlisting}
+def gcd(a, b):
+ while b != 0:
+ a, b = b, a % b
+ return a
+\end{lstlisting}
+ \item Check that the tests pass again
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Euclidean Algorithm -- Recursive}
+ \begin{itemize}
+ \item Final improvement -- make \texttt{gcd} recursive
+ \item More readable and easier to understand
+\begin{lstlisting}
+def gcd(a, b):
+ if b == 0:
+ return a
+ return gcd(b, a%b)
+\end{lstlisting}
+ \item Check that the tests pass again
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Document \texttt{gcd}}
+ \begin{itemize}
+ \item Undocumented function is as good as unusable
+ \item Let's add a docstring \& We have our first test!
+ \end{itemize}
+\begin{lstlisting}
+def gcd(a, b):
+ """Returns the Greatest Common Divisor of the
+ two integers passed as arguments.
+
+ Args:
+ a: an integer
+ b: another integer
+
+ Returns: Greatest Common Divisor of a and b
+ """
+ if b == 0:
+ return a
+ return gcd(b, a%b)
+\end{lstlisting}
+\end{frame}
+
+
+\begin{frame}[fragile]
+ \frametitle{Persistent Test Cases}
+ \begin{itemize}
+ \item Tests should be pre-determined and written, before the code
+ \item The file shall have multiple lines of test data
+ \item Separates the code from the tests
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Separate \texttt{test\_gcd.py}}
+\begin{lstlisting}
+from gcd import gcd
+
+def test_gcd():
+ assert gcd(48, 64) == 16
+ assert gcd(44, 19) == 1
+
+if __name__ == '__main__':
+ test_gcd()
+\end{lstlisting}
+\end{frame}
+
+\section{Python Testing Frameworks}
+
+\begin{frame}[fragile]
+ \frametitle{Python Testing Frameworks}
+ \begin{itemize}
+ \item Testing frameworks essentially, ease the job of the user
+ \item Python provides two frameworks for testing code
+ \begin{itemize}
+ \item \texttt{unittest} framework
+ \item \texttt{doctest} module
+ \end{itemize}
+\item \texttt{nose} is a package to help test
+ \end{itemize}
+\end{frame}
+
+\subsection{\texttt{nose}}
+
+\begin{frame}[fragile]
+ \frametitle{\texttt{nose} tests}
+ \begin{itemize}
+ \item It is not easy to organize, choose and run tests scattered
+ across multiple files.
+ \item \texttt{nose} module aggregate these tests automatically
+ \item Can aggregate \texttt{unittests} and \texttt{doctests}
+ \item Allows us to pick and choose which tests to run
+ \item Helps output the test-results and aggregate them in various
+ formats
+ \item Not part of the Python distribution itself
+\begin{lstlisting}
+$ apt-get install python-nose
+\end{lstlisting} %$
+ \item Run the following command in the top level directory
+\begin{lstlisting}
+$ nosetests
+\end{lstlisting} %$
+ \end{itemize}
+\end{frame}
+
+\end{document}