diff options
author | Srikant | 2012-01-24 16:19:59 +0530 |
---|---|---|
committer | Srikant | 2012-01-24 16:19:59 +0530 |
commit | 2965bf37bb8fc6c6d672d6775612531e4a3074ba (patch) | |
tree | 72fd647da1fe30c6ae57ecbd264ac6a0498731a2 /TDD/using_python_framework_for_tdd | |
parent | b5a5acdddb2ef001e9c97a2959b0dbff9096423c (diff) | |
download | sdes-stscripts-2965bf37bb8fc6c6d672d6775612531e4a3074ba.tar.gz sdes-stscripts-2965bf37bb8fc6c6d672d6775612531e4a3074ba.tar.bz2 sdes-stscripts-2965bf37bb8fc6c6d672d6775612531e4a3074ba.zip |
Added supporting files.
Added script and slides for 'using_python_framework_for_tdd',
math_utils diretory contains files used in the tutorials,
two_column.py is added to convert script.rst into
two column format.Use it as:
$ two_column.py tdd1_script.rst
image dir contains png files for iitb logo's etc.
Diffstat (limited to 'TDD/using_python_framework_for_tdd')
-rw-r--r-- | TDD/using_python_framework_for_tdd/tdd2.tex | 365 | ||||
-rwxr-xr-x | TDD/using_python_framework_for_tdd/tdd2_script.rst | 198 |
2 files changed, 563 insertions, 0 deletions
diff --git a/TDD/using_python_framework_for_tdd/tdd2.tex b/TDD/using_python_framework_for_tdd/tdd2.tex new file mode 100644 index 0000000..561f4a2 --- /dev/null +++ b/TDD/using_python_framework_for_tdd/tdd2.tex @@ -0,0 +1,365 @@ +\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} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +\begin{document} + +\begin{frame} +\begin{center} +\vspace{12pt} +\textcolor{blue}{\huge Test Driven Development \\Part II} +\end{center} +\vspace{18pt} +\begin{center} +\vspace{10pt} +\includegraphics[scale=0.95]{../images/fossee-logo.png}\\ +\vspace{5pt} +\scriptsize Developed by FOSSEE Team, IIT-Bombay. \\ +\scriptsize Funded by National Mission on Education through ICT\\ +\scriptsize MHRD,Govt. of India\\ +\includegraphics[scale=0.30]{../images/iitb-logo.png}\\ +\end{center} +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Introduction} + +\begin{frame} + \frametitle{Objectives} + At the end of this tutorial, you will be able to, + \begin{itemize} + \item Know what are persistent test cases. + \item Write doctest \& unittest for any given function. + \item Understand the use of nosetest. + + \end{itemize} + \end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\begin{frame} +\frametitle{Pre-requisite} +\label{sec-3} + +Spoken tutorial on - +\begin{itemize} +\item Test Driven Development -- Part I +\end{itemize} +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\begin{frame}[fragile] + \frametitle{Persistent Test Cases} + \begin{itemize} + \item Tests should be pre-determined and written, before the code + \item Test Data is repeatedly used; Hence, saved in persistent + format + \item Let's save data for fibonacci tests in a text file. + \item The file shall have multiple lines of test data + \item Each line corresponds to a single test case + \item Each line consists of two comma separated values -- + \begin{itemize} + \item First coloumn is the integer which has to be + passed to the function. + \item Second coloumn is the return value from the function. + \end{itemize} + \item Let us call our data file \texttt{fibonacci\_testcases.dat} + \end{itemize} +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[fragile] + \frametitle{Modify \texttt{fibonacci.py}} +\begin{lstlisting} +if __name__ == '__main__': + for line in open('fibonacci_testcases.dat'): + values = line.split(', ') + n = int(values[0]) + a = int(values[1]) + + tc = fibonacci(n) + if tc != a: + print "Failed for n=%d.\ + Expected %d. Obtained %d instead."\ + % (n, a, tc) + exit(1) + + print "All tests passed!" +\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} + \end{itemize} +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{\texttt{doctest} module} + +\begin{frame}[fragile] + \frametitle{doctest} + \begin{itemize} + \item Documentation always accompanies a well written piece of code + \item Use \texttt{docstring} to document functions or modules + \item Along with description and usage, examples can be added + \item Interactive interpreter session inputs and outputs are + copy-pasted + \item \texttt{doctest} module picks up all such interactive examples + \item Executes them and determines if the code runs, as documented + \end{itemize} + Let's use the \texttt{doctest} module for our \texttt{fibonacci} function +\end{frame} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\begin{frame}[fragile] + \frametitle{doctest for \texttt{fibonacci.py}} +\begin{tiny} +\begin{lstlisting} +def fibonacci(n): + """Returns the nth fibonacci number. + + Args: + n: an integer + + + >>> fibonacci(3) + 2 + >>> fibonacci(4) + 3 + """ + if n == 0: + return 0 + elif n == 1: + return 1 + else: + return fibonacci(n-1) + fibonacci(n-2) +\end{lstlisting} +\end{tiny} +\begin{itemize} +\item We have added examples to the \texttt{docstring} +\item Now we need to tell the \texttt{doctest} module to execute +\end{itemize} +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[fragile] + \frametitle{doctest for \texttt{fibonacci.py} \ldots} +\begin{lstlisting} +if __name__ == "__main__": + import doctest + doctest.testmod() +\end{lstlisting} +\begin{itemize} +\item \texttt{testmod} automatically picks all sample sessions +\item Executes them and compares output with documented output +\item It doesn't give any output, when all the results match +\item Complains only when one or more tests fail. +\end{itemize} +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[fragile] + \frametitle{\texttt{doctest} -- Execution} + \begin{itemize} + \item Run the doctests by running \texttt{fibonacci.py} +\begin{lstlisting} +$ python fibonacci.py +\end{lstlisting} %$ + \item All the tests pass, and doctest gives no output + \item For a more detailed report we can run with -v argument +\begin{lstlisting} +$ python fibonacci.py -v +\end{lstlisting} %$ + \item If the output contains a blank line, use \texttt{<BLANKLINE>} + \item To see a failing test case, replace \texttt{return a} with \texttt{b} + \end{itemize} +\end{frame} + +\subsection{\texttt{unittest} framework} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[fragile] + \frametitle{\texttt{unittest}} + \begin{itemize} + \item It won't be long, before we complain about the power of + \texttt{doctest} + \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{fibonacci.py}} + \begin{itemize} + \item Subclass the \texttt{TestCase} class in \texttt{unittest} + \item Place all the test code as methods of this class + \item Use the test cases present in \texttt{fibonacci\_testcases.dat} + \item Place the code in \texttt{test\_fibonacci.py} + \end{itemize} +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[fragile,allowframebreaks] + \frametitle{\texttt{test\_fibonacci.py}} +\small +\begin{lstlisting} +import fibonacci +import unittest + +class TestFibonacciFunction(unittest.TestCase): + + def setUp(self): + self.test_file = \ + open('fibonacci_testcases.dat') + self.test_cases = [] + for line in self.test_file: + values = line.split(', ') + n = int(values[0]) + a = int(values[1]) + + self.test_cases.append([n, a]) + + def test_fibonacci(self): + for case in self.test_cases: + n = case[0] + a = case[1] + self.assertEqual(fibonacci.fibonacci(n),a) + + def tearDown(self): + self.test_file.close() + del self.test_cases + +if __name__ == '__main__': + unittest.main() +\end{lstlisting} +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[fragile] + \frametitle{\texttt{test\_fibonacci.py}} + \begin{itemize} + \item \texttt{setUp} -- we read all the test data and store it in a + list + \item \texttt{tearDown} -- delete the data to free up memory and + close open file + \item \texttt{test\_fibonacci} -- actual test code + \item \texttt{assertEqual} -- compare actual result with expected one + \item Write documentation for above code. + \end{itemize} +\end{frame} + +\section{\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} +$ easy_install nose +\end{lstlisting} %$ + \item Run the following command in the top level directory +\begin{lstlisting} +$ nosetests +\end{lstlisting} %$ + \end{itemize} +\end{frame} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame} +\frametitle{Summary} +\label{sec-8} + + In this tutorial, we have learnt to, + + +\begin{itemize} +\item Use of persistent test cases for better control. +\item Undestand the use of doctest \& unittest. +\item Understand the use of nosetest . + +\end{itemize} +\end{frame} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[fragile] +\frametitle{Evaluation} +\label{sec-9} + + +\begin{enumerate} +\item ? +\vspace{8pt} +\item ? +\end{enumerate} +\end{frame} +\begin{frame} +\frametitle{Solutions} +\label{sec-10} + + +\begin{enumerate} +\item +\vspace{15pt} +\item +\end{enumerate} +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\begin{frame} + + \begin{block}{} + \begin{center} + \textcolor{blue}{\Large THANK YOU!} + \end{center} + \end{block} +\begin{block}{} + \begin{center} + For more Information, visit our website\\ + \url{http://fossee.in/} + \end{center} + \end{block} +\end{frame} + + +\end{document} diff --git a/TDD/using_python_framework_for_tdd/tdd2_script.rst b/TDD/using_python_framework_for_tdd/tdd2_script.rst new file mode 100755 index 0000000..85c96d5 --- /dev/null +++ b/TDD/using_python_framework_for_tdd/tdd2_script.rst @@ -0,0 +1,198 @@ +.. Objectives +.. ---------- + + .. At the end of this tutorial, you will be able to: + + .. 1. Know what is TDD. + .. 2. Understand the use of test cases. + .. 3. Write simple tests for a function. + +.. Prerequisites +.. ------------- + +.. 1. Test driven development - Part 1 + + +Script +------ + +.. L1 + +{{{ Show the first slide containing title, name of the production +team along with the logo of MHRD }}} + +.. R1 + +Hello friends and Welcome to the tutorial on +'Test driven development - Part 2'. + +.. L2 + +{{{ Show slide with objectives }}} + +.. R2 + +At the end of this tutorial, you will be able to, + + 1. understand use of persistent test cases. + #. write doctest and unittest for any given function. + #. and understand the use of nosetest. + +.. L3 + +{{{ Switch to the slide3, pre-requisite slide }}} + +.. R3 + +Before beginning this tutorial,we would suggest you to complete the +tutorial on "Test driven development-part 1". + +.. R4 + + + +.. L4 + +{{{ Switch to slide4 ,Persistent test cases}}} + + +.. R5 + +To illustrate TDD, lets take a simple program. Consider a +function ``fibonacci``, that takes one argument and returns +the nth number of ``fibonacci`` series. + +.. L5 + +{{{ Switch to slide5, First test- fibonacci }}} + +.. R6 + +To test ``fibonacci`` function, we need test +cases. +As shown in this slide, +test cases are expected outputs for a given set of inputs. + + +.. L6 + +{{{ Switch to slide6, Test cases }}} + +.. R7 + +The sample code for test cases is shown here. Observe that if +any ``if`` statement is executed, test aborts after printing the +error message. + +.. L7 + +{{{ Switch to slide7, Test cases-Code }}} + +.. R8 + +The ``fibonacci`` function is written just enough so that +test can run. + + +.. L8 + +{{{ switch to slide8, Stubs }}} + +.. R9 + +Combine the function and test cases and put them together in +``fibonacci.py`` file.Add the test cases after name=main idiom. + +.. L9 + +{{{ Switch to slide9, fibonacci.py }}} + +.. R10 + +Lets run fibonacci.py by typing ``python fibonacci.py``. +As we haven't written any meaningful code in our ``fibonacci`` +function, it fails immediately. +Our next step is to write just minimum code to pass our tests. + +.. L10 + +{{{ Run the fibonacci.py in terminal and show the error output.}}} +:: + + python fibonacci.py + +.. R11 + +Modify the fibonacci stub function with given code. +Save and run it again as `` python fibonacci.py``. +{{{ pause }}} +Observe that, there will be no errors, as +the test passes successfully. + +.. L11 + +{{{ switch to slide-11, Euclidean Algorithm }}} +Switch to terminal and modify fibonacci function in ``nano`` +editor and run. +:: + + python fibonacci.py + +.. R12 + +The same ``fibonacci`` function is modified to make it more readable +and easy to understand using recursion. +Pause this video here.Replace the ``fibonacci`` function with recursive one. +Run the modified ``fibonacci.py`` file. The test should pass again +without any errors. +After successfully achieving this result, you can resume the video. + +.. L12 + +{{{ Show slide12, Euclidean Algorithm- Recursive}}} + + +.. R13 + +This brings us to the end of the tutorial.In this tutorial, + we have learnt to, + + 1. Undestand the basic steps involved in Test driven development. + #. Design a Test driven approach for a given ``fibonacci`` function. + + +.. L13 + +{{{ switch to slide-13,Summary }}} + +.. R14 + +Here are some self assessment questions for you to solve + 1. + + 2. + +.. L14 + +{{{ switch to slide-14, Evaluation }}} + +.. R15 + +And the answers are, + 1. + + 2. + +.. L15 + +{{{ switch to slide-15 ,Solutions}}} + +.. R16 + +Hope you have enjoyed this tutorial and found it useful. +Thank you! + +.. L16 + +{{{ Switch to slide-16, Thankyou}}} + |