Qu’est-ce que le correctif (monkey -) en Python?
(monkey-) le patching est une technique permettant de modifier le comportement du code sans modifier sa source. Cela se fait lors de l’exécution, généralement en remplaçant les attributs des objets existants. Un objet peut être une instance, une classe ou même un module. La technique est le plus souvent (ab)utilisée pour les tests lorsque nous ne pouvons pas passer des moqueries de manière simple.
un autre exemple impressionnant est la bibliothèque gevent qui transforme le code synchrone en asynchrone en utilisant le patch de singe.,
comparons-le en utilisant wrk:
Gevent a fait des requêtes une bibliothèque coroutine-friendly et grâce à la concurrence, il a permis à notre exemple de serveur de gérer plus de 13,5 fois plus de requêtes par seconde.
en fin de compte, nous avons un programme qui a une concurrence basée sur coroutine (même principe que dans asyncio ou node.js) mais son code ressemble toujours à un code synchrone. Nous n’avons pas besoin de bibliothèques coopératives spéciales ou de mots clés asynchrones/await dans notre code. C’est presque de la magie.
Patch dans les tests
Python inclut un utilitaire pour patcher, c’est-à-dire unittest.moquer.patch., La façon par défaut de l’utiliser est de décorer notre fonction de test. Supposons que nous ayons une vue Django qui ressemble à ceci<
et nous aimerions la tester. Nous remarquons qu’il a une dépendance – ApiClient d’un autre module. Si nous voulons tester la vue get_stats de manière prévisible et fiable, nous devons utiliser un test-double au lieu D’ApiClient. Cependant, il n’y a pas de moyen simple de le faire. S’il était passé à get_stats comme argument, Nous pourrions simplement passer Mock à la place.,
1
2
3
4
|
def get_stats(demande, api_client_class):
… vous pouvez utiliser la fonction api_client = api_client_class ()
…,
|
…mais ce n’est pas le cas. Nous pouvons toujours utiliser patch decorator, cependant!
ce n’est pas encore terminé, mais si nous mettons un débogueur dans le test, nous remarquons que ApiClient.get_stats_for est maintenant un MagicMock:
cela signifie que notre moquerie a réussi. Nous avons remplacé une dépendance problématique par une maquette. Soit dit en passant, si vous recherchez les meilleures pratiques pour utiliser les moqueries, consultez mon guide (presque) définitif sur les moqueries en Python ou pourquoi se moquer peut être dangereux lorsqu’il est surutilisé.,
maintenant, le test échoue toujours car get_stats reçoit un MagicMock alors qu’il attend un dictionnaire. Nous devons paramétrer la maquette. Nous pouvons le faire en passant un deuxième argument à @patch:
Patch sans décorateur
patch peut également être utilisé comme gestionnaire de contexte. Un résultat de retour sera une simulation insérée à la place d’un attribut en cours de correction:
« le patch Python ne fonctionne pas!” – comment le faire?
parfois, vous serez confronté à la situation où, malgré la présence de patch decorator ou de context manager, la dépendance aura l’air de ne pas avoir été corrigée du tout., En bref, c’est peut-être parce qu’il existe plusieurs références existantes à la chose que vous essayez de patcher. Le code testé en utilise un, mais vous en avez corrigé un autre avec succès. L’opération a réussi, mais le patient est décédé. Que faire?
en bref, vous devez vous assurer de patcher la même référence que le code testé utilise.
Voir où Patcher section de unittest.documentation simulée pour plus de détails. Alternativement, vous pouvez utiliser une alternative astucieuse à patch, c’est patch.objet.
patch.object-plus simple pour bien faire les choses
patch.,l’objet est mort simple à utiliser – vous importez simplement l’objet dont vous souhaitez patcher et appliquer le patch.objet:
Si vous souhaitez utiliser patch.objet pour une méthode, vous importez une classe. Si vous voulez patch.objet une fonction ou une classe entière, importer le module dans lequel ils vivent.
devriez-vous Patcher?
(monkey-) les correctifs doivent être utilisés avec parcimonie. Qui devrait être votre dernier recours. Dans mon code, je n’ai pas d’autre option que le patch grâce à l’injection de dépendance.
à long terme, le prix de ces astuces est très, très élevé., Patcher signifie souvent toucher et modifier les détails de mise en œuvre d’une manière qui n’était pas prévue par les auteurs. Cela introduit un couplage supplémentaire avec des choses qui ne devraient pas l’avoir. Cela signifie qu’ils seront plus difficiles à changer.
Si vous le devez vraiment, corrigez uniquement L’API publique d’une autre bibliothèque ou d’un module dans votre code.
Laisser un commentaire