tdd/lab-workbook.rst
changeset 133 a9bb00e2073b
parent 130 e5d183dce985
equal deleted inserted replaced
132:24cec0337e81 133:a9bb00e2073b
       
     1 ======================================
       
     2 Lab Workbook - Test Driven Development
       
     3 ======================================
       
     4 
       
     5 The notation that follows every question denotes the level on the
       
     6 Revised Bloom's Taxonomy.
       
     7 
       
     8 Lab - 1
       
     9 =======
       
    10 
       
    11   1. Write a stub function for calculating the LCM of two numbers.
       
    12                                                             - U-level
       
    13   2. Write the tests for the LCM function, place the tests in if
       
    14      __name__ == '__main__': part of the Python file. Demonstrate that
       
    15      the tests fail.                                        - U-level
       
    16   3. Implement the code for the LCM function, using the gcd function
       
    17      provided in the examples in the chapter. Demonstrate the tests
       
    18      pass. (For the algorithm refer to Wikipedia - [0])     - Ap-level
       
    19   4. Alternatively, build a set of test cases, preferably a large
       
    20      number of cases, place it in a text file and use these test cases
       
    21      to test your LCM function. Demonstrate that tests still continue
       
    22      to pass.                                               - U-level
       
    23 
       
    24 [0] - http://en.wikipedia.org/wiki/Least_common_multiple#Reduction_by_the_greatest_common_divisor
       
    25 
       
    26 Lab - 2
       
    27 =======
       
    28 
       
    29   1. Write the stub function, followed by the tests(demonstrating the
       
    30      failed tests), in turn followed by the code(demonstrating the
       
    31      passing tests) to calculate the number of days between two
       
    32      dates. Name your function num_of_days(). The function should take
       
    33      two arguments, both being tuples. Each tuple represents the date
       
    34      in the format of (dd, mm, yyyy) where dd, mm and yyyy are
       
    35      integers.                                              - Ap-level
       
    36 
       
    37   2. Rewrite the num_of_days() function to take the start date as an
       
    38      optional argument. If the start date is not specified calculate
       
    39      the number of days between the only specified date since Unix
       
    40      epoch. Prior to manipulating the code to do this, make sure you
       
    41      change the tests, make them fail and then refactor the code.
       
    42                                                             - Ap-level
       
    43 
       
    44 
       
    45 Lab -3
       
    46 ======
       
    47 
       
    48   1. Move the tests that were written to GCD function in the examples
       
    49      of this chapter to a separate function called test_gcd(). Do the
       
    50      same for LCM function and num_of_days() function. Make sure when
       
    51      the respective Python files are executed as stand alone scripts
       
    52      these tests executed.                                  - U-level
       
    53   2. Put all these files in a single directory called utils and run
       
    54      the nosetests command. Make a report of the results.   - U-level
       
    55   3. Write doctests to each of the above functions. Demonstrate and
       
    56      report the results as executed by running the doctests using
       
    57      doctest.testmod() function and using nosetests command. -Ap-level
       
    58 
       
    59 Lab - 4
       
    60 =======
       
    61 
       
    62   1. Consider the following use case: We are given a large list of
       
    63      items called *data* where each item is a again a list with three
       
    64      values: username, which is a string; status of the user which
       
    65      can be one of the following three strings 'new', 'valid' or
       
    66      'invalid'; and the last login time which is a datetime Python
       
    67      object.  Write a function called **query** that takes a filter
       
    68      dictionary as a parameter and returns the result of the items in
       
    69      the *data* list. They keys of the dictionary can be 'user',
       
    70      'status' and 'logtime' and their corresponding values can be any
       
    71      of the valid values for the corresponding key. Example filter
       
    72      dictionary::
       
    73 
       
    74        filter = {
       
    75            'user': 'john'
       
    76            'status': 'new'
       
    77            }
       
    78 
       
    79      Place your function in a file called query.py. Before writing the
       
    80      actual function, follow the test driven development
       
    81      approach. First write a stub, fail the tests and then write the
       
    82      code and make sure the tests pass. Specifically use unittest
       
    83      framework to test this function. Place your tests in a file
       
    84      called test_query.py
       
    85 
       
    86      A developer wrote a small utility function in a file named
       
    87      user_utils.py which uses your **query** function which looks as
       
    88      follows::
       
    89 
       
    90        def login_util(user=None):
       
    91            """Takes a user name and returns his last login time if the
       
    92            user is a valid user, else return None. If the user is
       
    93            'host' it returns the last login time of all the users.
       
    94            """
       
    95 
       
    96            filter_dict = {
       
    97                'user': user
       
    98                'status': 'active'
       
    99                }
       
   100 
       
   101            if user == 'host':
       
   102                filter_dict['status'] + ['new', 'invalid']
       
   103 
       
   104            return query(filter_dict)
       
   105 
       
   106      Unfortunately the developer did not provide us with the test
       
   107      cases. We wrote the following test cases for you to only discover
       
   108      that the function miserably fails. 
       
   109 
       
   110      The tests were placed in a file called test_user_utils.py and we
       
   111      have used the unittest framework::
       
   112 
       
   113        import query
       
   114        import user_utils
       
   115        import unittest
       
   116 
       
   117        class TestUserUtils(unittest.TestCase):
       
   118         
       
   119            def setUp(self):
       
   120                """Boiler plate method to provide common data to all
       
   121                the test methods.
       
   122                """
       
   123                self.test_names = ['Alex', 'Guido', 'Thomas', 'host',
       
   124                    'Tom', 'James']
       
   125                self.data_len = len(query.data)
       
   126 
       
   127            def test_login_utils(self):
       
   128                """Tests for the login_utils function.
       
   129                """
       
   130 
       
   131                for name in self.test_names:
       
   132                    if name == 'host':
       
   133                        assertEqual(len(user_utils.login_utils(name)), self.data_len)
       
   134                    else:
       
   135                        assertLess(len(user_utils.login_utils(name)), self.data_len)
       
   136 
       
   137            def tearDown(self):
       
   138                """Boiler plate method to clean up all the data created
       
   139                for tests.
       
   140                """
       
   141 
       
   142                del self.test_names
       
   143                del self.data_len
       
   144 
       
   145      Fix the bug, run the tests to make sure the function passes the
       
   146      tests and if possible refactor the code with a better approach. - An-level