지금까지 API 테스트는 Postman을 통해 진행했었다. Postman은 좋은 툴이지만 하나 하나 send 버튼을 누르며 테스트를 해야하는 불편함이 있었다.
하지만 Test 코드를 작성하면 한줄의 명령으로 모든 테스트 케이스를 한번에 처리할 수 있다는 큰 장점이 있다.
drf의 APITestCase를 상속받아서 클래스로 test 케이스를 만들 수 있다.
# tests.py
from rest_framework.test import APITestCase
from rest_framework.views import status
from django.shortcuts import resolve_url
from django.urls import reverse
from ..models import *
class PhoneVerificationTestCase(APITestCase):
def setUp(self):
self.url_1 = '/accounts/verification'
self.url_2 = reverse('accounts:verification')
self.data = {"phone": "01012345678"}
def test_post_phone_number_success(self):
response = self.client.post(self.url_1, data=self.data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
def test_post_phone_number_string_error(self):
data = {"phone": "010123456abc"}
response = self.client.post(self.url_2, data=data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
setUp 작성하기
먼저 setUp 메서드에서 기본적으로 test에 필요한 url, 공통적으로 body에 담길 data 등을 지정할 수 있다.
url에서 만약 url name을 사용하려면 위 코드의 url_2와 같이 reverse 혹은 resolve_url 사용할 수 있다.
테스트 케이스 만들기
테스트 함수명의 앞에는 test가 있어야 테스트가 실행된다.
self.client 뒤에 http 메소드(위에서는 post)를 써주고 인자로 (url, data, format)을 넣으면 이에 대한 응답이 response에 담기게 된다.
self.assertEqual는 테스트의 응답이 기대하는 응답과 일치하는지 확인해준다. 위 코드에서는 인자로 response의 상태코드, 기대하는 응답의 상태 코드를 넣어주었다.
python manage.py test
명령으로 테스트가 실행된다.
첫번째 테이스 케이스에서 201 상태 코드를 반환하면 테스트에 통과하게 되고 다른 상태 코드를 반환하면 fail이 뜨게 된다.
factory를 사용하면 간편하게 테스트용 임시 데이터를 생성할 수 있으며 다량의 데이터가 필요할 때 더욱 편리하다.
pip install factory-boy
factory를 사용하기 위해서 우선 factory-boy를 인스톨한다.
pip install faker
무작위 데이터를 생성해주는 faker를 인스톨한다.
# factories.py
import factory
from faker import Faker
from django.contrib.auth.hashers import make_password
from ..models import *
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = User
name = Faker().name()
nickname = Faker().name()
email = factory.lazy_attribute(lambda u: f"{u.name.split()[0]}@example.com")
phone = "01012345678"
password = make_password("qwer1234")
위 코드를 통해 테스트용 user 인스턴스를 만들 수 있다.
factory를 임포트한 뒤, 무작위 데이터를 생성해주는 Faker를 임포트해준다.
UserFactory 클래스에 factory.django.DjangoModelFactory를 상속받는다.
class Meta에 사용할 모델(여기서는 User)를 지정해준다. (serializer와 유사함)
이제 필드값을 지정해주는데, 이때 이름과 닉네임은 Faker().name()을 통해 무작위로 생성해준다. (이외 이메일의 경우 Faker().email() 등 사용 가능..)
factory.lazy_attribute를 통해 위에서 지정한 필드값을 사용할 수 있다.(위 코드에서는 name 값의 첫번째 문자열을 이메일 앞부분으로 사용함)
전화번호와 비밀번호는 직접 지정해주었다.(비밀번호는 make_password로 암호화)
# tests.py
from .factories import UserFactory
...
class LoginTestCase(APITestCase):
def setUp(self):
self.url = '/accounts/login'
self.user = UserFactory()
def test_login_success(self):
data = {
"email": self.user.email,
"password": "qwer1234",
}
print(self.user)
response = self.client.post(self.url, data=data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
📌 faker를 통해 생성된 name과 email은 다음과 같다.
print(self.user.name)
print(self.user.email)
-----------------------------
Glenn Hunter
Glenn@example.com
만약 Factory를 사용하지 않았다면 로그인 테스트 코드가 다음과 같게 된다.
(setUp에서 테스트용 user 객체를 생성)
class LoginTestCase(APITestCase):
def setUp(self):
self.url = '/accounts/login'
self.user = User.objects.create(
email="test@example.com",
nickname="test",
phone="01012345678"
)
self.user.set_password("qwer1234")
self.user.save()
def test_login_success(self):
data = {
"email": "test@example.com",
"password": "qwer1234",
}
response = self.client.post(self.url, data=data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
factory를 사용하면 테스트 코드가 간결해지고 가독성이 높아지는 것을 느낄 수 있다. (다량의 객체 생성이 필요할 때 효과 up)