In this section, we will take you through a journey in which we will show you how TDD is done using stubs, and how Docker can come handy in developing software in the deployment equivalent system. For this purpose, we take a web application use case that has a feature to track the visit count of each of its users. For this
example, we use Python as the implementation language and redis as the key-value pair database to store the users hit count. Besides, to showcase the testing capability of Docker, we limit our implementation to just two functions: hit and getHit.
NOTE: All the examples in this chapter use python3 as the runtime environment. The ubuntu 14.04 installation comes with python3 by default. If you don't have python3 installed on your system, refer to the respective manual to install python3.
As per the TDD practice, we start by adding unit test cases for the hit and getHit functionalities, as depicted in the following code snippet. Here, the test file is named test_hitcount.py:
import unittest import hitcount
class HitCountTest (unittest.TestCase):
def testOneHit(self):
# increase the hit count for user user1 hitcount.hit("user1")
# ensure that the hit count for user1 is just 1 self.assertEqual(b'1', hitcount.getHit("user1"))
if __name__ == '__main__':
unittest.main()
This example is also available at https://github.com/thedocker/
testing/tree/master/src.
Here, in the first line, we are importing the unittest Python module that provides the necessary framework and functionality to run the unit test and
generate a detailed report on the test execution. In the second line, we are importing the hitcount Python module, where we are going to implement the hit count functionality. Then, we will continue to add the test code that would test the hitcount module's functionality.
Now, run the test suite using the unit test framework of Python, as follows:
$ python3 -m unittest
The following is the output generated by the unit test framework:
E
======================================================================
ERROR: test_hitcount (unittest.loader.ModuleImportFailure)
---Traceback (most recent call last):
...OUTPUT TRUNCATED ...
ImportError: No module named 'hitcount'
---Ran 1 test in 0.001s
FAILED (errors=1)
As expected, the test failed with the error message ImportError: No module named 'hitcount' because we had not even created the file and hence, it could not import the hitcount module.
Now, create a file with the name hitcount.py in the same directory as test_hitcount.py:
$ touch hitcount.py
Continue to run the unit test suite:
$ python3 -m unittest
The following is the output generated by the unit test framework:
E
======================================================================
ERROR: testOneHit (test_hitcount.HitCountTest)
---Traceback (most recent call last):
File "/home/user/test_hitcount.py", line 10, in testOneHit hitcount.hit("peter")
AttributeError: 'module' object has no attribute 'hit'
---Ran 1 test in 0.001s
FAILED (errors=1)
Again the test suite failed like the earlier but with a different error message AttributeError: 'module' object has no attribute 'hit'. We are getting this error because we have not implemented the hit function yet.
Let's proceed to implement the hit and getHit functions in hitcount.py, as shown here:
import redis
# connect to redis server
r = redis.StrictRedis(host='0.0.0.0', port=6379, db=0)
# increase the hit count for the usr def hit(usr):
r.incr(usr)
# get the hit count for the usr def getHit(usr):
return (r.get(usr))
This example is also available on GitHub at https://github.
com/thedocker/testing/tree/master/src.
Note: To continue with this example, you must have the python3 compatible version of package installer (pip3).
The following command is used to install pip3:
$ wget -qO- https://bootstrap.pypa.io/get-pip.py | sudo python3
-In the first line of this program, we are importing the redis driver, which is the connectivity driver of the redis database. In the following line, we are connecting to the redis database, and then we will continue to implement the hit and getHit function.
The redis driver is an optional Python module, so let's proceed to install the redis driver using the pip installer, which is illustrated as follows:
$ sudo pip3 install redis
Our unittest will still fail even after installing the redis driver because we are not running a redis database server yet. So, we can either run a redis database server to successfully complete our unit testing or take the traditional TDD approach of mocking the redis driver. Mocking is a testing approach wherein complex behavior is substituted by predefined or simulated behavior. In our example, to mock the redis driver, we are going to leverage a third-party Python package called mockredis. This mock package is available at https://github.com/locationlabs/mockredis and the pip installer name is mockredispy. Let's install this mock using the pip installer:
$ sudo pip3 install mockredispy
Having installed mockredispy, the redis mock, let's refactor our test code test_hitcount.py (which we had written earlier) to use the simulated redis functionality provided by the mockredis module. This is accomplished by the patch method provided by the unittest.mock mocking framework, as shown in the following code: self.assertEqual(b'1', hitcount.getHit("user1"))
if __name__ == '__main__':
unittest.main()
This example is also available on GitHub at https://github.com/
thedocker/testing/tree/master/src.
Now, run the test suite again:
$ python3 -m unittest .
---
-Ran 1 test in 0.000s
OK
Finally, as we can see in the preceding output, we successfully implemented our visitors count functionality through the test, code, and refactor cycle.