[django] TDD 연습

haremeat·2021년 11월 29일
0

Django

목록 보기
1/16
post-thumbnail
post-custom-banner

일단 TDD 관련 글을 적기 전에

갑자기 저번 주까지는 잘 되던 장고가 안 되서 알아보니 파이썬 버전이 2.7로 돌아가 있었다.
pycharm에서 File-settings-Python Interpreter 로 접속해서 3.9로 다시 맞춰주었고
pycharm 껐다 키니 버전은 되돌아왔다.

  • 여기서 중요한 건 interpreter에 3.9로 맞춰져 있다고 해당 버전이 깔린 게 아니다! 옆의 톱니바퀴를 클릭 후 Add까지 눌러주고 OK해야 깔리는 것

그 후 장고 재설치

pip install django

Pillow도 재설치

python -m pip install Pillow

테스트 코드 사용 연습하기

python manage.py test

드디어 된다.
처음엔 OK만 뜬다. 아무런 테스트 미션도 주지 않았기 때문.

blog 폴더의 tests.py를 다음과 같이 작성해보자

from django.test import TestCase

# Create your tests here.

class TestView(TestCase):
    def test_post_list(self):
        self.assertEqual(2, 3)

그리고 다시 테스트 코드를 돌려보면 Fail이 뜬다.
2와 3은 같지 않으니 당연한 결과

from django.test import TestCase

# Create your tests here.

class TestView(TestCase):
    def test_post_list(self):
        self.assertEqual(2, 2)

이렇게 적으면 OK가 뜬다.

beautifulsoup4 설치하기

웹 브라우저 타이틀이 뭐라고 되어 있는지, 버튼에 써 있는 내용은 무엇인지 알기 위해서는 html로 나타내는 페이지의 요소를 쉽게 다룰 수 있는 도구가 필요하다. 이를 위해 먼저 beautifulsoup4를 설치해보자.

pip install beautifulsoup4

test.py에 테스트할 내용 나열하기

from django.test import TestCase, Client

class TestView(TestCase):
    def setUp(self):
        self.client = Client()


    def test_post_list(self):
        # 1.1 포스트 목록 페이지를 가져온다.
        # 1.2 정상적으로 페이지가 로드된다.
        # 1.3 페이지 타이틀은 'Blog'이다.
        # 1.4 내비게이션 바가 있다.
        # 1.5 Blog, About Me라는 문구가 내비게이션 바에 있다.

        # 2.1 메인 영역에 게시물이 하나도 없다면
        # 2.2 '아직 게시물이 없습니다'라는 문구가 보인다.

        # 3.1 게시물이 2개가 있다면
        # 3.2 포스트 목록 페이지를 새로고침했을 때
        # 3.3 메인 영역에 포스트 2개의 타이틀이 존재한다.
        # 3.4 '아직 게시물이 없습니다'라는 문구는 더 이상 보이지 않는다.

테스트 코드 작성

from django.test import TestCase, Client
from bs4 import BeautifulSoup
from .models import Post

class TestView(TestCase):
    def setUp(self):
        self.client = Client()


    def test_post_list(self):
        # 1.1 포스트 목록 페이지를 가져온다.
        response = self.client.get('/blog/')
        # 1.2 정상적으로 페이지가 로드된다.
        self.assertEqual(response.status_code, 200)
        # 1.3 페이지 타이틀은 'Blog'이다.
        soup = BeautifulSoup(response.content, 'html.parser')
        self.assertEqual(soup.title.text, 'Blog')
        # 1.4 내비게이션 바가 있다.
        navbar = soup.nav
        # 1.5 Blog, About Me라는 문구가 내비게이션 바에 있다.
        self.assertIn('Blog', navbar.text)
        self.assertIn('About Me', navbar.text)

        #
        # 2.1 메인 영역에 게시물이 하나도 없다면
        self.assertEqual(Post.objects.count(), 0)
        # 2.2 '아직 게시물이 없습니다'라는 문구가 보인다.
        main_area = soup.find('div', id='main-area')
        self.assertIn('아직 게시물이 없습니다', main_area.text)

        # 3.1 게시물이 2개가 있다면
        post_001 = Post.objects.create(
            title = '첫 번째 포스트입니다.',
            content = '1등이 전부는 아니잖아요?'
        )
        post_002 = Post.objects.create(
            title = '두 번째 포스트입니다.',
            content = '1등이 전부는 아니잖아요?'
        )
        self.assertEqual(Post.objects.count(), 2)

        # 3.2 포스트 목록 페이지를 새로고침했을 때
        response = self.client.get('/blog/')
        soup = BeautifulSoup(response.content, 'html.parser')
        self.assertEqual(response.status_code, 200)

        # 3.3 메인 영역에 포스트 2개의 타이틀이 존재한다.
        main_area = soup.find('div', id='main-area')
        self.assertIn(post_001.title, main_area.text)
        self.assertIn(post_002.title, main_area.text)
        # 3.4 '아직 게시물이 없습니다'라는 문구는 더 이상 보이지 않는다.
        self.assertNotIn('아직 게시물이 없습니다.', main_area.text)

이후 테스트를 다시 돌려보면
당연하게도 Fail이 뜬다.

Traceback (most recent call last):
File "D:\python_django\DjangoExample\blog\tests.py", line 29, in test_post_list
self.assertIn('아직 게시물이 없습니다', main_area.text)
AttributeError: 'NoneType' object has no attribute 'text'

main_area = soup.find('div', id='main-area')에 해당되는 내용이 없기 때문에 오류가 뜬다. id가 main-area인 div가 아직 없기 때문에 None이 저장됐기 때문이다.

Traceback (most recent call last):
File "D:\python_django\DjangoExample\blog\tests.py", line 29, in test_post_list
self.assertIn('아직 게시물이 없습니다', main_area.text)
AssertionError: '아직 게시물이 없습니다' not found in '\nBlog\n'

이제는 문구가 조금 바뀌었다. 게시물이 없을 때 문구가 뜨는 기능을 아직 구현하지 않아서 그렇다.

{% if post_list.exists %}

{% for p in post_list %}
<div class="card mb-4">
    {% if p.head_image %}
    <img src="{{ p.head_image.url }}" alt="Card img cap" class="card-img-top head-img">
    {% else %}
    <img src="https://picsum.photos/seed/{{ p.id }}/800/200" alt="Card img cap" class="card-img-top">
    {% endif %}
    <div class="card-body">
        <h2 class="card-title">{{ p.title }}</h2>
        {% if p.hook_text %}
        <h5 class="text-muted">{{ p.hook_text }}</h5>
        {% endif %}
        <p class="card-text">{{ p.content | truncatewords:45 }}</p>
        <a href="{{ p.get_absolute_url }}" class="btn btn-primary">Read More &rarr;</a></h2>
    </div>
</div>
{% endfor %}

{% else %}
    <h3>아직 게시물이 없습니다.</h3>
{% endif %}

어렵지 않으니 바로 구현해주자

Ran 1 test in 0.022s
OK
Destroying test database for alias 'default'...

드디어 OK가 뜬다.

Ref

장고 + 부트스트랩 파이썬 웹 개발의 정석

profile
버그와 함께하는 삶
post-custom-banner

0개의 댓글