Completed the section on realistic test scenarios and introductory paragraphs on nose.
authorMadhusudan.C.S <madhusudancs@gmail.com>
Tue, 31 Aug 2010 20:15:06 +0530
changeset 115 7455326cac40
parent 114 83b3e357ed08
child 116 958e2e9f2858
Completed the section on realistic test scenarios and introductory paragraphs on nose.
tdd/tdd.rst
--- a/tdd/tdd.rst	Tue Aug 31 20:14:18 2010 +0530
+++ b/tdd/tdd.rst	Tue Aug 31 20:15:06 2010 +0530
@@ -226,41 +226,90 @@
 code but also better tests! So let us keep building upon what we have
 learnt so far.
 
-Let us  start writing tests  for more realistic test  cases. Generally
-tests  are predetermined  as said  above, if  not the  code  itself is
-flawed. The predetermined tests are stored along with the test code in
-some  persistent way  like  in a  database,  a text  file,  a file  of
-specific format  like XML or  in other way.  Let us continue  with our
-example of  GCD function. We  will keep all  our test cases in  a text
-file,  which  is  indeed   persistent.  Let  our  file  have  multiple
-lines. Each line in this file  corresponds to a single test case. Each
-line consists of  three coloumns: first two coloumns  are the integers
-for  which the GCD  has to  be computed  and the  last coloumn  is the
-expected GCD  to the  preceding two  numbers. So how  do we  write our
-tests  to use  these  test cases?  Pretty  simple, let  us review  the
-machinery required first.
+Let us start writing tests for more realistic test cases. Generally
+tests are predetermined as said above, if not the software design in
+itself is flawed. The predetermined tests are stored along with the
+test code in some persistent format like in a database, a text file, a
+file of specific format like XML or in some other way. Let us continue
+with our example of GCD function. We will keep all our test cases in a
+text file, which is indeed persistent. Let us specify the format of
+the test data in our file as follows.
+
+  1. The file has multiple lines of test data.
+  2. Each line in this file corresponds to a single test case.
+  3. Each line consists of three comma separated coloumns:
 
-  1. File reading: We already have learnt this in our chapters on
+     i. First two coloumns are the integers for which the GCD has to
+        be computed
+     ii. Third coloumn is the expected GCD to the preceding two
+         numbers.
+
+So how do we write our tests to use these test cases? Pretty simple, let
+us review the machinery required first.
+
+  1. File reading: We already have learnt this in the modules on
      Basic Python.
-  2. Parsing read data from file: This just involves a for loop over
-     the data since we know that file contains lines which are
-     equivalent to file records and hence parse the data line by line
-     as strings as we iterate Over it and convert it to required data
-     type.
+  2. Parsing the read data from the file: This just involves a using a
+     **for** loop which iterates over the data line by line since we
+     know that the file contains each test case as a sepate line which
+     are equivalent to the file records and hence parse the data line
+     by line as strings as we iterate over it and convert it to the
+     required data type.
 
 Since we already have all the machinery required, let us proceed writing
-our test cases.
+our test cases. We do not need not make any changes to the gcd
+function so we will just write down the test here. Let us call our
+data file gcd_testcases.dat::
 
+  if __name__ == '__main__':
+      for line in open('gcd_testcases.dat'):
+          values = line.split(', ')
+          a = int(values[0])
+          b = int(values[1])
+          g = int(values[2])
 
+          tc = gcd(a, b)
+          if tc != g:
+              print "Test failed for the case a=%d and b=%d. Expected %d. Obtained %d instead." % (a, b, g, tc)
+              exit(1)
 
+      print "All tests passed!"
 
+When we execute the gcd.py script again we will notice that all the
+tests passed.
+
+Running at the **nose**
+=======================
 
-%%%%%%%%% Much Later %%%%%%%%%%%%%%%%%
-The idea of placing the tests with in the Python scripts and to
-execute them when the script is run as a stand-alone script works well
-as long as we have our code in a single Python file or the tests for
-each script can be run separately. But in a more realistic software
-development scenario, often this is not the case. The code is spread
-around multiple Python scripts, each Python script also being called
-as a Python module, and across several Python packages. In such a
-scenario we may want to do more.
+Not too far ahead we go we will start running at the nose saying of
+Python developers saying that this is not sufficient to write
+complicated tests in an efficient manner and writing tests for the
+programs are so important that Python should provide a tool for
+managing large tests. To further explain, the idea of placing the
+tests with in the Python scripts and to execute them when the script
+is run as a stand-alone script works well as long as we have our code
+in a single Python file or as long as the tests for each script can be
+run separately. But in a more realistic software development scenario,
+often this is not the case. The code is spread around multiple Python
+scripts, each script also called as a Python module, and also across
+several Python packages.
+
+In such a scenario what we would like to do is to create a separate
+directory for holding these test. The structure of this directory is
+the exact replica of the Python package hierarchy of our software to
+be tested. This structure is especially useful because of the fact
+that we have a one to one correspondence to our code and to its test.
+Hence it is easy for us to navigate through the tests as we maintain
+the existing tests and to add new tests as the code evolves. We have a
+collection of tests in the specified structure. Any collection of
+tests is called as the test suite for the *software package*. Hence we
+shall call this directory of tests as our test suite.
+
+Fine we have all these, but how do we make our tests aware that they
+are the tests for such and such a Python module or code and when
+executed must test that corresponding code? To make the lives of
+Python developers and testers easy Python provides a very handy tool
+called as **nose**. The name should have been pretty evident from the
+heading of this section! So in the rest of this module let us discuss
+how to use **nose** to write, maintain and extend our tests as the
+code evolves.