[PYTHON] Est-ce que ça va avec un tel patch? (Mémo sur le simulacre ~ Partie 2 ~)

Je ne suis pas bien. C'est un problème.

Lorsque j'ai utilisé le simulacre que j'ai écrit dans Article précédent, j'étais accro à environ 2 points.

Il est nécessaire de changer la cible du correctif en fonction de la méthode d'importation

Prenons le cas du test d'un module qui utilise une bibliothèque externe comme suit. (Dans l'exemple suivant, la bibliothèque http requêtes est utilisée comme bibliothèque externe. Certains points de la description suivante dépendent des requêtes. C'est le contenu qui a été fait.) Pour tester ce module seul, vous pouvez vous moquer des classes de la bibliothèque externe.

python:Module à tester(A.target.Que ce soit py)


from requests import Session

#Utilisez la classe Session quelque part
s = Session()

Ici, si vous écrivez comme suit, vous ne pouvez pas bien vous moquer de la bibliothèque externe.

Maquette de bibliothèque externe(Erreur)


import A

from mock import patch

# A.Se moquer de la classe Session utilisée dans la cible(Je vais)
with patch('requests.Session'):
	#tester

Le point est de savoir comment importer la bibliothèque externe dans le module sous test.

Si from requests import Session est spécifié, la classe Session sera placée sous l'espace du module où l'importation a été exécutée. Si le module testé est ʻA.target.py, ce sera ʻA.target.Session.

Le module testé utilise la classe Session (ʻA.target.Session`) importée sous lui, donc vous devez vous en moquer.

Maquette de bibliothèque externe(correct)


import A

from mock import patch

# A.Se moquer de la classe Session importée dans la cible
with patch('A.target.Session'):
	#tester

D'un autre côté, que faire si vous dites «demandes d'importation»?

Module à tester(Lorsque vous n'utilisez pas de)


import requests

#Utilisez la classe Session quelque part
s = requests.Session()

Cette fois, au lieu d'importer la classe Session sous mon contrôle, je spécifie requests.Session et le package de la bibliothèque externe. Par conséquent, la cible fictive est également «requests.Session» au lieu de «A.target.Session».

Maquette de bibliothèque externe(Lorsque vous n'utilisez pas de)


import A

from mock import patch

#Se moquer de la classe Session dans le package de requêtes
with patch('requests.Session'):
	#tester

Précautions lors de la moquerie des propriétés

Avec patch, l'attribut cible spécifié (méthode, etc.) est également automatiquement simulé. Dans ce cas, la classe Mock appelée MagicMock est utilisée par défaut.

Exemple de moquerie de l'attribut de la cible spécifiée


>>> import requests
>>> from mock import patch

# requests.La méthode de publication de la classe Session est simulée
>>> with patch('requests.Session'):
    s = requests.Session()
    print(s.post)
...
<MagicMock name='Session().post' id='4401343792'>

Considérez le cas où la simulation de réponse est définie comme la valeur de retour de la méthode post de la classe requests.Session qui est automatiquement simulée ci-dessus. Puisque la réponse de la méthode de publication a une propriété "texte", il est supposé que la même propriété (simulée) est définie dans la réponse fictive à créer.

Utilisez PropertyMock pour simuler des propriétés. Même si vous utilisez MagicMock, vous ne pouvez pas spécifier la valeur de retour de la propriété (= valeur de retour du getter).

Utilisez MagicMock pour les propriétés(Échec)


>>> import requests
>>> from mock import patch, MagicMock

>>> with patch('requests.Session'):
    s = requests.Session()
    response = MagicMock()
    # 'text'Propriétés simulées avec MagicMock(Essayez de)
    text = MagicMock()
    text.return_value = 'property'
    response.text = text
    s.post.return_value = response
    print(s.post().text)
...

# text.return_La valeur spécifiée pour value n'est pas renvoyée
<MagicMock name='Session().post().text' id='4506288536'>

Cependant, le simple remplacement de MagicMock par PropertyMock ne change pas le résultat.

Utilisez PropertyMock pour les propriétés(Échec)


>>> import requests
>>> from mock import patch, MagicMock, PropertyMock

>>> with patch('requests.Session'):
    s = requests.Session()
    response = MagicMock()
    #Utilisez PropertyMock au lieu de MagicMock
    text = PropertyMock()
    text.return_value = 'property'
    response.text = text
    s.post.return_value = response
    print(s.post().text)
...

#Ne fonctionne toujours pas...
<PropertyMock name='Session().post().text' id='4506377240'>

Il s'agit d'un problème qui se produit lorsque vous essayez de définir un PropertyMock pour une instance fictive (la réponse simulée dans l'exemple ci-dessus). Dans ce cas, vous devez définir PropertyMock sur l'objet type et non sur l'objet simulé lui-même.

Utilisez PropertyMock pour les propriétés(Succès)


>>> import requests
>>> from mock import patch, MagicMock, PropertyMock

>>> with patch('requests.Session'):
    s = requests.Session()
    response = MagicMock()
    text = PropertyMock()
    text.return_value = 'property'
    #Si vous définissez PropertyMock sur une autre maquette, définissez-la sur ce type d'objet, et non sur l'objet maquette lui-même.
    type(response).text = text
    s.post.return_value = response
    print(s.post().text)
...
property

J'ai beaucoup écrit jusqu'à présent

Les deux étaient correctement écrits dans le document ...

http://www.voidspace.org.uk/python/mock/patch.html#where-to-patch http://www.voidspace.org.uk/python/mock/mock.html?highlight=propertymock#mock.PropertyMock

Conclusion

Lisons le document correctement.

Recommended Posts

Est-ce que ça va avec un tel patch? (Mémo sur le simulacre ~ Partie 2 ~)
Mémo sur Sphinx Partie 1 (Création d'un projet)
Un mémo sur la création d'une application Django (Python) avec Docker
Un mémo lorsque le visage est détecté avec Python + OpenCV rapidement
Un mémorandum sur le simulacre de Python
Créez un thermomètre avec Raspberry Pi et rendez-le visible sur le navigateur Partie 4
Un mémo pour quand pip3 est installé avec python2.7 pour une raison quelconque
[Python] Qu'est-ce qu'une instruction with?
Jouez avec une tortue avec des graphiques de tortue (partie 1)
Une note sur mock (bibliothèque fictive Python)
Lorsque vous souhaitez l'utiliser tel quel lorsque vous l'utilisez avec lambda memo
En savoir plus sur COM (Component Object Model) en douceur Partie 2 Est-il vraiment indépendant du langage?