views.py 유닛테스트 Example

0

위코드 2차 프로젝트

목록 보기
11/13

클래스101 크리에이터 지원

1. 구현한 뷰

  1. 로직 : 크리에이터 지원에서 기본정보 입력(카테고리) 시 타이틀, 이미지를 제외한 내용이 입력될 수 있는 뷰를 구현

  2. 특이사항 : 데코레이터 사용으로 사용자 판별

  3. review : 반만 되는 반쪽짜리 코드 + 코드가 깔끔하지 못 함.

  • transaction의 사용 이유 알고 사용하기 : 연속적인 작업이 아닌 상황인데 트랜잭션 이용 않기

  • 데코레이터로 유저 가져와놓곤 따로 유저를 변수로 넣는 것은 불필요한 행위

  • 마찬가지로 PendingLecuture.~ 에서 User를 따로 부를 필요가 없었음

  • 로직 상 update가 쓰이려면 필터를 걸어주는 것이 맞음. 그리고 else 를 사용했어야 했다면 아래와 같이 사용하는 것이 맞음

    다음에는 get_or_create 를 연구해볼 것

  • 이미 있는 유저에 대해서는 update를 해줬으므로 integer error 를 없애주면 됨.

  1. 코드
import json, bcrypt, jwt, boto3, os, logging, uuid
from json import JSONDecodeError


from django.views import View
from django.http  import JsonResponse
from django.core.exceptions import ObjectDoesNotExist


from my_settings            import AWS_STORAGE_BUCKET_NAME
from creator.custom_storage import MediaStorage


from lecture.models import (
                            Category, SubCategory, Difficulty,
                            Hashtag, PendingLecture, PendingLectureHashtag,
                            Introduction, Vote)
from user.models    import User, Creator

from utils.decorators import auth_check


class BasicInformationView(View):
    @auth_check
    def post(self,request):
        try:
            data = json.loads(request.body)
            sub_category_id = data.get('sub_category_id')
            detailed_category = data.get('detailed_category')
            difficulty_id = data.get('difficulty_id')

            if not PendingLecture.objects.filter(user=request.user).exists():
                PendingLecture.objects.create(
                        sub_category_id = sub_category_id,
                        detailed_category = detailed_category,
                        difficulty_id = difficulty_id,
                        user_id = user
                    )
            else:
                PendingLecture.objects.filter(user=request.user).update(                                                
                        sub_category_id = sub_category_id,
                        detailed_category = detailed_category,
                        difficulty_id = difficulty_id,
                        user_id = user
                    )         
            return JsonResponse({'message' : 'SUCCESS'}, status=201)

        except KeyError:
            return JsonResponse({'message': 'KEY_ERROR'}, status=400)
        except JSONDecodeError:
            return JsonResponse({'message': 'JSON_DECODE_ERROR'}, status=400)
        except TypeError:
            return JsonResponse({'message': 'TYPE_ERROR'}, status=400)
        except ObjectDoesNotExist:
            return JsonResponse({'message' : 'USER_DOES_NOT_EXIST'}, status=400)

2. 구현한 test

참고 블로그
1. 필요했던 로직 : 제대로 구현되는지, 토큰이 없는 것을 거를 수 있는지, 들어오는 데이터 값이 없을 때 거를 수 있는지

  1. 특이사항 : 토큰 발행이 필요(auth_check)

  2. 코드

import json, jwt

from django.test import TransactionTestCase, Client

from unittest.mock import patch, MagicMock

from user.models    import User, Creator
from creator.views  import BasicInformationView
from lecture.models import (
                            Category, SubCategory, Difficulty,
                            Hashtag, PendingLecture, PendingLectureHashtag,
                            Introduction, Vote)

from my_settings import SECRET_KEY, HASHING_ALGORITHM

TEST_DATA = {
    "data" : {
    "sub_category_id" : "2",
    "detailed_category" : "손뜨개 코바늘",
    "difficulty" : "3"
    }
}


NONE_TEST_DATA = {
    "data" : {
    "sub_category_id" : None,
    "detailed_category" : None,
    "difficulty" : None
    }
}

# 필요한 테스트 자료 구현


class BasicInformationViewTest(TransactionTestCase):
    def setUp(self):
        User.objects.create(
            id = "1",
            username = "안다민",
            email = "damin0320@gmail.com",
            kakao_id = "1234567890"
        )
        
        self.token = jwt.encode({"username_id" : User.objects.get(id=1).id}, SECRET_KEY, algorithm=HASHING_ALGORITHM)
        
        # 필요한 토큰 발행 로직 구현
        
        PendingLecture.objects.create(
            title = "신나는 가죽공예",
            cover_image_url = "https://class2oo0k.s3.ap-northeast-2.amazonaws.com/media/misa.jpeg",
            summary_image_url = "https://class2oo0k.s3.ap-northeast-2.amazonaws.com/media/misa_note.jpeg",
        )
        
    def tearDown(self):
        User.objects.all().delete()
        PendingLecture.objects.all().delete()

    def test_basic_information_post_success(self):
        client = Client()
        header = {"HTTP_Authorization" : self.token}
        token = header["HTTP_Authorization"]
        payload = jwt.decode(token, SECRET_KEY, algorithms=HASHING_ALGORITHM)
        user = User.objects.get(id = payload["username_id"])
        response = client.post("/creator/basic-information", json.dumps(TEST_DATA), content_type="application/json", **header)
        self.assertEqual(response.status_code, 201)
        
        
    def test_basic_information_post_token_fail(self):
        client = Client()
        header = {"NO_Authorization" : "1234"}
        response = client.post("/creator/basic-information", json.dumps(TEST_DATA), content_type="application/json", **header)
        self.assertEqual(response.status_code, 400)
        
        
    def test_basic_information_post_none_fail(self):
        client = Client()
        header = {"HTTP_Authorization" : self.token}
        token = header["HTTP_Authorization"]
        payload = jwt.decode(token, SECRET_KEY, algorithms=HASHING_ALGORITHM)
        user = User.objects.get(id = payload["username_id"])
        response = client.post("/creator/basic-information", json.dumps(NONE_TEST_DATA), content_type="application/json", **header)
        print(response)
        self.assertIsNotNone(response.status_code, 400)
        
        # 이후 성공 / 실패 케이스 구현
  • 추가한 점 : update 된 유저에 대해서는? => id값을 추가한다
USER_TEST_DATA = {
    "data" : {
    "username_id" : "1",
    "sub_category_id" : "2",
    "detailed_category" : "손뜨개 코바늘",
    "difficulty" : "3"
    }
}

...

    def test_basic_information_post_update(self):
        client = Client()
        header = {"HTTP_Authorization" : self.token}
        token = header["HTTP_Authorization"]
        payload = jwt.decode(token, SECRET_KEY, algorithms=HASHING_ALGORITHM)
        user = User.objects.get(id = payload["username_id"])
        response = client.post("/creator/basic-information", json.dumps(USER_TEST_DATA), content_type="application/json", **header)
        self.assertEqual(response.status_code, 201)

3. 고민했던 것

  • 위와 같은 로직을 구현하는 과정 자체
  • 토큰을 부여해줘야 하는지 마는지?
  • 성공, 실패 케이스 구현을 어떻게 나누고 구분해야하는지?
  • assert~ 사용법에 대한 고민
  • 멘토님 추가 조언에 따른 코드 정정 때 update 한 유저에 대한 추가 테스트 + 테스트 하던 데이터 너무 글로벌하게 있어서 범용성 안따지려면 안에서 만들어도 됨
profile
커피 내리고 향 맡는거 좋아해요. 이것 저것 공부합니다.

0개의 댓글