될때까지

((WnB)) 7일차 : 테스트 코드 작성 본문

프로젝트/wecode2차 : WnB

((WnB)) 7일차 : 테스트 코드 작성

랖니 2022. 8. 7. 22:59
728x90
  1. TestCase : unittest 프레임 워크의 테스트 조직의 기본 단위
  2. Fixture : 테스트를 진행할 때 필요한 테스트용 데이터 혹은 설정 등을 말한다. 주로 테스트가 실행되기전이나 후에 생긴다.
  3. assertion : unittest에서 테스트하는 부분이 제대로 됐는지를 확인한다.

 

Django에서 제공하는 테스트는 TestCase를 임포트해서 사용하고, 항상 TestCase객체를 상속받아 테스트 클래스를 생성해야한다.

from django.test import TestCase

테스트 코드 실행 명령어는 다음과 같다.

python manage.py test .

 

test는 각각의 함수를 직접 호출하는 게 아니고, Client()객체를 이용해서 우리가 설정한 엔드포인트 경로를 통해 함수를 호출해야한다.

테스트 케이스를 만들때는 항상 TestCase()객체를 상속받아 새로운 테스트 클래스를 생성한다.

내부에 작성하는 테스트 함수명은 test_로 시작해야지만 인식한다.

mock : 외부 API를 실제로 호출하는 뷰의 경우 mock(거짓된 값)을 이용한 테스트를 진행해야한다.(ex)카카오 소셜로그인)

 

카카오 회원가입/로그인뷰의 코드는 아래와 같다.

import requests
import jwt

from django.conf        import settings
from django.http        import JsonResponse
from django.views       import View

from users.models       import User

class KakaoOauthView(View):
    def get(self, request):
        token = request.META.get('HTTP_AUTHORIZATION')

        KAKAO_URL = 'https://kapi.kakao.com/v2/user/me'
        HEADER    = {'Authorization': token}
        
        user_info = requests.get(KAKAO_URL,headers=HEADER).json()
        
        kakao_id          = user_info['id']
        kakao_profile_img = user_info['kakao_account']['profile']['profile_image_url']
        email             = user_info['kakao_account']['email']
        
        user, created = User.objects.get_or_create(
            kakao_id = kakao_id
        ) 
        
        if created:
            user.kakao_profile_img = kakao_profile_img
            user.email             = email
            user.save()
            
            return JsonResponse({'message':'SIGNUP_SUCCESS'}, status=201)
        
        else:
            if user.kakao_profile_img != kakao_profile_img:
                user.kakao_profile_img = kakao_profile_img
                user.save()
                
            token = jwt.encode({'id':user.id}, settings.SECRET_KEY, settings.ALGORITHM)
            
            return JsonResponse({'message':'SIGNIN_SUCCESS', 'token':token}, status=200)

위 코드를 테스트하는 파일을 작성했다. 아직 완벽하게 이해는 안된다..

주말내내 테스트코드만 봤는데 봐도 봐도 어렵다. 그래도 일단 적용해보기..!!

import jwt

from django.test    import TestCase, Client
from unittest.mock  import patch, MagicMock

from users.models   import User
from django.conf    import settings

class KakaoOauthViewTest(TestCase):
    
    # 테스트할때는 id를 "꼭" 집어넣어야한다.
    # 테스트를 진행할 때 필요한 테스트용 데이터인 Fixture를 만든다.
    # 테스트케이스에서 쓸 데이터를 만든다.
    # 테스트끼리 서로 독립적으로 돌아야한다.
    def setUp(self):
        User.objects.create(
              id                = 1,
              email             = 'test@gmail.com',
              kakao_id          = 44444,
              kakao_profile_img = 'https://i.pinimg.com/564x/5c/a1/42/5ca142d34fd1903773b4f4e6f43d9045.jpg',
        )
        
    # 테스트가 끝나고 나면 생성한 데이터를 지운다.
    def tearDown(self):
        User.objects.all().delete()
    
    # 외부api에 요청을 보내주는 아이(requests)를 내가 만든 가짜 데이터(mock)로 붙이겠다.
    # users.views.requests가 쓰인 곳을 패치하겠다.(다른걸로 대체하겠다)
    @patch("users.views.requests")
    def test_success_kakao_signup(self, mocked_requests):
    	# 뷰를 테스트할 때 Client를 사용한다. (장고에서 제공)
        client = Client()
        
        # 카카오로 요청을 보냈을 때 받는 응답을 가짜로 써주기
        class MockedResponse:
            def json(self):
                return {
                    "id": 2022080735,
                    "connected_at": "2022-08-04T06:27:33Z",
                    "properties": {
                        "profile_image": "프로필이미지 url",
                        "thumbnail_image": "카카오 배경화면 이미지 url"
                    },
                    "kakao_account": {
                        "profile_image_needs_agreement": 'false',
                        "profile": {
                            "thumbnail_image_url": "카카오 thumb nail img",
                            "profile_image_url": "카카오 프로필 이미지",
                            "is_default_image": 'false'
                        },
                        "has_email": 'true',
                        "email_needs_agreement": 'false',
                        "is_email_valid": 'true',
                        "is_email_verified": 'true',
                        "email": "fake-email@test.com",
                        "has_birthday": 'true',
                        "birthday_needs_agreement": 'false',
                        "birthday": "0809",
                        "birthday_type": "SOLAR"
                    }
                }
            
        # mocked_requests.get의 결과로 MockedResponse()를 주겠다.
        mocked_requests.get = MagicMock(return_value = MockedResponse())
        headers = {'HTTP_Authorization' : '가짜 access_token'}
        # 요청을 가짜로 보내기
        response = client.get("/users/kakao/oauth", **headers)

        # 보냈을 때 응답의 상태코드와 메세지가 같다면 성공        
        self.assertEqual(response.status_code, 201)
        self.assertEqual(response.json().get('message'), 'SIGNUP_SUCCESS')
           
    @patch("users.views.requests")
    def test_success_kakao_signin(self, mocked_requests):
        client = Client()
        
        class MockedResponse:
            def json(self):
                return {
                    "id": 44444,
                    "connected_at": "2022-08-04T06:27:33Z",
                    "properties": {
                        "profile_image": "프로필이미지 url",
                        "thumbnail_image": "카카오 배경화면 이미지 url"
                    },
                    "kakao_account": {
                        "profile_image_needs_agreement": 'false',
                        "profile": {
                            "thumbnail_image_url": "카카오 thumb nail img",
                            "profile_image_url": "카카오 프로필 이미지",
                            "is_default_image": 'false'
                        },
                        "has_email": 'true',
                        "email_needs_agreement": 'false',
                        "is_email_valid": 'true',
                        "is_email_verified": 'true',
                        "email": "fake-email@test.com",
                        "has_birthday": 'true',
                        "birthday_needs_agreement": 'false',
                        "birthday": "0909",
                        "birthday_type": "SOLAR"
                    }
                }
                 
        mocked_requests.get = MagicMock(return_value = MockedResponse())
        headers = {'HTTP_Authorization' : '가짜 access_token'}
        # get함수에 대한 테스트니까 get으로 작성
        response = client.get("/users/kakao/oauth", **headers)
        
        # 반환되는 status_code랑 message를 비교해서 같다면 ok를 띄운다
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json(), {
            'message' : 'SIGNIN_SUCCESS',
            'token' : jwt.encode({'id':User.objects.latest('id').id}, settings.SECRET_KEY, settings.ALGORITHM)
        })

 

 

* 참고자료

https://velog.io/@combi_jihoon/Django-Test

728x90