✅ 오늘 배운 것
어제 정리한 내용을 바탕으로 개발서버의 오류를 해결해보자. 현재 migration 관련해서 현재 브랜치와 테스트 서버의 버전이 일치하지가 않아서 모든 테스트에서 오류가 나는 상황이다. 하지만 이걸 일단 무시하고 테스트 코드를 개략적으로라도 작성해 보자.
# todos/views.py
class TodoView(APIView):
def post(self, request):
if serializer.is_valid(raise_exception=True):
serializer.save()
send_push_notification_device(
request.auth.get("device"),
request.user,
TODO_FCM_MESSAGE_TITLE,
TODO_FCM_MESSAGE_BODY,
)
return Response(
serializer.data, status=status.HTTP_201_CREATED
)
현재 뷰의 코드 일부분을 가져와봤다. 여기서 send_push_notification_device는 알람을 보내는 함수이다. 이 로직은 FE 서버에서 요청이 들어오면 해당되는 device_token의 값이 있기에 정상적으로 호출되지만, 테스트 환경에서 호출되면 별도의 디바이스에서 호출되는 것이 아니므로 오류가 나는 문제가 있었다.
지금부터 할 일은 기존의 테스트 로직을 수정하여 해당 함수를 우회하도록 작성해 주는 것이다.
우선 테스트에서는 django.urls의 reverse를 사용해서 이런 식으로 뷰의 이름을 통해 url을 가져온다. 여기서 url은 해당 뷰의 url이고, 'todos'는 해당 뷰를 unique하게 구분짓는 식별자로 볼 수 있다.
from django.urls import reverse
url = reverse("todos")
맨 처음에 작성해 볼 todo의 create API를 보자. 해당 뷰의 이름은 'todos'로 되어 있다. 그렇다면 위와 같은 코드로 해당 API의 url을 얻을 수 있겠다. 이제 pytest의 patch 기능을 이용해서, 해당 뷰 함수 안에서 호출되는 함수가 리턴하는 값을 mock 객체로 바꿔 주면 되겠다.
url = reverse('todos')
with('todos.firebase_messaging.send_push_notification_device', returned_value=None):
response = client.get(url)
그런데 이 방법을 사용하기에는 바꿔줘야 할 테스트의 개수가 너무 많았다. 사실 열개 즈음이라 한다면 할 수도 있는데, 만약 여기서 로직 하나가 또 추가되어서 또 patch를 써야 하면 그것도 10개씩 추가해줘야 하는 상황이라 이런 방법을 최대한 안 쓰고 싶었다.
그러니까 원하는 것은 'with patch'문을 일일이 선언하지 않아도 자동으로 특정 view를 호출할 때는 해당 뷰 안에 있는 특정 함수를 mock response 등으로 처리하는 거였다.
찾아보니 방법이 있었다. pytest에서 '모든' 무언가에 기본적인 설정을 부여하고 싶을 때는 conftest.py 파일을 건드려야 한다는 것은 알고 있었는데, 이 방법도 마찬가지였다.
# conftest.py
@pytest.fixture(autouse=True)
def patch_send_push_notification_device(monkeypatch):
monkeypatch.setattr('todos.firebase_messaging.send_push_notification_device', lambda: None)
이렇게만 추가해 주면, 앞으로 어떤 뷰나 로직에서든 중간에 해당 send_push_notification_device 함수가 호출되는 부분이 있다면 해당 부분은 건너뛰어지고 리턴 값은 None으로 변환된다고 이해했다.
다만 해당 fixture의 autouse 값이 참이기 때문에 만약 FCM 로직을 테스트하고 싶을 경우에는 수동으로 이를 disable 해 주어야 하겠다. 일단은 이대로 코드를 작성해 두었다.
✅ 궁금한 점
- mock 객체의 정확한 정의가 궁금하다.
- pytest의 patch 함수를 사용하면 로직이 어떻게 흘러갈까? 그리고 어떻게 해서 함수의 리턴값을 임의로 조작하는지도 궁금하다.
- pytest의 monkeypatch는 또 무엇일까?
'개발 일기장 > SWM Onestep' 카테고리의 다른 글
20241015 TIL: React Native에서 Django로 end-to-end test 작성하기 [진행중] (3) | 2024.10.15 |
---|---|
20241014 TIL: pytest에서 특정 함수 우회하기 [끝] (1) | 2024.10.14 |
20241011 TIL: 개발서버 오류 수정하기 [보류] (2) | 2024.10.11 |
20241010 TIL: 다국어 처리 지원하기 [끝] (0) | 2024.10.09 |
20241008 TIL: 다국어 처리 지원하기 [진행중] (1) | 2024.10.08 |