[Django] Unit Test

hukim·2020년 11월 8일
0

Django

목록 보기
9/12
post-custom-banner

Unit Test란?

내가 작성한 코드의 가장 작은 단위인 함수를 테스트하는 메소드 입니다.
그래서 내가 작성한 로직을 테스트하는 유닛테스트 코드를 짜서 테스트하게 됩니다.

지금까지는 제가 백엔드 서버를 동작시키고 Httpie나 postman으로 주로 Integration 테스트를 수행해왔습니다.

예를 들어 테스트할 엔드포인트가 10개라면 이것을 httpie나 postman으로 테스트하면 최소 수분은 걸릴 것이고 엔드포인트 10개를 테스트하는 유닛테스트를 돌린다면 수초만에 테스트가 끝날 것입니다. 그리고 Integration테스트는 데이터베이스 서버를 돌려야하고 메모리가 유닛테스트보다 더 많이 사용하게 되므로 비용도 비쌉니다.

Unit Test 작성하기

파이썬에 유닛테스트를 할 수 있는 unittest 모듈을 이용했습니다.

간단한 이력서 리스트를 가져오는 view를 작성했습니다.

class ResumeListView(View):
	def get(self, request):
            resume_list = [{
                'id'          : resume.id,
                'title'       : resume.title,
                'status'      : resume.status,
                'create_time' : resume.create_time
            } for resume in Resume.objects.filter(user = 1)]

            return JsonResponse({'message' : 'SUCCESS', 'resume_list' : resume_list}, status = 200)            

다음은 test.py을 만들고 유닛테스트를 작성합니다.

from django.test   import TestCase, Client
from user.models   import User
from resume.models import Resume
from datetime      import datetime

class ResumeListTest(TestCase):
    def setUp(self):
        User.objects.create(
            id                = 1,
            email             = 'email',
            password          = 'password',
            phone             = 'phone',
            name              = 'name',
            profile_image_url = 'image'
        )

        Resume.objects.create(
            id           = 1, 
            title        = 'title',
            status       = False,
            introduction = 'introduction',
            user_id      = 1
        )

    def tearDown(self):
        User.objects.all().delete()
        Resume.objects.all().delete()

    def test_resumelist_get_success(self):
        client = Client()
        response = client.get('/resume')
        self.assertEqual(response.json(),
            {
                'message' : 'SUCCESS',
                'resume_list' : [{
                    'id' : 1,
                    'title' : 'title',
                    'status' : False,
                    'create_time' : datetime.today().strftime('%Y-%m-%d')
                }]
            }
        )
        self.assertEqual(response.status_code, 200)
    
    def test_resumelist_get_not_found(self):
        client = Client()
        response = client.get('/resume/')
        self.assertEqual(response.status_code, 404)
  • 실행결과

장고를 테스트할 때 우리는 결국 각각의 함수를 호출하는 것이 아니라 우리가 설정한 엔드포인트 경로를 통해 함수를 호출해야합니다.

그러기 위해 사용하는 것이 Client() 객체 입니다. request나 http와 비슷한 일을 하고 이름대로
클라이언트로서 동작합니다.

테스트 케이스를 만들 때는 항상 TestCase() 객체를 상속받아 새로운 테스트 클래스를 생성합니다.

내부에 작성하는 테스트 함수 명은 언제나 test_로 시작해야합니다.

  • setUp 에서 테스트할 데이터들을 create합니다.
  • tearDown에서는 테스트를 마치고 데이터들을 모두 삭제합니다.
  • 위에서는 두 가지의 경우에 대해서 테스트했습니다. (success, not_found)
  • response = client.get('/resume') localhost가 아닌 기준 경로로부터 실행합니다.
  • self.assertEqual(response.status_code, 200) 응답코드를 비교합니다.
  • self.assertEqual(response.json(), ...) JSON 데이터를 서로 비교합니다.

Unit Test의 장점

  • 유닛테스트는 Ui Test 또는 Integration Test보다 테스트 비용이 싸다고 할 수 있습니다.
    Ui Test는 백엔드 서버와 프론트 서버를 연동하여 사람이 직접 테스트하지만, 유닛테스트는 사람이 스크립트로 한꺼번에 자동으로 실행하기 때문입니다.
  • 유닛테스트는 다른 테스트에 비해 실행 속도도 매우 빠릅니다. 그래서 유닛테스트를 활용하면 하루에도 배포를 여러번 할 수 있어서 개발 및 배포 속도에 중요한 영향을 줍니다. 그렇기 때문에 개발을 할 때 최대한 활용하는 편이 좋습니다.
  • 새로운 기능을 구현할 때 유닛 테스트를 잘 작성해놓으면 중장기적으로 유지 보수가 쉬운 장점이 있습니다.
  • 유닛테스트를 잘 짜놓으면 유닛테스트가 되었던 코드에서는 버그가 거의 발견되지 않고 대부분 버그가 발견되는 경우는 유닛테스트가 없어서 발생하는 경우가 많고 만약 뒤늦게 발견된 버그에 대해서도 버그를 수정한 후 유닛테스트를 작성해놓으면 버그를 방지할 수 있습니다.
post-custom-banner

0개의 댓글