돌파구가 보이지 않는 테스트 코드 정복은 목적지를 수정하여 우선적으로 status_code 와 Object 단위에 대한 테스트만 먼저 완성하기로 했다. 다시 말해, 실제 출력되는 값이 아닌, .count()
메소드를 사용해서 생성이 되는지만 테스트 하기로 한 것이다. 테스트를 해야하는 API는 즐비했고 사수님 포함 우리가 너무 많은 시간을 투자했기 때문에 이 이상은 낭비 할 수 없었다.
먼저 깔끔하게 Git 정리를 하고 최신 버전으로 pull 을 받은 후 각자가 구현한 다른 API로 넘어가서 테스트 코드를 적용했다.
이때 push & pull 하는 과정에서 remote origin & upstream
에 대한 궁금증이 생겨서 알아보았었다. 이에 관한 것은 다음 포스팅에서 다루기로 한다.
아래는 완성된 테스트 코드 전문이다.
class SchoolGradesTestCase(APITestCase):
def setUp(self):
User = get_user_model()
self.user = User.objects.create_user(username='test', password='Password!', is_staff=True)
self.access = AccessToken.for_user(self.user)
self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {self.access}')
self.serializer = GradesSerializer
school = School.objects.create(school_name='test')
Grade.objects.create(school_id=school.id, grade="1등급")
def test_schoolgrade_viewset(self):
data = {
"school_id": 1,
"grade" : "1등급"
"others": "texttexttext",
"school_info": [
{
"school_name": "test",
}
]
}
patch_data = {
"grade_id" : 1,
"grade" : "2등급"
}
response = self.client.get('/grade/')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(Grade.objects.count(), 1)
self.assertEqual(Grade.objects.get().school_name, 'test')
response = self.client.patch('/grade/1/', patch_data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
response = self.client.delete('/grade/1/', format='json')
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
response
부분을 살펴보면, ('url', '(입력 데이터)', '(데이터의 형식)') 과 같은 형태로 되어있다. 그리고 테스트에 사용하려는 요청 메소드(get, post, patch, delete)에 따라 이 형태도 바뀔 수 있다. get
의 경우에는 body
가 없고, list
의 형태로 데이터를 요청하고 출력하기 때문에 입력 데이터와 데이터의 형식을 넣지 않아도 된다. 여담으로 format
같은 경우는 settings.py
에서 default 값을 지정해두고 사용하는 것도 가능하다. 물론, setting 을 건드릴때는 항상 동료들과 상의 후 결정해야하는 것도 잊지 말아야 한다.
response = self.client.get('/grade/')
※ 전체 리스트를 불러오는 get 요청
response = self.client.patch('/grade/1/', patch_data, format='json')
※ patch_data 를 받아서 값을 수정하는 patch 요청
format
의 종류에는 multipart
와 json
두 가지를 Django 에서 기본적으로 지원한다. 특히나 factory
를 사용할 경우, multipart
형식이 디폴트 값이기 때문에 json
으로 작업하고자 한다면 따로 지정해주어야 한다.
이전 테스트와 이번 테스트간의 다른점은 정참조하는 테이블에서 데이터를 추가로 가져오는 로직이 포함된 API를 테스트 하는 것이다. Grade 라는 테이블은 School 을 정참조 하고 있고 Serializer 에서 school_name 을 추가로 가져오는 로직이 구현되어 있다.
school = School.objects.create(school_name='test')
Grade.objects.create(school_id=school.id, grade="1등급")
setUp 에서 Grade 테이블의 FK 값에 해당하는 school_id 가 필요하게 때문에 School의 Object 를 먼저 생성해주고, Grade Object 를 생성해준다.
self.assertEqual(Grade.objects.get().school_name, 'test')
추가로 포함된 school_name 을 제대로 가져왔다면 school_name 으로 필터링을 해도 Grade 가 출력되어야 하는 테스트를 진행한다.
여기까지 테스트 코드를 마무리하고 모든 코드를 싹 정리한 뒤 PR을 올렸다.