This feature of Python makes me love programming again.

If you ask me about one thing that implementing it in C++ is for me tedious i would point “Mocking”. And still you need to do this a lot. (I hope I don’t need to explain how important is testing and how it involves mocking). There are some common well known ways to do that, but in Python it is so easy, that i could not believe 🙂 and I love it.

C++ mocking hell:

Lets discuss this topic in short from the C++ point of view. What are our options?

  1. Dependency injection. – Create interfaces for all stuff that you want to mock in test.
    Major issue of that is ending with a lot of “test purpose” interfaces, and you have a lot of abstract classes that allows you inject “mock” instead of “production code”. This interfaces are dead in production, and all of “polymorphism” also. I really do not recommend that, a specially on a level of detailed unit tests.
  2. Mocking by linking. – move all the stuff you want to mock into a separate library (or at least compilation unit), create library containing all the mocks, and link against it.
    A lot of effort for every unit test, don’t you think :-), well that is a C++ world. Major issue of that is, that you need additional interface for accessing a mock object, it need to be singleton, or at least static.
  3. Configure your build using “#ifdef” preprocesor statements … if any one of you are doing that for testing …. please stop.

Mocking in Python – easy peasy , but how it works ?

Python language it self is heavily Object Oriented Designed, everything is a object, including modules, classes it self and functions. Thanks to duck-typing or lack “type checking” you can override everything with everything. Here is a short example of mocking “without mocking framework”.

def duck_qwack():
    print("quack")
def hundred_ducks():
    for i in range(100):
        duck_qwack()
duck_call_counter = 0
def duck_mock():
    global duck_call_counter
    duck_call_counter += 1
duck_qwack = duck_mock
hundred_ducks()
print(duck_call_counter)

With pytest-mock is even easier:

def duck_qwack():
    print("quack")


def hundred_ducks():
    for i in range(100):
        duck_qwack()


def test_duck(mocker):
    duck_mock = mocker.patch("test_duck.duck_qwack")
    hundred_ducks()
    assert duck_mock.call_count == 100

Foot note:

This is only the small example of how different experience of programming can you get from learning different programming languages. In fact I am using python for years, but never used for big project … until now, and this is really refreshing.
With all of intergalactic greetings
Michał

Leave a comment