Hello, is around this time that the "roasted green tea latte taste" protein of a certain M ○ Protein bought in sale not drink at soup ** like a taste of ** shrimp (what
By the way, based on the policy that the API of our Django server ** covers 120% in the test **, we write the test code about twice as much as the implementation code every day. Under such circumstances, today I will briefly introduce "how to test the Public function implemented in the Helper class via API (and where it got stuck".
The following two functions have been implemented (function names etc. are dummy for posting, and setting.py and urls.py are already set separately)
app/views.py
from rest_framework.views import APIView
from app.helper import helper_foo
from app.models import HogehogeSerializer
class HogehogeListAPIView(APIView):
"""Implement Post functionality in API View using Django framework
"""
permission_classes = (permissions.IsAuthenticated,)
def post(self, request, format=None):
""" API Post/hogehoge
"""
serializer = HogehogeSerializer(data=request.data)
if serializer.is_valid(): #Checking Request data
try:
with transaction.atomic():
serializer.save()
helper_foo(serializer.data) #Call a Helper function
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):
"""Helper function
Create an S3 Bucket based on the data
"""
client = boto3.client("s")
"""
Create a bucket (throw an error if it fails)
"""
client.create_bucket(...
And here is the content of 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 = #Create test data
def test_hogehoge_post(self):
response = self.client.post('/hogehoge',
self.data},
format='json')
self.assertEqual(response.status_code, 201)
#Check with various Asserts
The code that actually creates the S3Bucket is executed in the test, and every time the test is run, the extra S3Bucket increases.
Executed by being able to mock the function as follows with patch in the Mock module of Unittest
Target specifies ʻ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)
#Check with various Asserts
self.assertEqual(mock_function.call_count, 1) #Check if the Mock function has been called once
When executed, the test result fails and the following message is displayed
self.assertEqual(mock_function.call_count, 1)
AssertionError: 0 != 1
Oh, isn't the function Mocked? Looking at the AWS console, S3Bucket is (unfortunately) well done.
After investigating various things, it is said that the reference logic of Patch is as follows.
Now we want to test some_function but we want to mock out SomeClass using patch (). The problem is that when we import module b, which we will have to do then it imports SomeClass from module a. If we use patch () to mock out a.SomeClass then it will have no effect on our test; module b already has a reference to the real SomeClass and it looks like our patching had no effect. (Source 3 / library / unittest.mock.html # where-to-patch))
In other words When module b is imported into module a, module b is referenced from module a, so referencing it with b.someclass (helper.helper_foo here) does not affect the test. And that
So, I changed the target of Mock from ʻapp.helper.foo_helper to ʻ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)
#Check with various Asserts
self.assertEqual(mock_function.call_count, 1) #Check if the Mock function has been called once
This confirmed that the test worked and that no S3 bucket was generated.
I've been using Python for almost 10 years, but for the first time I was able to understand how Module reference works when importing.
that's all. Test code is interesting in fields where there are various discoveries, so I'm hoping that more Pytest articles will be added to Qiita these days.
Recommended Posts