Bonjour, c'est à peu près à cette époque que la protéine «goût de thé vert torréfié latte» d'une certaine protéine M ○ achetée en solde ne se boit pas à la soupe ** comme un goût de ** crevette (quoi
D'ailleurs, sur la base de la politique selon laquelle l'API de notre serveur Django ** couvre 120% dans le test **, nous écrivons le code de test environ deux fois plus que le code d'implémentation chaque jour. Dans de telles circonstances, aujourd'hui je présenterai brièvement "comment tester la fonction publique implémentée dans la classe Helper via l'API (et où elle s'est bloquée".
Les deux fonctions suivantes ont été implémentées (le nom de la fonction, etc. est factice pour la publication, et setting.py et urls.py sont déjà définis séparément)
app/views.py
from rest_framework.views import APIView
from app.helper import helper_foo
from app.models import HogehogeSerializer
class HogehogeListAPIView(APIView):
"""Implémenter la fonctionnalité de publication dans la vue API à l'aide du framework Django
"""
permission_classes = (permissions.IsAuthenticated,)
def post(self, request, format=None):
""" API Post/hogehoge
"""
serializer = HogehogeSerializer(data=request.data)
if serializer.is_valid(): #Vérification des données de demande
try:
with transaction.atomic():
serializer.save()
helper_foo(serializer.data) #Fonction d'assistance d'appel
except Exception as error:
return Response(status=status.HTTP_400_BAD_REQUEST)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
app/helper.py
import boto3
def helper_foo(data):
"""Fonction d'assistance
Créer un compartiment S3 basé sur les données
"""
client = boto3.client("s")
"""
Créer un bucket (lancer une erreur en cas d'échec)
"""
client.create_bucket(...
Et voici le contenu de pytest
app/tests.py
from django.test import TestCase
from django.conf import settings
from rest_framework.test import APIClient
class HogehogeAPITest(TestCase):
def setUp(self):
self.client = APIClient()
self.data = #Créer des données de test
def test_hogehoge_post(self):
response = self.client.post('/hogehoge',
self.data},
format='json')
self.assertEqual(response.status_code, 201)
#Vérifier avec diverses assertions
Le code qui crée réellement le S3Bucket est exécuté dans le test, et le S3Bucket supplémentaire augmente chaque fois que le test est exécuté.
Exécuté en pouvant simuler la fonction comme suit avec un patch dans le module Mock d'Unittest
La cible spécifie ʻapp.helper.foo_helper`.
app/tests.py
from unittest.mock import patch
from django.test import TestCase
from django.conf import settings
from rest_framework.test import APIClient
class HogehogeAPITest(TestCase):
def setUp(self):
self.client = APIClient()
@patch('app.helper.helper_foo')
def test_hogehoge_post(self, mock_function):
response = self.client.post('/hogehoge',
self.data},
format='json')
self.assertEqual(response.status_code, 201)
#Vérifier avec diverses assertions
self.assertEqual(mock_function.call_count, 1) #Vérifiez si la fonction Mock a été appelée une fois
Une fois exécuté, le résultat du test échoue et le message suivant s'affiche
self.assertEqual(mock_function.call_count, 1)
AssertionError: 0 != 1
Oh, la fonction n'est-elle pas moquée? En regardant la console AWS, S3Bucket est (malheureusement) bien fait.
Après avoir étudié diverses choses, la logique de référence de Patch est la suivante.
Maintenant, nous voulons tester some_function mais nous voulons simuler SomeClass en utilisant patch (). Le problème est que lorsque nous importons le module b, ce que nous devrons faire, alors il importe SomeClass du module a. Si nous utilisons patch () pour simuler out a.SomeClass alors cela n'aura aucun effet sur notre test; le module b a déjà une référence à la vraie SomeClass et il semble que notre patch n'a eu aucun effet. (Source 3 / library / unittest.mock.html # where-to-patch))
En d'autres termes Lorsque le module b est importé dans le module a, le module b est référencé à partir du module a, donc le référencer avec b.someclass (helper.helper_foo ici) n'affecte pas le test. Et cela
Donc, j'ai changé la cible de Mock de ʻapp.helper.foo_helper en ʻapp.views.foo_helper
.
app/tests.py
from unittest.mock import patch
from django.test import TestCase
from django.conf import settings
from rest_framework.test import APIClient
class HogehogeAPITest(TestCase):
def setUp(self):
self.client = APIClient()
@patch('app.views.helper_foo')
def test_hogehoge_post(self, mock_function):
response = self.client.post('/hogehoge',
self.data},
format='json')
self.assertEqual(response.status_code, 201)
#Vérifier avec diverses assertions
self.assertEqual(mock_function.call_count, 1) #Vérifiez si la fonction Mock a été appelée une fois
Cela a confirmé que le test fonctionnait et qu'aucun compartiment S3 n'avait été généré.
J'utilise Python depuis près de 10 ans, mais pour la première fois, j'ai pu comprendre le fonctionnement de la référence de module lors de l'importation.
c'est tout. Le code de test est intéressant dans les domaines où il y a diverses découvertes, j'espère donc que plus d'articles Pytest seront ajoutés à Qiita ces jours-ci.
Recommended Posts