well-balanced

[Django tutorial] 장고 테스트 자동화 본문

Python

[Django tutorial] 장고 테스트 자동화

Cosmian 2020. 2. 1. 03:47

Django tutorial을 참고해서 작성했습니다.
많은 의역이 있습니다. 올바르지 않은 부분이 있다면 댓글 남겨주시면 감사하겠습니다.

우리에게 아래와 같은 Question 모델이 있다고 생각해보자.

class Question(models.Model):
    def __str__(self):
        return self.question_text

    def was_published_recently(self):
        now = timezone.now()
        return self.pub_date >= timezone.now() - datetime.timedelta(days = 1)

    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

was_published_recently 메소드는 발행 날짜가 오늘로부터 하루가 지나가지 않았다면 True를 리턴하는 친구다.

이를 shell에서 한번 Test 해보자.

>>> import datetime
>>> from django.utils import timezone
>>> from polls.models import Question
>>> # create a Question instance with pub_date 30 days in the future
>>> future_question = Question(pub_date=timezone.now() + datetime.timedelta(days=30))
>>> # was it published recently?
>>> future_question.was_published_recently()
True

False를 리턴해야하지만 우리가 의도했던 것과는 다르게 True를 리턴하고 있다. 이를 자동적으로 테스트하는 코드를 만들어보자. Django tutorial의 경우는 polls/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 questions 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)

그리고 터미널에서 한번 테스트를 돌려보자.

$ python manage.py test polls
...
AssertionError: True is not False

Ran 1 test in 0.001s

FAILED (failures=1)
Destroying test database for alias 'default'...

아마 어떤 라인에서 에러가 발생했는지 등을 알려주고, 위와 같은 에러를 반환할 것이다.

자 어떤 일이 일어났는지 단계별로 살펴보자.

1. manage.py test polls 명령어를 입력함으로써 polls app 안에 있는 test 파일을 찾는다.
2. django.test.TestCase를 상속받고 있는 서브 클래스를 찾는다.
3. 테스팅을 수행하기 위해 특별한 데이터베이스를 생성한다.
4. test로 시작하는 메소드들을 찾는다. 여기선 test_was_published_recently_with_future_question 메소드가 된다.
5. 해당 메소드에서 생성날짜 필드가 30일 후인 Question 인스턴스를 생성한다.
6. assertIs 메소드를 사용해서 was_published_recently 가 우리가 기대한 False가 아닌 True를 리턴했음을 발견한다.
7. 테스트는 터미널에서 우리에게 어떤 테스트가 실패했고, 어떤 라인에서 에러가 발생했는지 알려준다.

그럼 이제 테스트에 실패한 모델의 메소드를 수정하러 가야한다.

def was_published_recently(self):
    now = timezone.now()
    return now - datetime.timedelta(days=1) <= self.pub_date <= now

그리고 다시 테스트를 하면 아래와 같은 결과를 얻을 수 있다.

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK
Destroying test database for alias 'default'...

우리는 버그를 노출시키는 테스트를 작성했고, 우리의 테스트를 통과하도록 버그를 수정했다.

훗날에 우리의 App에서는 많은 버그들이 발생할 것이다. 하지만 우리가 작성한 테스트가 동작하면서 우리에게 즉시 경고할 것이기 때문에 우리는 무심코 이 버그를 다시 다룰 일이 없다는 것을확신할 수 있다. 앱의 이 작은 부분만큼은 안전하게 고정시켰다고 생각할 수 있다.

이렇게 테스트를 하는 것이 왜 좋은지 묻는다면 아무래도 테스트가 시스템에 의해 수행된다는 점일 것이다. 테스트 세트를 한 번 만들어놓으면 시간이 많이 걸리는 수동 테스트를 수행할 필요 없이 코드가 원래 의도한 대로 잘 동작하는지 확인할 수 있다. Django 공식 튜토리얼 문서에서는 이외에도 많은 장점을 소개하는데 이를 간단하게 요약 작성하고 이만 끝내려한다.

Tests will save you time
어떤 요소중 어느 하나가 변경되면 app의 동작하지 않을 수 있다. 뭔지 알 수 없는 하나를 확인하기 위해 20가지의 다른 종류의 테스트 데이터를 사용하여 코드를 실행한다면 당연히 시간을 낭비할 수 밖에 없다. 때로는 생산적이고 창의적인 프로그래밍 작업에서 벗어나, 코드가 제대로 동작하고 있는지를 테스트하는 코드를 만든다는 것은 매력적이지 않고 재미없는 사업에 직면하는 일처럼 보일 수도 있다. 그러나, 테스트를 작성하는 일은 당신의 app을 수동으로 테스트하거나 새롭게 발생한 문제의 원인을 규명하는데 몇 시간을 소비하는 것보다 훨씬 더 만족스러운 일이다.

Tests don’t just identify problems, they prevent them
Test가 없다면 애플리케이션의 목적이나 의도된 동작은 다소 불투명할 수 있다. 심지어 그것이 당신이 작성한 코드일지라도 그것이 정확하게 어떤 일을 하는지 알아내려고 노력하면서 그 안에서 이리저리 쑤시고 다니는 자신을 발견하게 될 것이다. 테스트는 그것을 변화시킨다. 당신의 코드를 내부에서 비추고, 잘못된 것이 있다면 비록 당신이 그것에 대해 인지하지 못했더라도 그 부분에 집중시킨다.

Tests make your code more attractive
당신은 훌륭한 소프트웨어를 만들었을지도 모른다. 하지만 다른 개발자들은 테스트가 부족하다는 이유로 그걸 보지 않는 일이 생길 것이다. 테스트가 없기 때문에 그들은 그것을 믿지 않는 것이다.
장고 개발자 중 한 명인 Jacob Kaplan-Moss는 이렇게 말했다. “Code without tests is broken by design.”
다른 개발자들이 소프트웨어를 보기 전에 테스트를 보고 테스트한다는 것도 당신이 테스트를 작성해야하는 이유 중 하나이다.

Tests help teams work together
위에서는 개인 프로젝트를 유지하는 개발자의 관점에서 다뤘지만, 주로 복잡한 애플리케이션은 팀 단위로 유지된다. 테스트는 팀원들이 무심코 당신의 코드를 망가뜨리지 않는 것을 보장한다. Django 프로그래머를 직업삼고 싶다면 Test를 잘 작성해야만 한다!

Comments