miercuri, 20 mai 2009

Python mocking __new__

In acest tutorial voi prezenta o facilitate python extrem de interesanta: inlocuirea metodei speciale __new__. Acest lucru mi-a fost util in momentul in care am scris o suita de teste pentru o clasa. Problema era ca aceasta clasa era Singleton si in concluzie era dificil sa ma asigur ca resursele injectate sunt corecte de la un test la altul. Solutia de compromis a fost sa elimin comportamentul Singleton al clasei doar pentru teste.

In this tutorial I will show you an unsual feature of python: replacing special method __new__. This seemed extremely useful to me in the moment I wrote some unit tests for a class. Adding the fact the class was a Singleton makes the problem even more interesting. It was difficult for me, to make sure every test was injecting the correct resources. The solution I came up with was to eliminate the "singleton" behavior just for tests.

class TestedClass(float):
def mockedNew(cls, *args, **kwds):
print("Mocked new")
self = float.__new__(*args, **kwds)
return self

def deleteNew(cls):
cls.__new__ = cls.mockedNew

def __new__(cls, arg=0.0):
print("Normal new")
return float.__new__(cls, arg*0.0254)

def __init__(self, arg=0.0):
print("Not working")

deleteNew = classmethod(deleteNew)
mockedNew = classmethod(mockedNew)

if __name__ == "__main__":
TestedClass.deleteNew()
print(TestedClass(12))

In mod normal, in exemplul de mai sus, daca nu as apela deleteNew rezultatul ar fi:
Usually, if I don't invoke deleteNew the result would be:
  • Normal new
  • Not working
  • 0.3048
Calling deleteNew changes the result to:
  • Mocked new
  • Not working
  • 12
In this manner I managed to change __new__ method behavior dynamically.

Niciun comentariu:

Trimiteți un comentariu