summaryrefslogtreecommitdiff
path: root/lecture_notes/test_driven_development/lab_workbook.rst
diff options
context:
space:
mode:
Diffstat (limited to 'lecture_notes/test_driven_development/lab_workbook.rst')
-rw-r--r--lecture_notes/test_driven_development/lab_workbook.rst146
1 files changed, 146 insertions, 0 deletions
diff --git a/lecture_notes/test_driven_development/lab_workbook.rst b/lecture_notes/test_driven_development/lab_workbook.rst
new file mode 100644
index 0000000..fa5afa4
--- /dev/null
+++ b/lecture_notes/test_driven_development/lab_workbook.rst
@@ -0,0 +1,146 @@
+======================================
+Lab Workbook - Test Driven Development
+======================================
+
+The notation that follows every question denotes the level on the
+Revised Bloom's Taxonomy.
+
+Lab - 1
+=======
+
+ 1. Write a stub function for calculating the LCM of two numbers.
+ - U-level
+ 2. Write the tests for the LCM function, place the tests in if
+ __name__ == '__main__': part of the Python file. Demonstrate that
+ the tests fail. - U-level
+ 3. Implement the code for the LCM function, using the gcd function
+ provided in the examples in the chapter. Demonstrate the tests
+ pass. (For the algorithm refer to Wikipedia - [0]) - Ap-level
+ 4. Alternatively, build a set of test cases, preferably a large
+ number of cases, place it in a text file and use these test cases
+ to test your LCM function. Demonstrate that tests still continue
+ to pass. - U-level
+
+[0] - http://en.wikipedia.org/wiki/Least_common_multiple#Reduction_by_the_greatest_common_divisor
+
+Lab - 2
+=======
+
+ 1. Write the stub function, followed by the tests(demonstrating the
+ failed tests), in turn followed by the code(demonstrating the
+ passing tests) to calculate the number of days between two
+ dates. Name your function num_of_days(). The function should take
+ two arguments, both being tuples. Each tuple represents the date
+ in the format of (dd, mm, yyyy) where dd, mm and yyyy are
+ integers. - Ap-level
+
+ 2. Rewrite the num_of_days() function to take the start date as an
+ optional argument. If the start date is not specified calculate
+ the number of days between the only specified date since Unix
+ epoch. Prior to manipulating the code to do this, make sure you
+ change the tests, make them fail and then refactor the code.
+ - Ap-level
+
+
+Lab -3
+======
+
+ 1. Move the tests that were written to GCD function in the examples
+ of this chapter to a separate function called test_gcd(). Do the
+ same for LCM function and num_of_days() function. Make sure when
+ the respective Python files are executed as stand alone scripts
+ these tests executed. - U-level
+ 2. Put all these files in a single directory called utils and run
+ the nosetests command. Make a report of the results. - U-level
+ 3. Write doctests to each of the above functions. Demonstrate and
+ report the results as executed by running the doctests using
+ doctest.testmod() function and using nosetests command. -Ap-level
+
+Lab - 4
+=======
+
+ 1. Consider the following use case: We are given a large list of
+ items called *data* where each item is a again a list with three
+ values: username, which is a string; status of the user which
+ can be one of the following three strings 'new', 'valid' or
+ 'invalid'; and the last login time which is a datetime Python
+ object. Write a function called **query** that takes a filter
+ dictionary as a parameter and returns the result of the items in
+ the *data* list. They keys of the dictionary can be 'user',
+ 'status' and 'logtime' and their corresponding values can be any
+ of the valid values for the corresponding key. Example filter
+ dictionary::
+
+ filter = {
+ 'user': 'john'
+ 'status': 'new'
+ }
+
+ Place your function in a file called query.py. Before writing the
+ actual function, follow the test driven development
+ approach. First write a stub, fail the tests and then write the
+ code and make sure the tests pass. Specifically use unittest
+ framework to test this function. Place your tests in a file
+ called test_query.py
+
+ A developer wrote a small utility function in a file named
+ user_utils.py which uses your **query** function which looks as
+ follows::
+
+ def login_util(user=None):
+ """Takes a user name and returns his last login time if the
+ user is a valid user, else return None. If the user is
+ 'host' it returns the last login time of all the users.
+ """
+
+ filter_dict = {
+ 'user': user
+ 'status': 'active'
+ }
+
+ if user == 'host':
+ filter_dict['status'] + ['new', 'invalid']
+
+ return query(filter_dict)
+
+ Unfortunately the developer did not provide us with the test
+ cases. We wrote the following test cases for you to only discover
+ that the function miserably fails.
+
+ The tests were placed in a file called test_user_utils.py and we
+ have used the unittest framework::
+
+ import query
+ import user_utils
+ import unittest
+
+ class TestUserUtils(unittest.TestCase):
+
+ def setUp(self):
+ """Boiler plate method to provide common data to all
+ the test methods.
+ """
+ self.test_names = ['Alex', 'Guido', 'Thomas', 'host',
+ 'Tom', 'James']
+ self.data_len = len(query.data)
+
+ def test_login_utils(self):
+ """Tests for the login_utils function.
+ """
+
+ for name in self.test_names:
+ if name == 'host':
+ assertEqual(len(user_utils.login_utils(name)), self.data_len)
+ else:
+ assertLess(len(user_utils.login_utils(name)), self.data_len)
+
+ def tearDown(self):
+ """Boiler plate method to clean up all the data created
+ for tests.
+ """
+
+ del self.test_names
+ del self.data_len
+
+ Fix the bug, run the tests to make sure the function passes the
+ tests and if possible refactor the code with a better approach. - An-level