본문 바로가기

Django/DRF

[Django rest framework] TDD - Unit Test

 

 

먼저, 사전과제 개발을 진행하면서 필요하다고 느낀 테스트 코드에 대해서 작성할 것입니다. 틀린 점이 있을 수 있습니다.

 

Django rest framework 라이브러리로 개발을 해오면서 API가 제대로 동작하는지 Postman을 사용하여 확인하였지만, API가 많아질 수록 손수 테스트하기 어려워지기 때문에 테스트 코드를 작성해야 한다.

 

Unit Test

: 하나의 모듈을 기준으로 독립적으로 진행되는 가장 작은 단위의 테스트이다. 즉, 내가 작성한 코드의 가장 작은 단위인 함수를 테스트 하는 메소드이다.

 

Unit Test가 무엇인가?

: 파이썬에는 unittest 라는 유닛테스트를 가능하게 해주는 모듈이 포함되어있다. unittest 외에도 pytest 라는 패키지도 있지만 장고에서는 기본적으로 unittest 가 사용됨으로 이 라이브러리를 사용할 것이다.

 

하지만, 우리는 DRF에서 API Test를 할 것이므로 rest_framework 에서 지원해주는 test 모듈을 사용해 볼 것이다.

 

  • TestCase : unittest 프레임워크의 테스트 조직의 기본 단위
  • FIxture : 테스트를 진행할 때 필요한 테스트용 데이터 혹은 설정 등을 의미한다. 주로 테스트가 실행되기 전이나 후에 생긴다.
  • assertion : unittest에서 테스트하는 부분이 제대로 되었는지 확인하는 부분. assertion가 실패하면 테스트도 실패한다.

 

 

Unit Test Code

 

rest_framework.test 라이브러리에서 APITestCase, APIClient 기능을 import 한다

from rest_framework.test import APITestCase, APIClient

 

 

슈퍼 유저와 상품 1을 생성하는 base setUp 함수. (기본적인 셋팅)

# 상품 목록 및 생성 테스트
class ProductLIstCreateTest(APITestCase):
    client = APIClient()

    def setUp(self):
        user = User.objects.create_superuser(
            username='admin',
            password='admin',
            name='관리자',
            email='admin@email.com',
            gender=User.GenderChoices.MALE
        )
        self.user = user

        product = Product(
            title='펑딩 상품 1',
            description='펀딩 상품 설명1 1',
            goal_price=100000,
            total_price=10000,
            fund_price=1000,
            closing_date='2022-11-11',
            user_id=self.user.id
        )
        product.save()
        self.product = product
        # assertIsInstance 메서드 -> 테스트레서 개체가 주어진 클래스의 인스턴스인지 여부를 확인하는 데 사용하는 단위 테스트.
        self.assertIsInstance(product, Product)

 

 

상품 목록을 읽어올 수 있는 코드

    # 상품 목록 페이지 < GET >
    def test_read_product(self):
        response = self.client.get(
            '/products/', content_type='application/json'
        )
        self.assertEqual(response.status_code, 200)

 

 

상품 생성 테스트 코드

    # 상품 생성 페이지 < CREATE >
    def test_create_product(self):
        context = {
            'title': '펀딩 상품 2',
            'description': '펀딩 상품 내용 2',
            'goal_price': 200000,
            'fund_price': 10000,
            'closing_date': '2022-11-11',
            'user_id': self.user.id
        }

        response = self.client.post(
            '/products/', json.dumps(context), content_type='application/json'
        )
        self.assertEqual(response.status_code, 201)

 + << django.db.utils.IntegrityError: (1048, "Column 'user_id' cannot be null") >> 에러가 뜬다...

이유는 모르겠지만 models.py 에서 Product 클래스의 user를 null=True 인자를 추가해주고 마이그레이션을 해주면 테스트는 잘 작동 한다. (22..04.20 해결못함..)

 

 

상품 상세 페이지 setUp

위와 동일하게 작성하였습니다.

class ProductDetailTest(APITestCase):
    client = APIClient()

    def setUp(self):
        # 유저 생성
        user = User.objects.create_superuser(
            id=1,
            username='admin',
            password='admin',
            name='관리자',
            email='admin@email.com',
            gender=User.GenderChoices.MALE
        )
        user.save()
        self.user = user

        # 상품 생성
        product = Product(
            id=1,
            title='펑딩 상품 1',
            description='펀딩 상품 설명1 1',
            goal_price=100000,
            total_price=10000,
            fund_price=1000,
            closing_date='2022-11-11',
            user_id=self.user.id
        )
        product.save()
        self.product = product
        # assertIsInstance 메서드 -> 테스트레서 개체가 주어진 클래스의 인스턴스인지 여부를 확인하는 데 사용하는 단위 테스트.
        self.assertIsInstance(product, Product)

    # 상품 상세 페이지 코드 < GET >
    def test_detail_product(self):
        response = self.client.get(
            f'/products/{self.product.id}/', content_type='application/json'
        )

        self.assertEqual(response.status_code, 200)

 

 

상품 상세 페이지 < READ >

# 상품 상세 페이지 코드 < GET >
    def test_detail_product(self):
        response = self.client.get(
            f'/products/{self.product.id}/', content_type='application/json'
        )

        self.assertEqual(response.status_code, 200)

 

 

상품 수정 < PATCH >
상품의 일부수정을 가능하게 할 것이므로 put 메소드를 사용하지 않고 patch 메소드를 사용하였습니다.

    # 상품 수정 코드 < PATCH >
    def test_update_product(self):
        context = {
            'title': '변경 테스트'
        }

        response = self.client.patch(
            f'/products/{self.product.id}/', json.dumps(context), content_type='application/json'
        )

        self.assertEqual(response.status_code, 200)

 

 

상품 1회 펀드금액 만큼 펀드하기 < POST >

    # 상품 1회 펀드 기능 코드 < POST >
    def test_fund_product(self):
        response = self.client.post(
            f'/products/{self.product.id}/fund/', json.dumps({'id': '1'}),
            content_type='application/json'
        )

        self.assertEqual(response.status_code, 200)

현재 1회 펀딩할 사용자에 대해서 데이터를 인식하지 못해서 에러... (22.04.22 수정중...)

'Django > DRF' 카테고리의 다른 글

[DRF] queryset과 get_queryset()의 차이점  (0) 2022.05.26
[Django] DecimalField  (0) 2022.05.25
[Django rest Framework] get_object()  (0) 2022.04.23
[Django rest Framework] Swagger 문서 자동화 ( drf-yasg )  (0) 2022.04.22
[Django] ContentType  (0) 2022.03.29