TEST 사용 (Test Case, Unit Test)

승훈·2022년 11월 11일
0

Django 기초

목록 보기
8/10

자동화 된 테스트란?

코드의 동작을 체크하는 작업으로 많은 사람들과 공동작업을 하는 경우 반드시 필요한 기능이다. 수십, 수백개의 컴포넌트를 자동으로 테스트 하여 시간을 절약 할 수 있고 기능을 명확히 하여 앞으로 생길 문제를 밝혀낼 수 있다.

버그 식별하기

models.py에 데이터가 최근 데이터인지 아닌지를 확인하는 테스트를 해보겠다. 현재 날짜로 부터 미래의 날짜는 최근 데이터가 아닌 FALSE 데이터로 인식한다

  1. mysite에서 Shell 모드를 실행한다.

  2. 다음 명령어를 통해 현재 상태를 확인한다.

    >>> 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
  1. 이러한 작업이 수동으로 Test를 하는 방법이다.

버그를 노출하는 테스트 만들기

  1. 애플리케이션 안의 test.py 파일에 테스트 할 내용을 작성해준다.

    클래스 이름은 Test로 시작하는게 좋으며 TestCase를 상속해놓아야 한다.

    # /workspace/Edu_02/mysite/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)

테스트 실행

  1. 쉘모드로 접속하여 아래 코드로 Test를 자동으로 수행해본다.

    $ python manage.py test polls
  2. AssertionError가 나올 것이다. 예상했던 결과값이 False가 아닌 True 이기 때문이다. 테스트를 동과하면 OK메세지가 뜬다.

보다 포괄적인 테스트

발생할 수 있는 모든 경우에 대해 테스트코드를 작성해 놓는 것이 좋다. 코드의 양과 상관없이 여러번 체크가 가능하게 결과값은 다를지언정 같은 내용을 테스트 하는 여러 테스트를 수행하는 것도 좋은 방법니다.

def test_was_published_recently_with_old_question(self):
    """
    was_published_recently() returns False for questions whose pub_date
    is older than 1 day.
    """
    time = timezone.now() - datetime.timedelta(days=1, seconds=1)
    old_question = Question(pub_date=time)
    self.assertIs(old_question.was_published_recently(), False)

def test_was_published_recently_with_recent_question(self):
    """
    was_published_recently() returns True for questions whose pub_date
    is within the last day.
    """
    time = timezone.now() - datetime.timedelta(hours=23, minutes=59, seconds=59)
    recent_question = Question(pub_date=time)
    self.assertIs(recent_question.was_published_recently(), True)

뷰 테스트

뷰는 Request를 받고 Response를 해주는 것이 핵심이다. Django에서는 뷰레벨에서 사용자를 시뮬레이트 하기 위해 클래스 Client를 제공하며 이 테스트 클라이언트를 test.py 혹은 Shell 모드에서 사용가능하다. 일단 쉘을 이용한 테스트 방법을 알아본다.

  1. 쉘 모드로 접속한다.

  2. 테스트에 필요한 추가적인 속성을 사용할 수 있도록 setup_test_enviroment()를 설치한다.

    >>> from django.test.utils import setup_test_environment
    >>> setup_test_environment()
  3. 테스트 클라이언트 클래스를 import 한다.

    >>> from django.test import Client
    >>> # create an instance of the client for our use
    >>> client = Client()
  4. 이제 아래와 같이 뷰를 테스트 해볼 수 있다.

    >>> # get a response from '/'
    >>> response = client.get('/') # 조회를 위해 호출
    Not Found: /
    >>> response.status_code # 서버의 응답상태 반환
    404
    >>> from django.urls import reverse
    >>> response = client.get(reverse('polls:index'))
    >>> response.status_code # 서버응답이 성공하면 200을 반환한다.
    200
    >>> response.content
    b'\n    <ul>\n    \n        <li><a href="/polls/1/">What&#x27;s up?</a></li>\n    \n    </ul>\n\n'
    >>> response.context['latest_question_list']
    <QuerySet [<Question: What's up?>]>

새로운 뷰 테스트

포괄적인 테스트를 위해 Test Class를 만들어 사용할 수도 있다. 가능한 모든 상황을 코딩해놓고 정상응답 하는지, 어떤 값이 반환 될 것인지 등을 미리 정의해두고 그 조건에 맞으면 테스트가 통과되는 방식이다. 여러 테스틀 함으로 하드코딩하기 보단 반복되는 값에 대해서 미리 정의를 해놓고 가져와서 쓰는 방식이 추천된다


from django.urls import reverse

def create_question(question_text, days):
    time = timezone.now() + datetime.timedelta(days=days)
    return Question.objects.create(question_text=question_text, pub_date=time)

class QuestionIndexViewTests(TestCase):
    def test_no_questions(self):
        response = self.client.get(reverse('polls:index'))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "No polls are available.")
        self.assertQuerysetEqual(response.context['latest_question_list'], [])

    def test_past_question(self):
        question = create_question(question_text="Past question.", days=-30)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(
            response.context['latest_question_list'],
            [question],
        )

    def test_future_question(self):
        create_question(question_text="Future question.", days=30)
        response = self.client.get(reverse('polls:index'))
        self.assertContains(response, "No polls are available.")
        self.assertQuerysetEqual(response.context['latest_question_list'], [])

    def test_future_question_and_past_question(self):
        question = create_question(question_text="Past question.", days=-30)
        create_question(question_text="Future question.", days=30)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(
            response.context['latest_question_list'],
            [question],
        )

    def test_two_past_questions(self):
        question1 = create_question(question_text="Past question 1.", days=-30)
        question2 = create_question(question_text="Past question 2.", days=-5)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(
            response.context['latest_question_list'],
            [question2, question1],
        )

0개의 댓글

관련 채용 정보