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

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

기업협업[퀀텀AI]

목록 보기
12/18

내 두눈 밤이면 별이 되지, 나의 집은 뒷골목 달과 별이 뜨지요.

[ 체리필터, "낭만고양이" ]

D

더딘 작업속도에 점점 초조해져 갈 무렵, 사수님이 작업중이시던 기능 구현을 끝내고 합류하셨는데, 사수님도 DRF로 유닛 테스트를 만들어 본 적 없다고 하시면서 같이 공부하면서 만들어 보자고 하셨다. 또, 예제로 사용된 테스트 코드 샘플을 보여주시면서 이걸로 응용해 보자고도 하셨다.

class StreamPlatformTestCase(APITestCase):
    def setUp(self):
        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}')
    def test_stream(self):
        data = {
            'name' : 'tving',
            'about' : 'test',
            'website' : 'http://tving.co.kr'
        }
        response = self.client.post('/watch/stream/', data, format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        response = self.client.get('/watch/stream/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

이것은 Udemy 강의에서 사용된 학습자료를 바탕으로 만들어진 유닛 테스트인데, 'setUp'의 모양새는 내가 만든 것과 같았지만, response부분이 달랐다.

    def test_school_create(self):
        data = {
        'school_name' : '서울대' 
        }
        response = self.client.post(reverse('/school/', data))
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

R

reverse 는 Django 에서도 사용이 가능한데, 그 역할은 다음과 같다.

  • 장고는 urls.py 변경을 통해 ‘각 뷰에 대한’ url이 변경되는 유연한 시스템을 갖고 있다.
  • url이 변경 되더라도 url reverse가 변경된 url을 추적한다. (누락의 위험이 적다)

초보몽키님의 블로그
그래서 DRF공식문서 예시에 나온 것처럼 url 과 basename을 사용해보았지만, 어째선지 자꾸만 에러가 났다. 이것 때문에 거진 하루를 소비했지만, 결국 방법은 알아내지 못했고 한숨만 쉬던 중 사수님이 주신 예제로 바꾸어보았더니, 바로 통과가 되었다.

class SchoolTestCase(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}')

    def test_school_viewset(self):
        data ={
            'school_name' : 'test',
        }

        response = self.client.post('/school/', data, format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

F

Fail 이 뜨지 않는게 오히려 불안하다는 말을 들은 적이 있는데, 당시에는 개발자 전용 개그인줄로만 알았다. 그런데 단박에 OK가 뜨자, 묘한 위화감이 들면서 '과연 이게 정말 맞는 테스트 코드여서 OK가 뜬 걸까?' 하는 의문이 자리잡았다. 하지만 일주일이 거의 다 지나가고 있었고, 다른 API에 대한 테스트도 작성해야 했기에, 의문은 잠시 접어두고 기본적인 CRUD에 대한 테스트를 완성했다.

class SchoolTestCase(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}')

    def test_school_viewset(self):
        data ={
            'school_name' : 'test',
        }
        
        patch_data = {
            'school_name' : 'TESTname'
        }

        response = self.client.post('/school/', data, format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(School.objects.count(), 1)
        self.assertEqual(School.objects.get().school_name, 'test')
        
        response = self.client.get('/school/', data, format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        response = self.client.patch('/school/', patch_data, format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        
        response = self.client.delete('/school/', format='json')
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)

드디어. 일주일을 통으로 갈아넣으면서 테스트 코드 한 토막을 완성했다(일단은 그렇게 보였다). post부분에 두 줄을 추가한 이유는 create가 제대로 적용되었다면, 1개의 데이터가 카운팅 될 것이고, name이 'test'인 데이터여야 할 것이기에 검증 차원에서 추가해보았다. 테스트 결과도 모두 통과가 되었고, 사수님도 OK사인을 보내셨다. 이제 남은 것은 추가 된 기능에 대한 테스트 인데, '검색'과 serializer에서 추가로 찾은 결과값에 대한 테스트가 필요했다. 과연 내일안에 성공할 수 있을지.

TIL

가정 설정문, assert 함수

reverse에 대해 찾아보다가 우연찮게 assert 함수에 대해 알게 되었다. 파이썬 함수인 assertassertEqual처럼 메소드 형식으로 사용하는 경우도 있지만, 특정한 의미로써 assert 만으로도 사용하기도 한다. 이에 대해서 다음과 같은 설명이 있다.

예외를 발생시키는 예외처리랑 비슷하지만, 예외처리는 에러가 발생했을때 어떤 처리를 하기위한 코드이고, 이 assert (가정 설정문)은 어떤 조건이 True임을 보증하기 위해서 사용하는 것 입니다.

오류를 발생시키는 raise와 비슷하지만 다릅니다. raise에 대한 자세한 설명이 필요하다면 [바로가기]

raise는 만약에 오류가 발생했을때 "except 와 함께 이렇게 처리해라" 는 뜻이고

assert는 이 조건이 참일때 코드는 내가 보장한다. 이 조건은 올바르다!
하지만 이 조건이 거짓이라는 것은 내가 보증하지 않은 동작이다. 그러니 AssertionError를 발생해라.

이런 식의 흐름입니다.
출처: [개발자 지망생]

참초한 블로그에 예시들도 자세히 나와있으므로 참고하면 좋을 듯 하다.

추가로 유닛 테스트에서 자주 사용되는 8가지 정도의 assert-- 함수 종류에 대해서도 간략히 알아보자.

  • assertEqual()
    assertEqual(결과 값, 기대한 값)
    실제 데이터 값과 기대한 값이 동일한지 확인합니다.
    결과 값과 기대한 값이 같다면 (결과 값 == 기대한 값) Pass 입니다.

  • assertNotEqual()
    assertNotEqual(결과 값, 기대한 값)
    실제 데이터 값과 기대한 값이 다른지 확인합니다.
    결과 값과 기대한 값이 다르다면 (결과 값 != 기대한 값) Pass 입니다.

  • assertTrue()
    assertTrue(결과 값)
    결과 값이 True인지 확인합니다.
    결과 값이 True라면 Pass 입니다.

  • assertFalse()
    assertFalse(결과 값)
    결과 값이 False인지 확인합니다.
    결과 값이 False라면 Pass 입니다.

  • assertGreater()
    assertGreater(결과 값, 기대한 값)
    결과 값이 기대한 값보다 큰지 확인합니다.
    결과 값이 기대한 값보다 크다면 (결과 값 > 기대한 값) Pass 입니다.

  • assertGreaterEqual()
    assertGreaterEqual(결과 값, 기대한 값)
    결과 값이 기대한 값보다 크거나 같은지 확인합니다.
    결과 값이 기대한 값보다 크거나 같다면 (결과 값 >= 기대한 값) Pass 입니다.

  • assertLess()
    assertLess(결과 값, 기대한 값)
    결과 값이 기대한 값보다 작은지를 확인합니다.
    결과 값이 기대한 값보다 작다면 (결과 값 < 기대한 값) Pass 입니다.

  • assertLessEqual()
    assertLessEqual(결과 값, 기대한 값)
    결과 값이 기대한 값보다 작거나 같은지를 확인합니다.
    결과 값이 기대한 갑보다 작거나 같다면 (결과 값 <= 기대한 값) Pass 입니다

  • assertIn()
    assertIn(찾으려는 문장, 전체 문장)
    전체 문장에서 내가 찾으려는 문장이 들어 포함되었는지 확인합니다.
    전체 문장에서 내가 찾으려는 문장이 있다면 Pass 입니다.

  • assertNotIn()
    assertNotIn(찾으려는 문장, 전체 문장)
    전체 문장에서 내가 찾으려는 문장이 들어 포함되지 않았는지 확인합니다.
    전체 문장에서 내가 찾으려는 문장이 없다면 Pass 입니다.

출처: 자주 사용되는 assert 함수 정리

이젠 바다로 떠날 거예요, 거미로 그물 쳐서 물고기 잡으러

[ 체리필터, "낭만고양이" ]

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

0개의 댓글