The principle of mocking - and the Python Mock package
Archive - Originally posted on "The Horse's Mouth" - 2015-10-17 09:27:28 - Graham EllisWhen I'm writing code, or updating existing code, I need to test it before I release it as generally available.
There are lots of tests I might want to perform, to ensure that all conditions are checked, and that all past bugs have been fixed and have not re-appeared. And indeed as I develop the application, it's a good idea starting off with working out what it should do. All this lot comes under the enormous subject of "unittesting", "Test Driven Development" and "Behaviour Driven Development". For not only do you want to write good and thorough tests, but you also want to be able to run the all consistently, efficiently (= automatically) and have a system in place for managing the results of the tests so you can get a very quick "yes, all is fine" or a much more detailed "you have the following problems" report. Keywords / key packages in this business include things like unit test in Python and Cucumber and Gherkin in Ruby - though those latter form part of a system that you can use to test (web sites) no matter what language they're written in.
But one of the problems you have when testing is - its just that - TESTING. You don't want database changes that would result from your tests to actually appear in the live databases, and you want to get consistent results from the system even if it calls up data which is distincly inconsistent over time. For example, I look after a web application which displays train cancellations across the South West and I need to test it ... without having to wait for a train to be cancelled to do so (99.5% of services run!)
So - at the front of the application I'll use something like unittest and at the back I'll use mock objects. A mock object / mock method is where I replace the production API (application / programmer interface) of my database or remote data access class with another method of the same name, but one which does something much simpler and different for testing purposes. As long as the call is consistent and the returned results work in the narrow circumstanced that I need, it'll all work nicely and sweetly for testing, and the same code can work later on the real databse / connection.
Recent versions of Python (from 3.3) include a unittest.Mock class which allows you to define mocks through a provided structure. Within mock objects / methods you can include coverage checking (to make sure that all your calls have been exercised), call logging, and patches for individual methods rather than total class replacement - for example, my database accessors could remain unaltereed except that commit calls got replaces internally by rollbacks - allowing data read of live data during testing, but no changes being made to the database.
I've written a tiny ("hello mocking world") demo [here] in which I have mocked out the random number generator in favour of returing a single known fixed value. The source code for my application:
import random
def value():
return random.randint(0,100)
for k in range(6):
print (value())
and when run, it might return something like:
WomanWithCat:flask grahamellis$ python3 mzz
47
99
46
17
33
89
WomanWithCat:flask grahamellis$
Add in a mock method to replace random.randint:
import sys
from unittest.mock import Mock
random.randint = Mock(return_value = 456)
and when I run that now, I get a consistent result:
WomanWithCat:flask grahamellis$ python3 mzz
456
456
456
456
456
456
WomanWithCat:flask grahamellis$
A very simple example, but it gets you started. You can now embed that code in your application, add testing on the front
The Mock library is documented [here]. There is a LOT more you can do ...