testing-debugging/script.rst
changeset 522 d33698326409
parent 521 88a01948450d
child 523 54bdda4aefa5
equal deleted inserted replaced
521:88a01948450d 522:d33698326409
     1 .. Objectives
       
     2 .. ----------
       
     3 
       
     4 .. Writing Simple Tests (Applying)
       
     5 .. Automating these tests
       
     6 .. Coding Style
       
     7 .. Errors and Exceptions 
       
     8 
       
     9 .. Prerequisites
       
    10 .. -------------
       
    11 
       
    12 ..   1. Getting started with functions
       
    13 ..   2. Advanced Features of Functions   
       
    14      
       
    15 .. Author              : Amit Sethi
       
    16    Internal Reviewer   : 
       
    17    External Reviewer   :
       
    18    Checklist OK?       : <put date stamp here, if OK> [2010-10-05]
       
    19 
       
    20 Script
       
    21 ------
       
    22 
       
    23 {{{ Show the slide containing title }}}
       
    24 
       
    25 Hello Friends. Welcome to this tutorial on Testing and Debugging.
       
    26 
       
    27 {{{ Show the outline slide }}}
       
    28 
       
    29 In this tutorial we will learn.
       
    30 
       
    31 1.What software Testing is? 
       
    32 2.Learn to test simple functions for their functionality.
       
    33 3.Learn how to automate tests. 
       
    34 4.Need for coding style and some of the standards followed by the Python Community.
       
    35 5.Handling Errors and Exceptions.
       
    36 
       
    37 Software testing is an activity aimed at evaluating a program 
       
    38 and determining that it meets its required results.
       
    39 
       
    40 {{{ Slide with the function }}}
       
    41 
       
    42 Lets first write a simple function to calculate gcd of two numbers.::
       
    43 
       
    44      def gcd(a, b):
       
    45       	 if b == 0:
       
    46             return a
       
    47       	 return gcd(b, a%b)
       
    48 
       
    49 save this into a file "/home/fossee/gcd.py".
       
    50 
       
    51 Now we need to evaluate this function. Thus we have to check whether 
       
    52 function successfully gives us the gcd of two whole numbers. Thus we need
       
    53 a set of inputs and the exact outputs that are expected for those input 
       
    54 test cases.
       
    55 
       
    56 Let our test case be 48 and 64 as *a* and *b* respectively. For this test
       
    57 case we know that the GCD is 16. So that is the expected output. 
       
    58 
       
    59 {{{ Slide with change in code }}}
       
    60 
       
    61 Let us include code for testing in our  **gcd.py** file ::
       
    62 
       
    63   def gcd(a, b):
       
    64       if b == 0:
       
    65           return a
       
    66       return gcd(b, a%b)
       
    67   
       
    68   if __name__ == '__main__':
       
    69       result = gcd(48, 64)
       
    70       if result != 16:
       
    71           print "Test failed"
       
    72       print "Test Passed"
       
    73           
       
    74 Note that we have introduced a new semantic which uses two new magic names
       
    75 in Python *__name__* and *__main__*. This is a very common idiom used in
       
    76 Python. Every Python code in a file can be run in two ways: Either as an
       
    77 independent stand-alone script or as a Python module which can be imported
       
    78 by other Python scripts or modules. When the idiom::
       
    79 
       
    80   if __name__ == '__main__':
       
    81 
       
    82 {{{ Slide with the idiom }}}
       
    83 
       
    84 
       
    85 is used, the code within this if block is executed first when we run the
       
    86 Python file as a stand-alone script. In other words, when we run this
       
    87 python file as a stand-alone script the control of the program first starts
       
    88 from the code that is within this if block from which the control is
       
    89 transferred to other parts of the program or to other modules from
       
    90 here. This comes as an extremely handy feature especially when we want to
       
    91 test our modules individually.
       
    92       
       
    93 But there can be a number of places where the gcd function might break would we
       
    94 have to right a seperate test case for all of them. 
       
    95 
       
    96 Following is an (are) exercise(s) that you must do. 
       
    97 
       
    98 %% %% Write code for lcm and write tests for it  
       
    99 
       
   100 %% %% Answer is on the screen.
       
   101 
       
   102 Well thats where automating tests come in. We can run many tests to check where our
       
   103 code can break. Lets see this with an example. Lets try and automate tests on the 
       
   104 gcd function. For this we will write a file with test cases and call the function
       
   105 for all of them.
       
   106 
       
   107 {{{ Slide with the structure of file }}}
       
   108 
       
   109 The structure of the file will be the two parameters and the output result seperated 
       
   110 by space::
       
   111     
       
   112     |   12 |    28 |    4 |
       
   113     |   18 |    36 |   18 |
       
   114     | 4678 | 39763 | 2339 |
       
   115 
       
   116 The file structure is shown in form a table here.
       
   117 
       
   118 
       
   119 {{{ Slide with code piece }}}
       
   120 
       
   121 We add the code piece to automate the test.::
       
   122 
       
   123 
       
   124    if __name__ == '__main__':
       
   125       for line in open('testcases.txt'):
       
   126         numbers = line.split()
       
   127         x = int(numbers[0])
       
   128         y = int(numbers[1])
       
   129         result = int(numbers[2])
       
   130        	if gcd(x, y) != result:
       
   131             print "Failed gcd test for", x, y
       
   132 
       
   133 %% %% Pause the video do the following exercise 
       
   134 %% %% For the same inputs as gcd write automated tests for LCM.
       
   135 %% %% The solution is on the screen
       
   136 
       
   137 For any program there can be innumerable test cases thus it is not
       
   138 possible to test cases. However there are many ideas to reduce the set of
       
   139 test cases by testing those cases that are more likely to show errors.
       
   140 
       
   141 Moving from testing lets talk a bit about coding style now.
       
   142 
       
   143 Apart from from being able to perform the required task, a property
       
   144 of a good program is its readability. Code is read more often than it is
       
   145 written. This is because that way other people can learn from it and extend 
       
   146 and improve it. There are certain pointers for readable code that I am going to discuss.
       
   147 
       
   148 First, Naming variables.
       
   149 
       
   150 {{{ Slide with code snippet }}}
       
   151 
       
   152 Choose name that by which people will most likely guess the usage.Lets look at this 
       
   153 with an example::
       
   154 
       
   155        amount = 12.68
       
   156        denom = 0.05
       
   157        nCoins = round(amount/denom)
       
   158        rAmount = nCoins * denom
       
   159  
       
   160 As we can see in the example it is very easy to make what the code is doing.
       
   161 
       
   162 One can almost read it as English sentences.
       
   163 Amount is 12.68
       
   164 Denomination is .05
       
   165 Number of coins is round of amount by denominations.
       
   166 
       
   167 Proper naming helps so much in understanding the code.
       
   168 
       
   169 {{{ Slide with code style points }}}
       
   170 
       
   171 Also one should use. ::
       
   172      
       
   173      1.Four Space Indentation
       
   174      2.Limit to 79 characters a line, but readability should come first.
       
   175      3.Functions and methods should be separated with two blank lines. 
       
   176      4.No inline comments, comments should be above the line they comment.
       
   177      5.Use Docstring to explain units of code performing specific task like
       
   178      	functions.
       
   179      6.We should always have whitespace around operators and after punctuation. 
       
   180 
       
   181 %% %% Pause and do the following exercise
       
   182 %% %% Give meaningful names to the variables in following
       
   183 code
       
   184 	c=a/b
       
   185 
       
   186 
       
   187 This will help enormously towards making our program more readable.
       
   188 
       
   189 From coding style lets move on to handling errors and exceptions.  
       
   190 
       
   191 {{{ Slide with code snippet }}}
       
   192 
       
   193 Lets try out the following piece of code::
       
   194 
       
   195      while True print 'Hello world'
       
   196 
       
   197 {{{ Slide with Error }}}
       
   198 
       
   199 what happens when we do this on the interpreter. The interpreter 
       
   200 says that this is a syntax error. Syntax error are caused when we
       
   201 do not follow the rules of the programming language.
       
   202    
       
   203 {{{ Slide with expression }}}
       
   204 
       
   205 However lets try an expression like ::
       
   206 
       
   207 	1/0
       
   208 
       
   209 {{{ Slide with Error }}}
       
   210 
       
   211 Although this expression follows the programming language rules,
       
   212 however it is not possible to express the solution of this expression.
       
   213 Thus python throws an exception called ZeroDivisionError. Exception 
       
   214 is special kind of failure reported by the programming language.
       
   215 
       
   216 
       
   217 
       
   218 Lets see why and how we can use Exception in our programs.
       
   219 
       
   220 
       
   221 
       
   222 Type on your interpreter::
       
   223 
       
   224      a = raw_input("Enter a number:")
       
   225      num = int(a) 
       
   226 
       
   227 {{{ Run this code on interpreter with a character input }}}
       
   228 
       
   229 You will notice that when you run this program and give and
       
   230 non-numeric input it throws a 'ValueError' Exception. 
       
   231 
       
   232 So now we can 'catch' this exception and write code to 
       
   233 handle it.
       
   234 
       
   235 {{{ Slide with code snippet }}} 
       
   236 
       
   237 For this we have try and except clause in python. Lets change our 
       
   238 previous code slightly.::
       
   239 
       
   240 	 a = raw_input("Enter a number")
       
   241 	 try:
       
   242 		num = int(a)
       
   243    	 except:
       
   244 		print "Wrong input ..."
       
   245 
       
   246 {{{ Run the code with character input }}}
       
   247 
       
   248 In this piece of code python tries to run the code inside the try
       
   249 block but when if it fails it executes the code block in except.
       
   250 	  
       
   251 In previous example we encountered a problem with running our conversion
       
   252 to integer code. We found out what caused the error and then deviced a solution
       
   253 for it this whole process is called debugging.
       
   254  
       
   255 One can understand the debugging process using the figure.
       
   256 
       
   257 In debugging process we form a hypothesis of what causes the error.
       
   258 Test if it is correct by changing the code. And refine the hypothesis 
       
   259 on the basis of our result.
       
   260 
       
   261 
       
   262 
       
   263 Lets see another example of debugging. Create a file mymodule.py and
       
   264 add the following code::
       
   265     
       
   266     def test():
       
   267 	total=1+1	
       
   268 	print spam
       
   269 
       
   270 
       
   271 
       
   272 Lets now try and run this code ::
       
   273      
       
   274      import mymodule 
       
   275      mymodule.test()
       
   276 
       
   277 
       
   278 {{{ Slide with idb and total being accessed }}}
       
   279 
       
   280 Interpreter gives us an error because spam is not defined 
       
   281 but lets now do %debug on ipython interpreter. The prompt on the shell has changed to ipdb. This is debugger here you can access variables in that code block for example 'total'unlike the normal interpreter.
       
   282 
       
   283 %% %% Pause and do the following exercise
       
   284 %% %% Do the gcd program which takes input from user which tells
       
   285 %% %% the user wrong input if it is not valid and quits for 'q'.
       
   286  
       
   287 
       
   288 
       
   289 This brings us to the end of this tutorial on testing and debugging. 
       
   290 
       
   291 
       
   292 
       
   293 
       
   294 {{{ Show the summary slide }}}
       
   295  	
       
   296 In this tutorial we have learned to
       
   297 1.Create simple tests for a function.
       
   298 2.Learn to Automate tests using many predefined test cases.
       
   299 3.Good coding standards.
       
   300 4.Difference between syntax error and exception.
       
   301 5.Handling exception using try and except.
       
   302 6.Using %debug for debugging on ipython.
       
   303 
       
   304 {{{ Show the "sponsored by FOSSEE" slide }}}
       
   305 
       
   306 This tutorial was created as a part of FOSSEE project, NME ICT, MHRD India
       
   307 
       
   308 Hope you have enjoyed and found it useful.
       
   309 Thank you!
       
   310 
       
   311 
       
   312 
       
   313 
       
   314 
       
   315 
       
   316