author | Madhusudan.C.S <madhusudancs@gmail.com> |
Thu, 10 Jun 2010 18:51:22 +0530 | |
changeset 89 | 449760bc4089 |
child 109 | 0afd25eadf41 |
permissions | -rw-r--r-- |
89
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
1 |
Fundamentals |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
2 |
============ |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
3 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
4 |
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
|
5 |
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
|
6 |
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
|
7 |
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
|
8 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
9 |
Writing tests |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
10 |
============= |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
11 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
12 |
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
|
13 |
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
|
14 |
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
|
15 |
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
|
16 |
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
|
17 |
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
|
18 |
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
|
19 |
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
|
20 |
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
|
21 |
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
|
22 |
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
|
23 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
24 |
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
|
25 |
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
|
26 |
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
|
27 |
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
|
28 |
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
|
29 |
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
|
30 |
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
|
31 |
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
|
32 |
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
|
33 |
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
|
34 |
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
|
35 |
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
|
36 |
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
|
37 |
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
|
38 |
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
|
39 |
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
|
40 |
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
|
41 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
42 |
def gcd(a, b): |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
43 |
pass |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
44 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
45 |
This stub does nothing other than defining a new function called gcd which |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
46 |
takes two parameters a and b for which the GCD must be calculated. The body |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
47 |
of the function just contains pass which means it does nothing, i.e. empty. |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
48 |
We have our stub ready. One important thing we need to keep in mind when |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
49 |
we adopt TDD methodology is that we need to have a clear set of results |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
50 |
defined for our code units. To put it more clearly, for every given set of |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
51 |
inputs as test case we must have, before hand, the exact outputs that are |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
52 |
expected for those input test cases. If we don't have that we have failed |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
53 |
in the first step of the TDD methodology itself. We must never run for |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
54 |
outputs for our test cases after we have the code ready or even while |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
55 |
writing tests. The expected outputs/behaviour must be in our hands before |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
56 |
we start writing tests. Therefore let us define our test cases and the |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
57 |
expected output for those inputs. Let one of our test cases be 48 and 64 |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
58 |
as *a* and *b* respectively. For this test case we know that the GCD is |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
59 |
16. So that is the expected output. Let our second test case be 44 and |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
60 |
19 as *a* and *b* respectively. We know that their GCD is 1 by simple paper |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
61 |
and pen calculation. |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
62 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
63 |
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
|
64 |
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
|
65 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
66 |
tc1 = gcd(48, 64) |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
67 |
if tc1 != 16: |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
68 |
print "Test failed for the case a=48 and b=64. Expected 16. Obtained |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
69 |
%d instead." % tc1 |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
70 |
exit(1) |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
71 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
72 |
tc2 = gcd(44, 19) |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
73 |
if tc2 != 1: |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
74 |
print "Test failed for the case a=44 and b=19. Expected 1. Obtained |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
75 |
%d instead." % tc2 |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
76 |
exit(1) |
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
77 |
|
449760bc4089
Adding initial fundamentals and basic test content for TDD module.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff
changeset
|
78 |
print "All tests passed!" |