[기업협업] 퀀텀AI -Day 17-

제갈창민·2022년 1월 13일
0

기업협업[퀀텀AI]

목록 보기
11/18

형도 그랬단다 죽고 싶었지만 견뎌보니 괜찮더라

[ 노라조, "형" ]

D

되돌아 온 위코드 데이. 속절없이 날짜는 지나가고 그보다 시간은 더 빠르게 지나갔다. 진전이 없는 코드는 쌓여만 가는 페이지 방문 기록을 무색하게 만들고, 투자한 시간마저도 빛 바랜 기억의 편린으로 만들어 버렸다. 오늘로써 3일째, 출근도 안하는데 코드마저 발전이 없다면 내가 사장이라도 월급 주기 싫을 것 같기에, 닥치는대로 코드를 밀어 넣어 보기로 했다.

R

RequestFactory 모듈은 Django에서도 제공하는 TestCode 관련 지원 모듈이지만, 써본 적은 없었다. 사실상 TestCase 말고는 써보지 않았으니, 모르는게 더 많을 수 밖에. DRF에서는 대부분 Django에 존재하는 모듈에서 확장된 모듈을 제공하는데, TestCase => APITestCase, RequestFactory => APIRequestFactory, Client => APIClient 처럼 API가 다 붙어있다. 여하튼, 코드란 자고로 글만 읽어서는 알 수가 없다. 써보자, 일단.

F

(First)먼저, TestCase의 확장 모듈인 APITestCase부터 적용해 보았다.

tests.py

class TestSchool(APITestCase):
    def setUp(self):
        self.user = User.objects.create_user(username='testuser', password='password@123')
        self.token = Token.objects.get(user__username=self.user)
        self.client.credentials(HTTP_AUTHORIZATION='Token' + self.token.key)
        self.school = models.School.objects.create(school_name='서울대',(etc..))
        
    def test_school_create(self):
        data = {'school_name' : '서울대' }
        response = self.client.post(reverse('/school/', data))
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

setUp부터 난관 이었는데, 나의 model에는 존재하지 않는 UserToken은 어디서 가져오는지, credentials는 무엇이고, responsereverse는 또 무엇인지 쉽게 이해할 수 없었다. 해서, 오늘은 'User' 와 'Token', 그리고 'credentials'까지 이 세 가지부터 알아보려고 한다.

TIL

존재하지 않는 모델, 가짜User, Token 테이블

User

분명 models.py에는 이 두 가지 모델명은 존재하지 않는다. 그래서 위의 테스트를 그대로 실행시키게 되면,

AttributeError: Manager isn't available; 'auth.User' has been swapped for 'schools.School'

이런 에러를 만나게 된다. 회사의 기존 코드를 클론 받아서 이어나가고 있지만, 전체 코드를 살펴보지는 못했기에, 어디엔가 내가 모르는 설정이 되어 있는듯 했다.
auth.User를 찾아 헤맨 끝에, settings.py에서 auth.User를 사용하기 위해 설정해 주는 코드가 있다는 것을 알아냈고 찾아보았더니 역시나, 다음과 같은 설정이 되어있었다.

AUTH_USER_MODEL = 'schools.School'

이것을 'Custom user model'이라고 하고 이 경우에는 다음의 코드를 'setUp'에 추가로 작성해 주어야 한다.

from django.contrib.auth import get_user_model
User = get_user_model()

커스텀 된 유저 모델을 가져와서 적용해주는 모듈 'get_user_model'을 import 하고 'User' 를 변수로 지정해서 사용하려는 모델을 담아준다.
StackOverflow - 관련 답변

Token

'Token' 역시 테이블이 존재하지 않으며, 때문에 추가 설정을 필요로 한다.

from rest_framework_simplejwt.tokens import AccessToken

self.token = Token.objects.get(user__username=self.user)
(위의 코드를 아래의 코드로 바꿔줘야 한다.)
self.access = AccessToken.for_user(self.user)

현재 회사에서 'simplejwt'라는 모듈을 사용하고 있어서 적용하는 방법을 알아보았더니, 'AccessToken'을 임포트 하면 된다는 것을 알아냈다. 이렇게 하면 굳이 'Token' 가짜 테이블을 'auth.token'으로 설정해주지 않아도 알아서 테스트용 토큰이 생성되고 사용 할 수 있게 된다.

credentials

이 메소드에 대한 해답은 공식문서에 나와있다.

credentials 메소드는 테스트 클라이언트가 모든 후속 요청에 포함 할 헤더를 설정하는데 사용할 수 있습니다.

credentials를 다시 호출하면 기존 credentials을 덮어 씁니다.
인수없이 메서드를 호출하여 기존 credentials의 설정을 해제할 수 있습니다.
credentials 방법은 기본인증, OAuth1a과 OAuth2 인증 및 간단한 토큰 인증스키마와 같은 인증 헤더가 필요한 API를 테스트하는데 적합합니다.

<.force_authenticate(user=None, token=None)>
때로는 인증을 생략하고 테스트 클라이언트의 모든 요청을 인증 된 것으로 자동처리하도록 할 수 있습니다. 이는 API를 테스트하고 있지만 테스트 요청을 하기 위해 유효한 자격 증명을 작성하지 않으려는 경우 유용한 단축키입니다.

<사용예시>
user = User.objects.get(username='lauren')
client = APIClient()
client.force_authenticate(user=user)

후속 요청을 인증 해제하려면 force_authenticate를 호출하여 사용자/토큰을 None으로 설정하세요.
DRF 공식문서 번역본

즉, 테스트 실행 시, 후속으로 실행 될 모든 테스트 함수에 포함할 헤더를 설정하는 메소드이다. 인증을 통해 'Token'을 발급하면 인가된 API를 사용할 수 있는데, 이때 'Token'을 헤더에 담아서 매 API마다 로그인을 하지 않아도 되게 하는 것이 인증&인가의 기본 개념인것 처럼, credentials메소드가 자동으로 헤더에 'Token'을 담아 주는 것이다.
이제 실행이 가능하도록 정제된 'setUp' 코드를 보도록 하자.

class ProposeGoodShopTestCase(APITestCase):
    
    def setUp(self):
        User = get_user_model()
        self.user = User.objects.create_user(username='test', password='Password!')
        self.access = AccessToken.for_user(self.user)
        self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {self.access}')

이로써 APITestCase의 'setUp'이 설정 되었다.
내일은 1차로 완성된 테스트 코드를 살펴 보겠다.

살다보면 살아가다보면 웃고 떠들며 이 날을 넌 추억할테니

[ 노라조, "형" ]

profile
자기계발 중인 신입 개발자

0개의 댓글