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?
- 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. - 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. - 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ł