93 |
93 |
94 |
94 |
95 |
95 |
96 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
96 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
97 % Title page |
97 % Title page |
98 \title[]{Debugging and \\Test Driven Approach} |
98 \title[Python Development]{Python Development} |
99 |
99 |
100 \author[FOSSEE] {FOSSEE} |
100 \author[FOSSEE] {FOSSEE} |
101 |
101 |
102 \institute[IIT Bombay] {Department of Aerospace Engineering\\IIT Bombay} |
102 \institute[IIT Bombay] {Department of Aerospace Engineering\\IIT Bombay} |
103 \date[] {11, October 2009} |
103 \date[] {1 November, 2009\\Day 2, Session 3} |
104 \date[] % (optional) |
|
105 |
|
106 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
107 |
105 |
108 %\pgfdeclareimage[height=0.75cm]{iitblogo}{iitblogo} |
106 %\pgfdeclareimage[height=0.75cm]{iitblogo}{iitblogo} |
109 %\logo{\pgfuseimage{iitblogo}} |
107 %\logo{\pgfuseimage{iitblogo}} |
110 |
108 |
140 |
138 |
141 \begin{frame} |
139 \begin{frame} |
142 \maketitle |
140 \maketitle |
143 \end{frame} |
141 \end{frame} |
144 |
142 |
|
143 \section{Tests: Getting started} |
|
144 \begin{frame}[fragile] |
|
145 \frametitle{gcd revisited!} |
|
146 \begin{itemize} |
|
147 \item Open gcd.py |
|
148 \end{itemize} |
|
149 \begin{lstlisting} |
|
150 def gcd(a, b): |
|
151 if a % b == 0: |
|
152 return b |
|
153 return gcd(b, a%b) |
|
154 |
|
155 print gcd(15, 65) |
|
156 print gcd(16, 76) |
|
157 \end{lstlisting} |
|
158 \begin{itemize} |
|
159 \item python gcd.py |
|
160 \end{itemize} |
|
161 \end{frame} |
|
162 |
|
163 \begin{frame}[fragile] |
|
164 \frametitle{Find lcm using our gcd module} |
|
165 \begin{itemize} |
|
166 \item Open lcm.py |
|
167 \item $lcm = \frac{a*b}{gcd(a,b)}$ |
|
168 \end{itemize} |
|
169 \begin{lstlisting} |
|
170 from gcd import gcd |
|
171 def lcm(a, b): |
|
172 return (a * b) / gcd(a, b) |
|
173 |
|
174 print lcm(14, 56) |
|
175 \end{lstlisting} |
|
176 \begin{itemize} |
|
177 \item python lcm.py |
|
178 \end{itemize} |
|
179 \begin{lstlisting} |
|
180 5 |
|
181 4 |
|
182 56 |
|
183 \end{lstlisting} |
|
184 \end{frame} |
|
185 |
|
186 \begin{frame}[fragile] |
|
187 \frametitle{Writing stand-alone module} |
|
188 Edit gcd.py file to: |
|
189 \begin{lstlisting} |
|
190 def gcd(a, b): |
|
191 if a % b == 0: |
|
192 return b |
|
193 return gcd(b, a%b) |
|
194 |
|
195 if __name__ == "__main__": |
|
196 print gcd(15, 65) |
|
197 print gcd(16, 76) |
|
198 \end{lstlisting} |
|
199 \begin{itemize} |
|
200 \item python gcd.py |
|
201 \item python lcm.py |
|
202 \end{itemize} |
|
203 \end{frame} |
|
204 |
|
205 \begin{frame}[fragile] |
|
206 \frametitle{More use of main} |
|
207 For automating tests. |
|
208 \begin{lstlisting} |
|
209 if __name__ == '__main__': |
|
210 for line in open('numbers.txt'): |
|
211 numbers = line.split() |
|
212 x = int(numbers[0]) |
|
213 y = int(numbers[1]) |
|
214 result = (int(numbers[2])) |
|
215 assert gcd(x, y) == result |
|
216 \end{lstlisting} |
|
217 \end{frame} |
|
218 |
|
219 \section{Coding Style} |
|
220 \begin{frame}{Readability and Consistency} |
|
221 \begin{itemize} |
|
222 \item Readability Counts!\\Code is read more often than its written. |
|
223 \item Consistency! |
|
224 \item Know when to be inconsistent. |
|
225 \end{itemize} |
|
226 \end{frame} |
|
227 |
|
228 \begin{frame}[fragile] \frametitle{A question of good style} |
|
229 \begin{lstlisting} |
|
230 amount = 12.68 |
|
231 denom = 0.05 |
|
232 nCoins = round(amount/denom) |
|
233 rAmount = nCoins * denom |
|
234 \end{lstlisting} |
|
235 \pause |
|
236 \begin{block}{Style Rule \#1} |
|
237 Naming is 80\% of programming |
|
238 \end{block} |
|
239 \end{frame} |
|
240 |
|
241 \begin{frame}[fragile] |
|
242 \frametitle{Code Layout} |
|
243 \begin{itemize} |
|
244 \item Indentation |
|
245 \item Tabs or Spaces?? |
|
246 \item Maximum Line Length |
|
247 \item Blank Lines |
|
248 \item Encodings |
|
249 \end{itemize} |
|
250 \end{frame} |
|
251 |
|
252 \begin{frame}{Whitespaces in Expressions} |
|
253 \begin{itemize} |
|
254 \item When to use extraneous whitespaces?? |
|
255 \item When to avoid extra whitespaces?? |
|
256 \item Use one statement per line |
|
257 \end{itemize} |
|
258 \end{frame} |
|
259 |
|
260 \begin{frame}{Comments} |
|
261 \begin{itemize} |
|
262 \item No comments better than contradicting comments |
|
263 \item Block comments |
|
264 \item Inline comments |
|
265 \end{itemize} |
|
266 \end{frame} |
|
267 |
|
268 \begin{frame}{Docstrings} |
|
269 \begin{itemize} |
|
270 \item When to write docstrings? |
|
271 \item Ending the docstrings |
|
272 \item One liner docstrings |
|
273 \end{itemize} |
|
274 More information at PEP8: http://www.python.org/dev/peps/pep-0008/ |
|
275 \inctime{5} |
|
276 \end{frame} |
145 |
277 |
146 \section{Debugging} |
278 \section{Debugging} |
147 \subsection{Errors and Exceptions} |
279 \subsection{Errors and Exceptions} |
148 \begin{frame}[fragile] |
280 \begin{frame}[fragile] |
149 \frametitle{Errors} |
281 \frametitle{Errors} |
150 \begin{lstlisting} |
282 \begin{lstlisting} |
151 >>> while True print 'Hello world' |
283 In []: while True print 'Hello world' |
152 \end{lstlisting} |
284 \end{lstlisting} |
153 \pause |
285 \pause |
154 \begin{lstlisting} |
286 \begin{lstlisting} |
155 File "<stdin>", line 1, in ? |
287 File "<stdin>", line 1, in ? |
156 while True print 'Hello world' |
288 while True print 'Hello world' |
173 \end{frame} |
305 \end{frame} |
174 |
306 |
175 \begin{frame}[fragile] |
307 \begin{frame}[fragile] |
176 \frametitle{Exceptions} |
308 \frametitle{Exceptions} |
177 \begin{lstlisting} |
309 \begin{lstlisting} |
178 >>> 1 / 0 |
310 In []: 1 / 0 |
179 \end{lstlisting} |
311 \end{lstlisting} |
180 \pause |
312 \pause |
181 \begin{lstlisting} |
313 \begin{lstlisting} |
182 Traceback (most recent call last): |
314 Traceback (most recent call last): |
183 File "<stdin>", line 1, in <module> |
315 File "<stdin>", line 1, in <module> |
184 ZeroDivisionError: integer division |
316 ZeroDivisionError: integer division |
185 or modulo by zero |
317 or modulo by zero |
186 \end{lstlisting} |
318 \end{lstlisting} |
187 \end{frame} |
319 \end{frame} |
188 |
320 |
|
321 \begin{frame}[fragile] |
|
322 \frametitle{Handling Exceptions} |
|
323 Python uses \typ{try} and \typ{except} clause. |
|
324 %%Revisiting the raw\_input |
|
325 \begin{lstlisting} |
|
326 a = raw_input('Enter number(Q to quit):') |
|
327 try: |
|
328 num = int(a) |
|
329 print num |
|
330 except: |
|
331 if a == 'Q': |
|
332 print 'Exiting...' |
|
333 else: |
|
334 print 'Wrong input!' |
|
335 \end{lstlisting} |
|
336 |
|
337 |
|
338 \end{frame} |
|
339 |
|
340 %% \begin{frame}[fragile] |
|
341 %% \frametitle{Solving it with \typ{try} and \typ{except}} |
|
342 %% \vspace{-0.2in} |
|
343 %% \begin{lstlisting} |
|
344 %% highest = 0 |
|
345 %% for record in open('sslc1.txt'): |
|
346 %% fields = record.split(';') |
|
347 %% try: |
|
348 %% total = 0 |
|
349 %% for score_str in fields[3:8]: |
|
350 %% score = int(score_str) |
|
351 %% total += score |
|
352 %% if total > highest: |
|
353 %% highest = total |
|
354 %% except: |
|
355 %% pass |
|
356 %% print highest |
|
357 %% \end{lstlisting} |
|
358 %% \end{frame} |
189 \subsection{Strategy} |
359 \subsection{Strategy} |
190 \begin{frame}[fragile] |
360 \begin{frame}[fragile] |
191 \frametitle{Debugging effectively} |
361 \frametitle{Debugging effectively} |
192 \begin{itemize} |
362 \begin{itemize} |
193 \item \typ{print} based strategy |
363 \item \typ{print} based strategy |
207 |
377 |
208 \begin{frame}[fragile] |
378 \begin{frame}[fragile] |
209 \frametitle{Debugging in IPython} |
379 \frametitle{Debugging in IPython} |
210 \small |
380 \small |
211 \begin{lstlisting} |
381 \begin{lstlisting} |
212 In [1]: import mymodule |
382 In []: import mymodule |
213 In [2]: mymodule.test() |
383 In []: mymodule.test() |
214 --------------------------------------------- |
384 --------------------------------------------- |
215 NameError Traceback (most recent call last) |
385 NameError Traceback (most recent call last) |
216 <ipython console> in <module>() |
386 <ipython console> in <module>() |
217 mymodule.py in test() |
387 mymodule.py in test() |
218 1 def test(): |
388 1 def test(): |
219 ----> 2 print spam |
389 ----> 2 print spam |
220 NameError: global name 'spam' is not defined |
390 NameError: global name 'spam' is not defined |
221 |
391 |
222 In [3]: %debug |
392 In []: %debug |
223 > mymodule.py(2)test() |
393 > mymodule.py(2)test() |
224 0 print spam |
394 0 print spam |
225 ipdb> |
395 ipdb> |
226 \end{lstlisting} |
396 \end{lstlisting} |
227 \inctime{15} |
397 \inctime{15} |
230 \subsection{Exercise} |
400 \subsection{Exercise} |
231 \begin{frame}[fragile] |
401 \begin{frame}[fragile] |
232 \frametitle{Debugging: Exercise} |
402 \frametitle{Debugging: Exercise} |
233 \small |
403 \small |
234 \begin{lstlisting} |
404 \begin{lstlisting} |
235 import keyword |
405 science = {} |
236 f = open('/path/to/file') |
406 |
237 |
407 for record in open('sslc1.txt'): |
238 freq = {} |
408 fields = record.split(';') |
239 for line in f: |
409 region_code = fields[0].strip() |
240 words = line.split() |
410 |
241 for word in words: |
411 score_str = fields[6].strip() |
242 key = word.strip(',.!;?()[]: ') |
412 score = int(score_str) if score_str != 'AA' |
243 if keyword.iskeyword(key): |
413 else 0 |
244 value = freq[key] |
414 |
245 freq[key] = value + 1 |
415 if score > 90: |
246 |
416 science[region_code] += 1 |
247 print freq |
417 |
|
418 pie(science.values(), labels=science.keys()) |
|
419 savefig('science.png') |
248 \end{lstlisting} |
420 \end{lstlisting} |
249 \inctime{10} |
421 \inctime{10} |
250 \end{frame} |
422 \end{frame} |
251 |
423 |
252 %% \begin{frame} |
424 %% \begin{frame} |
291 \end{frame} |
463 \end{frame} |
292 |
464 |
293 \begin{frame}[fragile] |
465 \begin{frame}[fragile] |
294 \frametitle{Test for the palindrome: palindrome.py} |
466 \frametitle{Test for the palindrome: palindrome.py} |
295 \begin{lstlisting} |
467 \begin{lstlisting} |
296 from plaindrome import is_palindrome |
|
297 def test_function_normal_words(): |
468 def test_function_normal_words(): |
298 input = "noon" |
469 input = "noon" |
299 assert is_palindrome(input) == True |
470 assert is_palindrome(input) == True |
|
471 |
|
472 if __name__ == "main'': |
|
473 test_function_normal_words() |
300 \end{lstlisting} |
474 \end{lstlisting} |
301 \end{frame} |
475 \end{frame} |
302 |
476 |
303 \begin{frame}[fragile] |
477 \begin{frame}[fragile] |
304 \frametitle{Running the tests.} |
478 \frametitle{Running the tests.} |
305 \begin{lstlisting} |
479 \begin{lstlisting} |
306 $ nosetests test.py |
480 $ nosetests palindrome.py |
307 . |
481 . |
308 ---------------------------------------------- |
482 ---------------------------------------------- |
309 Ran 1 test in 0.001s |
483 Ran 1 test in 0.001s |
310 |
484 |
311 OK |
485 OK |
345 % |
519 % |
346 %\inctime{15} |
520 %\inctime{15} |
347 %\end{frame} |
521 %\end{frame} |
348 % |
522 % |
349 |
523 |
350 \begin{frame}[fragile] |
524 %% \begin{frame}[fragile] |
351 \frametitle{Exercise} |
525 %% \frametitle{Exercise} |
352 Based on Euclid's algorithm: |
526 %% Based on Euclid's algorithm: |
353 \begin{center} |
527 %% \begin{center} |
354 $gcd(a,b)=gcd(b,b\%a)$ |
528 %% $gcd(a,b)=gcd(b,b\%a)$ |
355 \end{center} |
529 %% \end{center} |
356 gcd function can be written as: |
530 %% gcd function can be written as: |
357 \begin{lstlisting} |
531 %% \begin{lstlisting} |
358 def gcd(a, b): |
532 %% def gcd(a, b): |
359 if a%b == 0: return b |
533 %% if a%b == 0: return b |
360 return gcd(b, a%b) |
534 %% return gcd(b, a%b) |
361 \end{lstlisting} |
535 %% \end{lstlisting} |
362 \vspace*{-0.15in} |
536 %% \vspace*{-0.15in} |
363 \begin{block}{Task} |
537 %% \begin{block}{Task} |
364 \begin{itemize} |
538 %% \begin{itemize} |
365 \item Write at least |
539 %% \item Write at least |
366 two tests for above mentioned function. |
540 %% two tests for above mentioned function. |
367 \item Write a non recursive implementation |
541 %% \item Write a non recursive implementation |
368 of gcd(), and test it using already |
542 %% of gcd(), and test it using already |
369 written tests. |
543 %% written tests. |
370 \end{itemize} |
544 %% \end{itemize} |
371 \end{block} |
545 %% \end{block} |
372 |
546 |
373 \inctime{15} |
547 %% \inctime{15} |
374 \end{frame} |
548 %% \end{frame} |
375 |
549 |
376 \begin{frame} |
550 \begin{frame} |
377 \frametitle{We have learned} |
551 \frametitle{Summary} |
|
552 We have coverd: |
378 \begin{itemize} |
553 \begin{itemize} |
379 \item Following and Resolving Error Messages. |
554 \item Following and Resolving Error Messages. |
380 \item Exceptions. |
555 \item Exceptions. |
|
556 \item Handling exceptions |
381 \item Approach for Debugging. |
557 \item Approach for Debugging. |
382 \item Writting and running tests. |
558 \item Writting and running tests. |
383 \end{itemize} |
559 \end{itemize} |
384 \end{frame} |
560 \end{frame} |
385 |
561 |