테스트 케이스를 사용하기 이전에만 해도 구현한 기능을 테스트 하기 위해 프론트를 작성해서 프론트에서 확인하거나, 포스트맨을 통해 설계한 API에 요청을 보내는 방법으로 기능을 테스트 할 수 있었다.
포스트맨을 처음 접했을 때도 엄청 간편하게 구현한 기능을 테스트 할 수 있었지만 테스트 케이스를 사용해서 테스트 코드를 사용하면 다른 외부 툴을 사용할 필요 없이 빠르게 여러 기능들을 테스트 할 수 있다.
from django.test import TestCase
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase
class UserRegistrationAPIViewTestCase(APITestCase):
def test_registration(self):
url = reverse('user_view')
user_data = {
"email": "test@gmail.com",
"password": "password"
}
response = self.client.post(url, user_data)
self.assertEqual(response.status_code, 201)
def test_login(self):
url = reverse('token_obtain_pair')
user_data = {
"email": "test@gmail.com",
"password": "password"
}
response = self.client.post(url, user_data)
self.assertEqual(response.status_code, 200)
위 코드는 회원가입과 로그인을 테스트 하는 코드이다.
우선 url 변수에 담은 reverse는 요청을 보낼 url의 name 값으로 해당 url을 가져올 수 있다.
다음 user_data는 요청을 보낼 data를 담아 둔 것이고, response에 self.client.post로 위에서 정의한 url과 user의 data를 같이 보내고, self.assertEqual로 post 요청 후 status code가 201인지 비교하여 테스트한다.
(self.client는 APITestCase에서 생성된 인스턴스이다.)
아래 로그인도 같은 코드이나 위에서 만든 user data로 access 토큰을 발급받는 것 외 차이가 없다.
하지만 이렇게 테스트를 실행했을 때 에러가 발생한다.
이유는 모든 테스트 코드는 서로 의존하지 않고, 독립적이여야 한다는 원칙이 존재하고, db에 저장된 object로 테스트를 하는 것이 아니며 위의 회원가입 테스트가 끝나는 순간 초기화가 되어버리기 때문에 로그인 테스트에서는 테스트할 user가 없는 것이다.
따라서 setUp 또는 setUpTestData를 사용해 테스트에 적용할 data를 생성하고 이어서 독립적인 테스트 코드를 작성하여 구현한 기능을 테스트 할 수 있다.
class ArticleCreateTest(APITestCase):
@classmethod
def setUpTestData(cls):
cls.user_data = {'email':'kim@gmail.com', 'password':'kimpassword'}
cls.article_data = {'title':'some title', 'content':'some content'}
cls.user = User.objects.create_user('kim@gmail.com', 'kimpassword')
def setUp(self): #client는
self.access_token = self.client.post(reverse('token_obtain_pair'), self.user_data).data['access']
아래 코드는 faker 패키지로 setUpTestData에 랜덤한 값의 유저를 생성하여 해당 유저로 글을 작성하고, 불러오는 테스트이다.
url에서 get_absolute_url()을 사용하게 되면 article object가 실행될 때 get_absolute_url 메소드가 실행되고, 생성되는 object의 pk 값을 kwargs에 넣어서 reverse의 url로 전달한 후 해당 path의 reverse 값을 tests.py의 url로 돌아온다.
그 다음 response로 get 요청을 하여 나온 결과를 serializer에 적용하여 json 형식의 data로 변환하고 serializer.item()을 사용해 반복문을 돌려 response의 key에 해당하는 value 값이 일치한지 한 번에
확인할 수 있다.
class ArticleReadTest(APITestCase):
@classmethod
def setUpTestData(cls):
cls.faker = Faker()
cls.articles = []
for i in range(10):
cls.user = User.objects.create_user(cls.faker.email(), cls.faker.word())
cls.articles.append(Article.objects.create(user=cls.user, title=cls.faker.sentence(), content=cls.faker.text()))
def test_get_article(self):
for article in self.articles:
url = article.get_absolute_url()
response = self.client.get(url)
serializer = serializers.ArticleSerializer(article).data
for key, value in serializer.items():
self.assertEqual(response.data[key], value)
models.py
class Somemodel(models.Model)
#some field...
def get_absolute_url(self):
return reverse("article_detail_view", kwargs={"article_id": self.id})