|
1 Fundamentals |
|
2 ============ |
|
3 |
|
4 Test Driven Development, abbreviated as TDD is a method of software |
|
5 development which banks on the idea of writing test cases that fail for the |
|
6 code that doesn't even exist yet. The actual code is written later to pass |
|
7 the test and then refactored. |
|
8 |
|
9 Writing tests |
|
10 ============= |
|
11 |
|
12 Writing a test is simple. Writing a failing test? It is much more simple. |
|
13 Let us consider a very simple program which returns the Greatest Common |
|
14 Divisor (GCD) of two numbers. Since the test cases for the code is written |
|
15 prior to the code itself, it is necessary to have a clear idea of the code |
|
16 units that our program will contain. Let us attempt to clearly define the |
|
17 code units in our case of a GCD program. Let our program contain one and |
|
18 only one function called gcd() which takes in two arguments as parameters. |
|
19 These arguments are the numbers for which GCD must be computed. The gcd() |
|
20 function returns a single value which is the GCD of the two arguments |
|
21 passed. So if we want to find out GCD of 44, 23, I will call my code unit |
|
22 as c = gcd(44, 23) where c will contain the GCD of those two numbers. |
|
23 |
|
24 Now we have defined our code units, how will we write tests? Before writing |
|
25 the test, a very fundamental question arises in our minds. How do tests |
|
26 look like? So let us answer this question first. Tests are nothing but a |
|
27 series of assertions which are either True or False depending on the |
|
28 expected behaviour of the code. We tell our tests whether our code unit |
|
29 asserts True or asserts False based on the expected behaviour of the code |
|
30 units. If we happen to run the tests now we are sure to get errors. Oh! But |
|
31 why? We don't even have the function gcd to call. The test code doesn't |
|
32 even compile! So what should we do now? So the idea is to first write the |
|
33 stubs for the code units before we start writing tests. This is necessary |
|
34 for two reasons. Firstly, by writing the stubs for the code units we will |
|
35 be able to correctly decide and fix on to the code units that we have |
|
36 planned to include in our program. We have a clear cut idea as to how our |
|
37 program is structured, how the tests must be written among other |
|
38 things. Secondly, the tests must at least compile and then fail! If the |
|
39 tests don't even compile, that doesn't mean the tests failed. It means |
|
40 it was a failure on the programmer's part. Let us define our stub:: |
|
41 |
|
42 def gcd(a, b): |
|
43 pass |
|
44 |
|
45 This stub does nothing other than defining a new function called gcd which |
|
46 takes two parameters a and b for which the GCD must be calculated. The body |
|
47 of the function just contains pass which means it does nothing, i.e. empty. |
|
48 We have our stub ready. One important thing we need to keep in mind when |
|
49 we adopt TDD methodology is that we need to have a clear set of results |
|
50 defined for our code units. To put it more clearly, for every given set of |
|
51 inputs as test case we must have, before hand, the exact outputs that are |
|
52 expected for those input test cases. If we don't have that we have failed |
|
53 in the first step of the TDD methodology itself. We must never run for |
|
54 outputs for our test cases after we have the code ready or even while |
|
55 writing tests. The expected outputs/behaviour must be in our hands before |
|
56 we start writing tests. Therefore let us define our test cases and the |
|
57 expected output for those inputs. Let one of our test cases be 48 and 64 |
|
58 as *a* and *b* respectively. For this test case we know that the GCD is |
|
59 16. So that is the expected output. Let our second test case be 44 and |
|
60 19 as *a* and *b* respectively. We know that their GCD is 1 by simple paper |
|
61 and pen calculation. |
|
62 |
|
63 Now we know what a test is? What are the ingredients required to write |
|
64 tests? So what else should we wait for? Let us write our first test!:: |
|
65 |
|
66 tc1 = gcd(48, 64) |
|
67 if tc1 != 16: |
|
68 print "Test failed for the case a=48 and b=64. Expected 16. Obtained |
|
69 %d instead." % tc1 |
|
70 exit(1) |
|
71 |
|
72 tc2 = gcd(44, 19) |
|
73 if tc2 != 1: |
|
74 print "Test failed for the case a=44 and b=19. Expected 1. Obtained |
|
75 %d instead." % tc2 |
|
76 exit(1) |
|
77 |
|
78 print "All tests passed!" |