[Django] 테스팅(Testing) 과정

오제욱·2024년 10월 1일
0
post-thumbnail

테스트 코드의 필요성

과거에 API를 작성한 후 테스트 할때 Insomnia 를 사용하여 직접 요청에 대한 응답 값을 확인했었다.
물론 Insomnia 를 사용해서 API를 테스트 하는 방법도 나쁘지 않았지만 관리 하는 API가 많아지고 복잡한 기능의 API를 테스트 하다 보니 관리가 힘들어지고 API를 테스트 하는데 걸리는 시간도 늘어나게 되었다.


위 사진 처럼 관리하는 API 가 많아지다 보니 관리가 힘들어졌고 가독성도 많이 떨어졌다.

Django Test 기능

Django의 테스트 프레임워크를 사용하면 자동화된 방식으로 다양한 테스트를 작성하고 실행할 수 있다. Django는 API에 대한 테스트도 지원합니다. 이를 통해 코드가 변경되더라도 새로운 버그를 빠르게 찾을 수 있다.

1. 테스트 파일 생성

앱 디렉토리 안에 tests.py 파일을 만들어 테스트를 작성할 수 있다. 하지만 더 구조화된 테스트를 원한다면, tests라는 디렉토리를 만들고 그 안에 각 기능별로 테스트 파일을 나눠 관리할 수 있다.

간단한 구조

myapp/
    tests.py

복잡한 구조

tests/
    __init__.py
    test_models.py
    test_views.py
    test_api.py

이렇게 구조화하면 앱 내의 각 기능에 대해 별도의 테스트 파일을 관리할 수 있어 가독성과 유지 보수에 좋다.

2. 테스트 코드 작성

테스트 코드는 Django의 TestCase를 상속받아 작성할 수 있습니다. TestCase는 Django에서 확장한 테스트 클래스이며, 자동으로 데이터베이스를 초기화해주고 롤백 기능을 제공한다.
각 테스트 함수의 네이밍은 test 로 시작 해야 한다.

from django.test import TestCase
from myapp.models import MyModel

class MyModelTest(TestCase):
	"""MyModel Test Definition"""
    def test_model_creation(self):
    	"""test model create"""
        name = "Test object"
        # 모델 객체 생성
        obj = MyModel.objects.create(name=name)
        # 객체가 정상적으로 생성되었는지 테스트
        self.assertEqual(obj.name, name)

이처럼 간단한 테스트를 진행 할 수 있다.

3. 테스트 Set up

TestCase의 setUp() 메서드를 사용하여 각 테스트 전에 실행될 코드를 정의할 수 있다. 예를 들어, 공통으로 사용할 테스트 데이터를 미리 생성해둘 수 있다.

from django.test import TestCase
from myapp.models import MyModel

class MyModelTest(TestCase):

    def setUp(self):
        # 테스트 실행 전 데이터베이스에 미리 객체를 생성
        self.obj = MyModel.objects.create(name="Set up object")

    def test_model_setup(self):
        # setUp에서 생성한 객체가 있는지 확인
        self.assertEqual(self.obj.name, "Set up object")

setUp() 메서드를 사용하면 각 테스트 전에 기본 설정을 통해 반복적인 객체 생성을 줄일 수 있다.
API 테스트를 위한 초기 데이터 세팅을 주로 진행한다.

4. API 테스트

DRF를 사용하여 API를 개발하면 APITestCase를 활용해 API 테스트를 할 수 있다. API 테스트에서는 GET, POST, PUT, DELETE 등의 요청을 테스트 할 수 있다.

API 코드

views.py

from rest_framework import viewsets
from myapp.models import MyModel
from myapp.serializers import MyModelSerializer

class MyModelViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

serializers.py

# serializers.py
from rest_framework import serializers
from myapp.models import MyModel

class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = '__all__'

3. urls.py

# urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from myapp import views

router = DefaultRouter()
router.register(r'mymodel', views.MyModelViewSet, basename='my_model')

urlpatterns = [
    path('', include(router.urls)),
]

API와 URL 설명

  1. API 엔드포인트:

    • /mymodel/MyModel 객체 목록을 가져오거나 새 객체를 생성
    • /mymodel/pk/ → 특정 MyModel 객체에 대한 상세 정보, 수정, 삭제
  2. URL 사용:

    • reverse('my_model_list'): "/mymodel/" URL을 생성하며, GET 요청 시 객체 목록을 가져오고 POST 요청 시 객체를 생성
    • reverse('my_model_detail', kwargs={'pk': self.my_model.pk}): /mymodel/<pk>/ URL을 생성하며, 특정 객체에 대해 GET, PUT, DELETE 요청을 수행

테스트 코드

from rest_framework.test import APITestCase
from rest_framework import status
from django.urls import reverse
from myapp.models import MyModel

class MyAPITest(APITestCase):

  def setUp(self):
      # 테스트 데이터 생성
      self.my_model = MyModel.objects.create(name="API Test Object")
		# url 정의
      self.url = reverse('my_model_detail', kwargs={'pk': self.my_model.pk})

  def test_get_api(self):
      # GET 요청을 테스트
      response = self.client.get(self.url)
      # 상태 코드 확인
      self.assertEqual(response.status_code, status.HTTP_200_OK)
      # 응답 데이터 확인
      self.assertEqual(response.data['name'], 'API Test Object')

  def test_post_api(self):
      # POST 요청을 테스트
      data = {'name': 'New Object'}
      response = self.client.post(reverse('my_model_list'), data)
      # 상태 코드 확인
      self.assertEqual(response.status_code, status.HTTP_201_CREATED)
      # 새 객체가 제대로 생성되었는지 확인
      self.assertEqual(MyModel.objects.count(), 2)
      self.assertEqual(MyModel.objects.last().name, 'New Object')

위와 같은 방법으로 API 테스트 코드를 작성 할 수 있다.

5. 테스트 코드의 사용

위의 예시 외에 더 다양한 형식으로 API 테스트 코드를 작성 할 수 있다.
작성한 API에 대한 여러가지 성공과 실패에 대한 케이스를 작성하면 이후 변경 사항이 생겼을 때 기존의 로직이 잘 동작하는지 검사하기 좋다.

profile
Django Python 개발자

0개의 댓글