Python

[Django] 테스트 코드 작성해보기

2023. 6. 3. 15:52

Django 튜토리얼의 챕터 5가 테스트 작성에 대한 내용이다.

'테스트 코드'에 대해 들어는 봤지만 실제로 작성해보기는 처음이기 때문에 왜 필요한지, 어떻게 작성하는지 기록해두고자 한다.

https://docs.djangoproject.com/ko/4.2/intro/tutorial05/

 

Django

The web framework for perfectionists with deadlines.

docs.djangoproject.com

 

테스트 코드란?

말 그대로 내가 개발한 것에 대한 테스트를 수행하는 코드이다.

내가 개발한 코드가 원하는 대로 동작을 하더라도, 비정상 상황에 대해 정상인것 처럼 작동한다면 문제가 있는 코드이다.

특히 코드를 수정할 때 기존 코드와 꼬여 예상치 못한 동작을 하게 될 수 있는데, 이 경우 테스트 코드가 버그를 잡아낼 수 있도록 도와준다.

코드를 수정할 때마다 매번 비정상 동작에 대한 검수를 하나하나 할 수 없기 때문에, Django에서는 이를 코드로 짜두고 자동화 테스트를 지원한다.

 

테스트 코드 짜보기

class Question(models.Model):
    question_text = models.CharField(max_length=200)    # 문자
    pub_date = models.DateTimeField("date published")   # 날짜와 시간
    
    def __str__(self):
        return self.question_text
    
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1) # 1일 이내 작성된 경우

Question이라는 모델에 pub_date라는 변수가 존재한다. 이는 Question 객체가 언제 생성되었는지를 저장하는 변수이다.

해당 클래스의 was_published_recently() 함수를 통해, Question 객체가 1일 이내에 생성되었는지 아닌지를 판별한다.

 

이때, pub_date에 미래의 시간이 저장되는 경우에도 was_published_recently() 함수가 True를 리턴하는 반례가 생긴다.

이를 shell로 확인해볼 수 있다.

 

이에 대한 test 코드는 다음과 같이 짤 수 있다. (test 코드는 테스트하고자하는 객체가 존재하는 애플리케이션의 tests.py(기본생성 폴더)에 작성하면 된다.)

import datetime
from django.test import TestCase
from django.utils import timezone
from .models import Question

class QuestionModelTests(TestCase):
    def test_was_published_recently_with_future_question(self):
        """
        was_published_recently() returns False for question whose pub_date is in the future.
        """
        time = timezone.now()+datetime.timedelta(days=30)
        future_question = Question(pub_date=time)
        self.assertIs(future_question.was_published_recently(), False)  # 결과가 False인지 검증

Question model에 대한 검증이라는 것을 명시하는 QuestionModelTests 클래스를 만들고, 그 안에 세부 메소드를 작성하도록 한다.

test_was_published_recently_with_future_question() 함수에서는, 현재로부터 30일 이후의 날짜를 pub_date로 가지는 future_question 객체를 생성한다.

그리고 assertIs()함수를 통해 future_question 객체에 대해 was_published_recently()를 수행하고 이 결과가 False가 나오는지 검증한다.

 

코드를 작성하고 python manage.py test <app_name>으로 코드를 실행하면 다음과 같이 뜬다.

결과를 통해 tests.py의 어떤 테스트가 실패했는지, 몇번째 줄에서 발생했는지, 원래 나와야 하는 값과 어떻게 다른지에 대해 상세하게 알 수 있다!

 

python manage.py test <app_name> 명령어를 수행했을 때 Django에서는 다음과 같은 순서로 테스트를 수행한다.

1. 입력한 app_name의 애플리케이션에서 테스트를 찾는다.
2. django.test.TestCase의 subclass가 존재하는지 찾는다.
3. 테스트를 목적으로하는 별도의 데이터베이스를 생성한다.
4. 함수 이름이 "test"로 시작하는 것들을 찾아 테스트를 수행한다.

 

앞으로 코드를 작성할때 때 발생할 수 있는 예외사항을 다양하게 고려해보고, 이를 테스트로 짜는 연습을 많이 해봐야할 것 같다.

 

+)코드 수정 후, 테스트에 통과하면 결과가 다음과 같이 나온다.