테스트 코드 작성
TDD 책 뒷 부분도 보는 것이 좋다.
ft/tests_post.py
import random
from django.contrib.auth import get_user_model
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APILiveServerTestCase
from snippets.models import Snippet
User = get_user_model()
class SnippetTest(APILiveServerTestCase):
test_title = 'Test Snippet[{}] Title'
test_code = 'print("Hello, world{}")'
default_linenos = False
default_language = 'python'
default_style = 'friendly'
test_username = 'test_username'
test_password = 'test_password'
def create_user(self):
user = User.objects.create_user(
username=self.test_username,
password=self.test_password,
)
return user
def create_snippet(self, num=1):
"""
주어진 num 값 (기본값 1) 만큼의 snippet을 만든다.
num이 1일 경우 생성 후 response를 리턴한다.
:param num: 만들 Snippet 개수
:return: num이 1일 경우 생성 요청 후 response
"""
for i in range(num):
test_title = self.test_title.format(i + 1)
test_code = self.test_code.format('!' * (i + 1))
url = reverse('snippet:list')
data = {
'title': test_title,
'code': test_code,
}
response = self.client.post(url, data, format='json')
if num == 1:
return response
def test_snippet_list(self):
# Snippet 목록을 생성하기 전에 인증을 위해 유저를 생성하고 로그인
self.create_user()
self.client.login(username=self.test_username, password=self.test_password)
# 1~20개 중 랜덤하게 Snippet 생성
num = random.randrange(1, 20)
self.create_snippet(num)
# num 값과 일치하는 개수만큼 Snippet이 생성되었는지 확인
self.assertEqual(Snippet.objects.count(), num)
# values_list를 사용해서 필요한 항목만 가져올 경우
for index, snippet_value_tuple in enumerate(Snippet.objects.values_list('title', 'code')):
self.assertEqual(snippet_value_tuple[0], self.test_title.format(index + 1))
self.assertEqual(snippet_value_tuple[1], self.test_code.format('!' * (index + 1)))
# 쿼리가 매우 커서 일부만 사용할 경우
for index, snippet in enumerate(Snippet.objects.all().iterator()):
self.assertEqual(snippet.title, self.test_title.format(index + 1))
self.assertEqual(snippet.code, self.test_code.format('!' * (index + 1)))
def test_snippet_create(self):
# Create 이전에 인증을 위해 유저를 생성하고 로그인
self.create_user()
self.client.login(username=self.test_username, password=self.test_password)
# Snippet 생성 요청
response = self.create_snippet()
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data.get('title'), self.test_title.format(1))
self.assertEqual(response.data.get('code'), self.test_code.format('!'))
self.assertEqual(response.data.get('linenos'), self.default_linenos)
self.assertEqual(response.data.get('language'), self.default_language)
self.assertEqual(response.data.get('style'), self.default_style)
Tutorial 4: Authentication & Permissions
client.login(username='lauren', password='secret')
Postman 테스트
Authorization > Type: Basic Auth, Username, Password 입력 후 테스트 가능
주의 : 프로덕션 환경에서 BasicAuthentication을 사용하는 경우 https를 통해서만 API를 사용해야 한다. BasicAuthentication은 헤더의 authorization 내용을 가로챌 경우, 복호화가 가능하다.
Setting the authentication scheme
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
# BasicAuthentication을 지우면,
# Basic 인증을 사용하지 않게된다.
# 실제 배포할 때는 사용하지 않는 것이 좋다.
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
)
}
Tutorial 5: Relationships & Hyperlinked APIs
Adding pagination
Postman 테스트 > Params에 key = page, value = 2
를 넣어 요청해본다.
Tutorial 6: ViewSets & Routers
Viewsets
이라는 추상 클래스를 제공한다. (Vewset
을 사용할지 GenericView
를 사용할지는 선택사항이다.)
Refactoring to use ViewSets
ReadOnlyModelViewSet
을 이용하면 list
와 detail
기능을 한꺼번에 처리할 수 있다.
ModelViewSet
은 list
와 create
, retrieve
, update
, destroy
기능을 자동으로 지원한다. 여기에 highlight
기능을 추가해줘야 한다.
class SnippetViewSet(viewsets.ModelViewSet):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly,)
@detail_route(renderer_classes=[renderers.StaticHTMLRenderer])
def highlight(self, request, *args, **kwargs):
snippet = self.get_object()
return Response(snippet.highlighted)
Using Routers
ViewSet
은 URLname
도 자동으로 생성한다.DefaultRouter
는 최상위 뷰를 자동으로 생성한다.
과제
- 테스트 코드에러 수정
- DRF 튜토리얼 한번 더해보기