DRF는 장고 테스트 위에 API 요청을 편하게 보내는 APITestCase와 APIClient를 제공한다. 장고 테스트 러너(test runner)는 테스트용 DB를 따로 만들고, 각 테스트를 트랜잭션으로 감싸 끝나면 되돌리므로 실제 데이터를 건드리지 않는다.
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase
class ReviewTests(APITestCase):
def setUp(self):
self.user = User.objects.create_user("alice", password="pw-1234")
self.movie = Movie.objects.create(title="Dune")
def test_anonymous_cannot_create_review(self):
res = self.client.post(reverse("review-create", args=[self.movie.pk]), {"rating": 5})
self.assertEqual(res.status_code, status.HTTP_401_UNAUTHORIZED)
def test_author_can_create_review(self):
self.client.force_authenticate(user=self.user)
res = self.client.post(reverse("review-create", args=[self.movie.pk]), {"rating": 5}, format="json")
self.assertEqual(res.status_code, status.HTTP_201_CREATED)
self.assertEqual(Review.objects.get().author, self.user)작성 순서
- 파일·메서드 이름을
test로 시작한다(tests.py,test_*.py). 러너가 이 이름으로 찾는다 setUp이나 팩토리(test data factory)로 테스트 데이터를 만든다- URL은 하드코딩하지 말고
reverse()로 만든다 - 응답 상태 코드와 본문, 그리고 DB에 남은 결과까지 확인한다
인증이 필요한 요청
force_authenticate(user=...): 인증 과정을 건너뛰고 사용자를 지정한다. 권한 로직을 시험할 때 쓴다- 토큰 인증 자체를 시험하려면
self.client.credentials(HTTP_AUTHORIZATION="Token " + token.key)로 헤더를 넣는다(DRF 인증과 권한) - 401(인증 없음)과 403(권한 없음)을 나눠 확인하면 인증·권한 설정 실수를 잡기 좋다
무엇을 테스트할까
뷰 하나하나보다 "익명은 못 쓴다", "작성자만 고친다", "같은 사람이 리뷰를 두 번 못 쓴다" 같은 행동 단위로 이름을 붙인다. 이런 API 테스트는 테스트 피라미드의 중간층에 해당하고, 변경할 때 안전망이 된다(자가 테스트 코드). 불안정하거나 읽기 어려운 테스트의 징후는 테스트 냄새를 본다.
출처: DRF Testing: APIClient · Forcing authentication · credentials