Testing in Django REST Framework

Sewon·2022년 1월 5일
1

for Django

목록 보기
1/1
post-thumbnail

사이드 프로젝트를 하며 단위 테스트를 작성하고자 하였고, 알게된 내용을 정리하고 까먹지 않기 위해 작성하였다.

Django REST Framework의 Test 클래스들은 Django의 Test 클래스들을 상속하고 있기 때문에 Django의 Test 클래스부터 잘 알아야 한다.

✔️ Django unit testing classes의 계층구조


→ Python unittest 라이브러리를 확장하여 만들어짐

test case classes

✔️ Main Testing Classes

1. Django

# test file

from django.test import TestCase

# class to define a test case for login
class UserLoginTestCase(TestCase):
	...
    # some setup
    
    def test_correct_login(self):
    	# unit test
        # 예상 시나리오 검증
        ...
    
    def test_if_password_incorrect_then_cant_login(self):
    	# unit test
        # 예상 시나리오 검증
        ...
    
    def test_if_user_not_registered_cant_login(self):
    	# unit test
        # 예상 시나리오 검증
    

2. Django REST Framework

  • DRF APITestCase 사용

  • APITestCase 클래스를 사용한 기본 테스트 케이스 구조
    기존 Django의 TestCase 클래스를 상속
    → credentials 기능이 추가된 APIClient 사용함

# test file

from rest_framework.test import APITestCase

# class to define a test case of login
class UserLoginTestCase(APITestCase):
	...

✔️ Test Fixture

  • Test Fixture란?
    → 테스트 수행 시 필요한 리소스 준비와 이를 정리하는 동작에 해당함

1. unittest 프레임워크에서 제공하는 함수, 클래스, 모듈 범위 별 Test Fixture

함수 Scope

  • setUp & tearDown
    → 하나의 클래스 내에 정의된 각각의 테스트 메소드들에 대해 setUp은 테스트 메소드 실행 전에 실행되고, tearDown은 테스트 메소드 실행 후에 실행됨

주의) setUp으로 매번 객체를 생성하는 것보다 테스트 함수 내에서 필요한 객체만 생성하는 것이 효율적이고 빠름

클래스 Scope

  • setUpClass & tearDownClass
    → 하나의 테스트 클래스 내에 정의된 테스트 메소드 실행 시 전체 1번만 동작함

모듈 Scope

  • setUpModule & tearDownModule
    → 하나의 모듈 내에서 전체 1번만 동작함

2. Django에서 추가로 제공하는 Test Fixture

  • setUpTestData
    → unittest에 속하지 않고 Django 프레임워크에 속함
    → class method이므로 클래스 Scope와 동일하게 하나의 클래스에서 1번만 실행됨 (테스트에서 Read Only로만 사용하는 객체에 대해 setUpTestData로 생성하는 것이 좋음)
    → 전체 테스트 케이스에 사용할 데이터를 정의하기 위한 class-level atomic block을 생성함
    모든 유닛 테스트 수행 후 자동으로 데이터베이스 rollback 시킴

3. 위와 같은 기존 fixture 방식의 대체 방안

  • factory_boy
    → 필요한 객체의 구조를 미리 정의해둠
    → 테스트 함수 내에서 필요한 객체 생성 가능함
    → Faker 라이브러리와 함께 사용 가능함

✔️ Assert

✔️ Test Discovery & Databases

1. Test Discovery

project
   |__django_apps
       |__users
          |__test
             |__ __init__.py
             |__ test_login.py
             |__ test_signup.py
             |__ test_delete_user.py

→ Django가 test 폴더 내부의 .py 파일을 인식함
→ 파일 내부의 test로 시작하는 테스트 케이스 함수를 실행함
→ Django에서 생성한 app 별로 test 폴더를 모듈로 생성하여 작성하는 것을 추천함

2. Test Database

→ 기본적으로, 테스트 실행 시 Django가 새로운 데이터베이스를 생성해주고 삭제시킴 (실제 서비스에 사용하는 데이터베이스와의 충돌을 방지하기 위함)
→ TEST라는 이름의 테스트용 데이터베이스를 아래와 같이 미리 정의해줄 수 있음

DATABASES = {
    'default': {
        'ENGINE': '<engine>',
        'NAME': '<database name>',
        'USER': '<database user>',
        ...
    },
    ...
    'TEST': {
        # testing database customization here
            'NAME': '<your testing database name>',
            # some other customization, for example the user user, password, etc
        },
}

Django TEST DB

→ 미리 정의하지 않는다면 Django가 자동으로 {default 세팅에 작성한 이름}_test 로 테스트용 데이터베이스를 생성함

✔️ 테스트 실행

$ python manage.py test

// 특정 테스트 실행
$ python manage.py test {django_app}
$ python manage.py test {django_app}.{test}.{file_name}
$ python manage.py test {django_app}.{test}.{file_name}.{class_name}
$ python manage.py test {django_app}.{test}.{file_name}.{class_name}.{func_name}

참고)

Python 3 unittest library docs
Testing in Django & Django REST - Useful Tools & Best Practices
Django REST Framework Testing docs
8퍼센트 Test case 작성 가이드

profile
for develop ☁️

0개의 댓글