일단 TDD 관련 글을 적기 전에
갑자기 저번 주까지는 잘 되던 장고가 안 되서 알아보니 파이썬 버전이 2.7로 돌아가 있었다.
pycharm에서 File-settings-Python Interpreter 로 접속해서 3.9로 다시 맞춰주었고
pycharm 껐다 키니 버전은 되돌아왔다.
그 후 장고 재설치
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가 뜬다.
웹 브라우저 타이틀이 뭐라고 되어 있는지, 버튼에 써 있는 내용은 무엇인지 알기 위해서는 html로 나타내는 페이지의 요소를 쉽게 다룰 수 있는 도구가 필요하다. 이를 위해 먼저 beautifulsoup4를 설치해보자.
pip install beautifulsoup4
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 →</a></h2>
</div>
</div>
{% endfor %}
{% else %}
<h3>아직 게시물이 없습니다.</h3>
{% endif %}
어렵지 않으니 바로 구현해주자
Ran 1 test in 0.022s
OK
Destroying test database for alias 'default'...
드디어 OK가 뜬다.
장고 + 부트스트랩 파이썬 웹 개발의 정석