The Co-op Life: Making Good Use Of The Python Mock Object Library

RedbrickJuly 15, 2016

For my third co-op term, I took on the role of Quality Assurance Analyst for Redbrick’s growing product team. This turned out to be an amazing opportunity to delve into software quality assurance on both a theoretical and practical level, and also help implement a brand new process at Redbrick.

So, where did I start? The first (and most important step) in developing a sound quality assurance process was to create the QA documents. This involved creating software test plans to document standards, practices, and conventions. It also meant identifying the most appropriate metrics for testing DeskMetrics features, and their Windows application functionality. The test plans also included templates to be filled out for keeping record of passed or failed tests, techniques to measure code coverage, and tools to complete the tests. The key with creating these was to keep in mind that the end goal was ultimately to automate a few tests, and produce a simple set of instructions for future use.

Next, I needed to write integration tests in Python for the DeskMetrics event ingestion pipeline. While I had written code in Python during my previous co-op, this was completely new to me (and where the ‘fake it ’til you make it part came in!). After a bit of research on writing test code in Python, I found the ‘unittest’ module was a good jumping off point.

One problem I ran into, right off the bat, was that the code to test had dependencies on external systems, such as RabbitMQ and a PostgreSQL database. I wanted to be able to write granular test code (essentially unit testing) without also testing the internal and external dependencies. That’s when I began to learn about the magical contents of the Python ‘unittest.mock’ library.

Using mock, I was able to create mocks (of stand-ins) for external dependencies that the code relies on. With mock, I found that I could set up all of the conditions to execute the code, replace some parts with a mock object, and then make assertions about the result and the mock object. Mock can make assertions about what methods were called to use the mock object and which arguments were called on the mock object. Mock also provides a ‘patch()’ decorator which can be used to patch modules within the scope of a test. The patch() decorator was very handy to me when writing the test code and I used it to patch the urllib3 library to avoid sending real api calls in the test code, and for patching the PostgreSQL server connection to avoid sending data to the database.

Another feature of the ‘unittest.mock’ library that I made use of was the MagicMock subclass. MagicMock puts objects back to the way it found them after a test has completed, which avoids state leakage between different tests. This also prevents other tests from mistakenly using something that was patched in a previous test. These three integration tests can be run with the ‘coverage run -m {test_code.py}’ command, which will list the amount of code coverage each test script has on the original code. After doing this, I automated these tests to run from a Jenkins job, and made sure that the coverage reports could be generated as a nice looking html file each time.

Let’s just say that the end result was very rewarding! Over just a few months as a Redbrick co-op, I had the opportunity to take ownership of the QA role, and even take some time to work with my fellow co-ops on an app to track the company’s weekly ping pong tournaments. Not a bad way to get a taste of the ‘real-world’ at Redbrick!


Redbrick is proud to be a supporter of the Co-operative Education Program at the University of Victoria. The “co-op” program enables students to alternate time in the classroom with paid work terms in their chosen field of study.