author | Madhusudan.C.S <madhusudancs@gmail.com> |
Tue, 31 Aug 2010 20:28:35 +0530 | |
changeset 116 | 958e2e9f2858 |
parent 115 | 7455326cac40 |
child 117 | fab0281a992f |
permissions | -rw-r--r-- |
116
958e2e9f2858
Adding the page header. Better late than never.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
115
diff
changeset
|
1 |
======================= |
958e2e9f2858
Adding the page header. Better late than never.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
115
diff
changeset
|
2 |
Test Driven Development |
958e2e9f2858
Adding the page header. Better late than never.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
115
diff
changeset
|
3 |
======================= |
958e2e9f2858
Adding the page header. Better late than never.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
115
diff
changeset
|
4 |
|
89
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
5 |
Fundamentals |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
6 |
============ |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
7 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
8 |
Test Driven Development, abbreviated as TDD is a method of software |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
9 |
development which banks on the idea of writing test cases that fail for the |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
10 |
code that doesn't even exist yet. The actual code is written later to pass |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
11 |
the test and then refactored. |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
12 |
|
109
0afd25eadf41
Add a section on real life tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
89
diff
changeset
|
13 |
First "Test" |
0afd25eadf41
Add a section on real life tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
89
diff
changeset
|
14 |
============ |
89
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
15 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
16 |
Writing a test is simple. Writing a failing test? It is much more simple. |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
17 |
Let us consider a very simple program which returns the Greatest Common |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
18 |
Divisor (GCD) of two numbers. Since the test cases for the code is written |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
19 |
prior to the code itself, it is necessary to have a clear idea of the code |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
20 |
units that our program will contain. Let us attempt to clearly define the |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
21 |
code units in our case of a GCD program. Let our program contain one and |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
22 |
only one function called gcd() which takes in two arguments as parameters. |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
23 |
These arguments are the numbers for which GCD must be computed. The gcd() |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
24 |
function returns a single value which is the GCD of the two arguments |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
25 |
passed. So if we want to find out GCD of 44, 23, I will call my code unit |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
26 |
as c = gcd(44, 23) where c will contain the GCD of those two numbers. |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
27 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
28 |
Now we have defined our code units, how will we write tests? Before writing |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
29 |
the test, a very fundamental question arises in our minds. How do tests |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
30 |
look like? So let us answer this question first. Tests are nothing but a |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
31 |
series of assertions which are either True or False depending on the |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
32 |
expected behaviour of the code. We tell our tests whether our code unit |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
33 |
asserts True or asserts False based on the expected behaviour of the code |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
34 |
units. If we happen to run the tests now we are sure to get errors. Oh! But |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
35 |
why? We don't even have the function gcd to call. The test code doesn't |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
36 |
even compile! So what should we do now? So the idea is to first write the |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
37 |
stubs for the code units before we start writing tests. This is necessary |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
38 |
for two reasons. Firstly, by writing the stubs for the code units we will |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
39 |
be able to correctly decide and fix on to the code units that we have |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
40 |
planned to include in our program. We have a clear cut idea as to how our |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
41 |
program is structured, how the tests must be written among other |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
42 |
things. Secondly, the tests must at least compile and then fail! If the |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
43 |
tests don't even compile, that doesn't mean the tests failed. It means |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
44 |
it was a failure on the programmer's part. Let us define our stub:: |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
45 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
46 |
def gcd(a, b): |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
47 |
pass |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
48 |
|
110
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
49 |
This stub does nothing other than defining a new function called gcd |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
50 |
which takes two parameters a and b for which the GCD must be |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
51 |
calculated. The body of the function just contains Python's **pass** |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
52 |
statement which means it does nothing, i.e. empty. We have our stub |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
53 |
ready. One important thing we need to keep in mind when we adopt TDD |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
54 |
methodology is that we need to have a clear set of results defined for |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
55 |
our code units. To put it more clearly, for every given set of inputs |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
56 |
as test case we must have, before hand, the exact outputs that are |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
57 |
expected for those input test cases. If we don't have that we have |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
58 |
failed in the first step of the TDD methodology itself. We must never |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
59 |
run looking for outputs for our test cases after we have the code |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
60 |
ready or even while writing tests. The expected outputs/behaviour must |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
61 |
be in our hands before we start writing tests. Therefore let us define |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
62 |
our test cases and the expected output for those inputs. Let one of |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
63 |
our test cases be 48 and 64 as *a* and *b* respectively. For this test |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
64 |
case we know that the GCD is 16. So that is the expected output. Let |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
65 |
our second test case be 44 and 19 as *a* and *b* respectively. We know |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
66 |
that their GCD is 1 by simple paper and pen calculation. |
89
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
67 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
68 |
Now we know what a test is? What are the ingredients required to write |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
69 |
tests? So what else should we wait for? Let us write our first test!:: |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
70 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
71 |
tc1 = gcd(48, 64) |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
72 |
if tc1 != 16: |
110
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
73 |
print "Test failed for the case a=48 and b=64. Expected 16. Obtained %d instead." % tc1 |
89
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
74 |
exit(1) |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
75 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
76 |
tc2 = gcd(44, 19) |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
77 |
if tc2 != 1: |
110
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
78 |
print "Test failed for the case a=44 and b=19. Expected 1. Obtained %d instead." % tc2 |
89
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
79 |
exit(1) |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
80 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
81 |
print "All tests passed!" |
109
0afd25eadf41
Add a section on real life tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
89
diff
changeset
|
82 |
|
110
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
83 |
Let us put all these in a file and call this file **gcd.py**:: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
84 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
85 |
def gcd(a, b): |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
86 |
pass |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
87 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
88 |
if __name__ == '__main__': |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
89 |
tc1 = gcd(48, 64) |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
90 |
if tc1 != 16: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
91 |
print "Test failed for the case a=48 and b=64. Expected 16. Obtained %d instead." % tc1 |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
92 |
exit(1) |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
93 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
94 |
tc2 = gcd(44, 19) |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
95 |
if tc2 != 1: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
96 |
print "Test failed for the case a=44 and b=19. Expected 1. Obtained %d instead." % tc2 |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
97 |
exit(1) |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
98 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
99 |
print "All tests passed!" |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
100 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
101 |
Note that we have introduced a new semantic which uses two new magic names |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
102 |
in Python *__name__* and *__main__*. This is a very common idiom used in |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
103 |
Python. Every Python code in a file can be run in two ways: Either as an |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
104 |
independent stand-alone script or as a Python module which can be imported |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
105 |
by other Python scripts or modules. When the idiom:: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
106 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
107 |
if __name__ == '__main__': |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
108 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
109 |
is used, the code within this if block is executed first when we run the |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
110 |
Python file as a stand-alone script. In other words, when we run this |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
111 |
python file as a stand-alone script the control of the program first starts |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
112 |
from the code that is within this if block from which the control is |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
113 |
transferred to other parts of the program or to other modules from |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
114 |
here. This comes as an extremely handy feature especially when we want to |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
115 |
test our modules individually. Now let us run our code as a stand-alone |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
116 |
script.:: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
117 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
118 |
madhu@madhu:~/Desktop$ python gcd.py |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
119 |
Traceback (most recent call last): |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
120 |
File "gcd.py", line 7, in <module> print "Test failed for the case a=48 and b=64. Expected 16. Obtained %d instead." % tc1 |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
121 |
TypeError: %d format: a number is required, not NoneType |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
122 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
123 |
Now we have our tests, the test cases and the code unit stub at |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
124 |
hand. We also have the failing test. So we know for sure that we have |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
125 |
cleared the first check point of TDD where the tests have failed. The |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
126 |
failing tests also give a green signal for us to go ahead to our next |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
127 |
check point i.e. to write the actual code in our code unit and make |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
128 |
the test pass. So let us write the code for the gcd function by |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
129 |
removing the **pass** control statement which had just created a gcd |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
130 |
function stub for us. |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
131 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
132 |
Most of us have learnt in high school math classes that the best and |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
133 |
the easiest known algorithm to compute the gcd of two numbers was |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
134 |
given to us 2300 years ago by a greek mathematician named Euclid. So |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
135 |
let us use the Euclid's algorithm to compute the gcd of two numbers a |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
136 |
and b:: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
137 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
138 |
def gcd(a, b): |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
139 |
if a == 0: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
140 |
return b |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
141 |
while b != 0: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
142 |
if a > b: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
143 |
a = a - b |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
144 |
else: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
145 |
b = b - a |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
146 |
return a |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
147 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
148 |
**Note**: If you are unaware of Euclidean algorithm to compute the gcd |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
149 |
of two numbers please refer to it on wikipedia. It has a very detailed |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
150 |
explanation of the algorithm and its proof of validity among other |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
151 |
things. |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
152 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
153 |
Now let us run our script which already has the tests written in it |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
154 |
and see what happens:: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
155 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
156 |
madhu@madhu:/media/python/sttp/tdd$ python gcd.py |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
157 |
All tests passed! |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
158 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
159 |
Success! We managed to pass all the tests. But wasn't that code simple |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
160 |
enough? Indeed it was. If you take a closer look at the code you will |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
161 |
soon realize that the chain of subtraction operations can be replaced |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
162 |
by a modulo operation i.e. taking remainders of the division between |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
163 |
the two numbers since they are equivalent operations. Also modulo |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
164 |
operation is far better than chain of subtractions because you will |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
165 |
reduce much faster using modulo operation than the subtraction. For |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
166 |
example if let us take 25, 5 as a and b in our example. If we write |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
167 |
down the steps of the algorithm written above we have the following: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
168 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
169 |
Step 1: a = 25 b = 5: Since both a and b are not 0 and b is greater |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
170 |
than a: b = 25 - 5 = 20 |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
171 |
Step 2: Since b is still not 0 and b is greater than a: b = 20 - 5 = |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
172 |
15 |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
173 |
Step 3: Since b is still not 0 and b is greater than a: b = 15 - 5 = |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
174 |
10 |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
175 |
Step 4: Since b is still not 0 and b is greater than a: b = 10 - 5 = 5 |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
176 |
Step 5: Since b is still not 0 and b is equal to a: b = 5 - 5 = 0 |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
177 |
Step 6: Since b is 0 the gcd is a = 5 which is returned |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
178 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
179 |
If we adopt the modulo operation instead of subtraction and follow the |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
180 |
steps: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
181 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
182 |
Step 1: a = 25 b = 5: Since both a and b are not 0 and b is greater |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
183 |
than a: b = 25 % 5 = 0 |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
184 |
Step 2: Since b is 0 the gcd is a = 5 which is returned |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
185 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
186 |
Wow! That was overwhelmingly lesser number of steps! So now we are |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
187 |
convinced that if we replace the subtraction operation with the modulo |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
188 |
operation our code performs much better. But if we think carefully we |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
189 |
know that the modulo of a and b is less than b irrespective of how |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
190 |
large the value of a is, including the case where a is already less |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
191 |
than b. So we can eliminate that extra conditional **if** statement by |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
192 |
just swapping the result of the modulo operation to the position of b |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
193 |
and b to the position of a. This ensures that a is always greater than |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
194 |
b and if not the swapping combined with modulo operation takes care of |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
195 |
it. To exemplify it, if a = 5 and b = 25 then by swapping and |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
196 |
performing modulo we have a = b = 25 and b = a % b = 5 % 25 = 5 and |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
197 |
hence we proceed. So let us replace our original code with this new |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
198 |
improved code we have come up with simple observations:: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
199 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
200 |
def gcd(a, b): |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
201 |
while b != 0: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
202 |
a, b = b, a % b |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
203 |
return a |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
204 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
205 |
Executing our script again we will see that all the tests pass. One |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
206 |
final improvement we can think of which is not necessary in terms of |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
207 |
efficiency but is certainly good to do keeping in mind the readability |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
208 |
is that we can use the concept of recursion for the same |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
209 |
algorithm. Without going into much detail this is how the code looks |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
210 |
if we use a recursive approach:: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
211 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
212 |
def gcd(a, b): |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
213 |
if b == 0: |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
214 |
return a |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
215 |
return gcd(b, a%b) |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
216 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
217 |
Much shorter and sweeter! And it passes all the tests! |
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
218 |
|
4e7b98636b58
Improved the initial Introduction on tests content.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
109
diff
changeset
|
219 |
|
109
0afd25eadf41
Add a section on real life tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
89
diff
changeset
|
220 |
More realistic "Tests" |
0afd25eadf41
Add a section on real life tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
89
diff
changeset
|
221 |
====================== |
0afd25eadf41
Add a section on real life tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
89
diff
changeset
|
222 |
|
112
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
223 |
|
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
224 |
Now we have successfully completed writing our first test, writing the |
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
225 |
relevant code and ensured the tests passed. We also refactored our |
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
226 |
code to perform better. With the knowledge of all these and some |
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
227 |
concepts and semantics like __main__ magic names we learnt we have |
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
228 |
come a long way with respect to writing tests. But our thirst is still |
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
229 |
unquenched! We want to do more and more tests! Not just write better |
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
230 |
code but also better tests! So let us keep building upon what we have |
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
231 |
learnt so far. |
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
232 |
|
115
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
233 |
Let us start writing tests for more realistic test cases. Generally |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
234 |
tests are predetermined as said above, if not the software design in |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
235 |
itself is flawed. The predetermined tests are stored along with the |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
236 |
test code in some persistent format like in a database, a text file, a |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
237 |
file of specific format like XML or in some other way. Let us continue |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
238 |
with our example of GCD function. We will keep all our test cases in a |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
239 |
text file, which is indeed persistent. Let us specify the format of |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
240 |
the test data in our file as follows. |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
241 |
|
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
242 |
1. The file has multiple lines of test data. |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
243 |
2. Each line in this file corresponds to a single test case. |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
244 |
3. Each line consists of three comma separated coloumns: |
112
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
245 |
|
115
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
246 |
i. First two coloumns are the integers for which the GCD has to |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
247 |
be computed |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
248 |
ii. Third coloumn is the expected GCD to the preceding two |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
249 |
numbers. |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
250 |
|
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
251 |
So how do we write our tests to use these test cases? Pretty simple, let |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
252 |
us review the machinery required first. |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
253 |
|
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
254 |
1. File reading: We already have learnt this in the modules on |
112
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
255 |
Basic Python. |
115
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
256 |
2. Parsing the read data from the file: This just involves a using a |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
257 |
**for** loop which iterates over the data line by line since we |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
258 |
know that the file contains each test case as a sepate line which |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
259 |
are equivalent to the file records and hence parse the data line |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
260 |
by line as strings as we iterate over it and convert it to the |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
261 |
required data type. |
112
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
262 |
|
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
263 |
Since we already have all the machinery required, let us proceed writing |
115
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
264 |
our test cases. We do not need not make any changes to the gcd |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
265 |
function so we will just write down the test here. Let us call our |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
266 |
data file gcd_testcases.dat:: |
112
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
267 |
|
115
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
268 |
if __name__ == '__main__': |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
269 |
for line in open('gcd_testcases.dat'): |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
270 |
values = line.split(', ') |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
271 |
a = int(values[0]) |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
272 |
b = int(values[1]) |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
273 |
g = int(values[2]) |
112
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
274 |
|
115
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
275 |
tc = gcd(a, b) |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
276 |
if tc != g: |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
277 |
print "Test failed for the case a=%d and b=%d. Expected %d. Obtained %d instead." % (a, b, g, tc) |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
278 |
exit(1) |
112
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
279 |
|
115
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
280 |
print "All tests passed!" |
112
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
281 |
|
115
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
282 |
When we execute the gcd.py script again we will notice that all the |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
283 |
tests passed. |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
284 |
|
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
285 |
Running at the **nose** |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
286 |
======================= |
112
0b01bb6ea6b8
Add a work-in progress section on writing realistic tests.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
110
diff
changeset
|
287 |
|
115
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
288 |
Not too far ahead we go we will start running at the nose saying of |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
289 |
Python developers saying that this is not sufficient to write |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
290 |
complicated tests in an efficient manner and writing tests for the |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
291 |
programs are so important that Python should provide a tool for |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
292 |
managing large tests. To further explain, the idea of placing the |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
293 |
tests with in the Python scripts and to execute them when the script |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
294 |
is run as a stand-alone script works well as long as we have our code |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
295 |
in a single Python file or as long as the tests for each script can be |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
296 |
run separately. But in a more realistic software development scenario, |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
297 |
often this is not the case. The code is spread around multiple Python |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
298 |
scripts, each script also called as a Python module, and also across |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
299 |
several Python packages. |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
300 |
|
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
301 |
In such a scenario what we would like to do is to create a separate |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
302 |
directory for holding these test. The structure of this directory is |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
303 |
the exact replica of the Python package hierarchy of our software to |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
304 |
be tested. This structure is especially useful because of the fact |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
305 |
that we have a one to one correspondence to our code and to its test. |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
306 |
Hence it is easy for us to navigate through the tests as we maintain |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
307 |
the existing tests and to add new tests as the code evolves. We have a |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
308 |
collection of tests in the specified structure. Any collection of |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
309 |
tests is called as the test suite for the *software package*. Hence we |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
310 |
shall call this directory of tests as our test suite. |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
311 |
|
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
312 |
Fine we have all these, but how do we make our tests aware that they |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
313 |
are the tests for such and such a Python module or code and when |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
314 |
executed must test that corresponding code? To make the lives of |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
315 |
Python developers and testers easy Python provides a very handy tool |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
316 |
called as **nose**. The name should have been pretty evident from the |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
317 |
heading of this section! So in the rest of this module let us discuss |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
318 |
how to use **nose** to write, maintain and extend our tests as the |
7455326cac40
Completed the section on realistic test scenarios and introductory paragraphs on nose.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
112
diff
changeset
|
319 |
code evolves. |