테스트 주도 개발 (TDD)는 Test Driven Development의 약자이다. TDD에 대한 자세한 내용은 따로 다룰 예정이다.
● 테스트 주도 개발 준비
테스트 하기에 앞서 blog 폴더의 test.py 파일을 다음과 같이 입력하여 테스트 케이스를 만들어 본다.
2와 3은 같지 않다는 것을 출력하며 테스트에 실패했다고 한다. django.test 패키지의 TestCase 모듈 내에 같은지 다른지 여부를 확인하는 기능이 있는 모양이다.
2, 2로 수정하면 다음과 같이 터미널에 출력된다.
● beautifulsoup4 설치
beautifulsoup4는 HTML에 의해 나타나는 페이지의 요소를 쉽게 다룰수 있게 해주는 도구이다. pip install beautifulsoup4 입력으로 설치한다.
● 포스트 목록 페이지 테스트
tests.py에 테스트할 내용 나열
blog 폴더의 tests.py에 코드와 주석을 입력해 본다.
미리 테스트할 요소들을 주석을 이용해 적어놓고 하나씩 테스트 코드를 입력해본다.
테스트 코드 작성
TestCase를 이용한 테스트 방식은 가상의 DB를 이용하므로 실제 DB와는 아무 상관없다.
# 1.1 포스트 목록 페이지 가져오기
Django test에서 clinet는 실제 사용자가 아닌 가상의 사용자다. self.clinet.get('/blog/')로 사용자가 127.0.0.1:8000의 ip와 port에 접속했다고 가정하고 열린 웹페이지 정보를 response 변수에 저장한다.
# 1.2 정상적으로 페이지 가져오기
웹 페이지를 찾을 수 없을때 404 not found로 응답하고 정상적으로 출력이 가능할 시 200을 응답 하도록 되어있다. 따라서 assertEqual(response.status_code, 200)으로 코드 200이 응답될시 테스트를 통과 하도록 한다.
# 1.3 페이지 타이틀은 'Blog'
Beautifulsoup으로 읽어들인 후 html.parser 명령어로 파싱한 결과를 soup 변수에 담는다. self.assertEqual(soup.title.text, 'Blog')로 title 요소에서 text를 이용했으므로 text 부분을 soup 변수에 저장한 후 그 변수 값이 Blog를 갖는다면 테스트를 통과 시킨다.
# 1.4 내비게이션 바가 있다.
soup.nav로 soup에 담긴 내용 중 nav 요소만 가져와 navbar에 저장한다.
# 1.5 Blog About Me 문구가 내비게이션 바에 있다.
self.assertIn('Blog' navbar.text)로 navbar 요소의 text 중에 Blog가 있다면 테스트를 통과시킨다 About Me를 찾는 코드도 동일하다.
# 2.1 포스트가 없을시
self.assertEqual(Post.objects.count(), 0)으로 작성된 포스트가 0개 인가를 확인한다. 여기서 테스트를 위해 생성된 가상의 DB는 실제 DB와는 아무런 관련이 없으며 가상의 DB는 현재 데이터가 없는 상태이다. 오직 setUp() 함수에서 설정한 요소만은 포함시킨다.
# 2.2 main area에 '아직 게시물이 없습니다' 라는 문구 보이기
soup.find를 이용하여 id가 main-area인 div 요소를 main_area 변수에 저장한다. 현재 테스트로 인해 생성된 DB는 Post 레코드가 없으므로 해당 문구가 나타는지 여부로 테스트를 통과 시킨다.
# 3.1 포스트가 2개 있을시
Post.objects.create 로 포스트를 생성하고 Post 모델의 필드값 즉 title, content를 매개변수로 한다. 이렇게 post_001, post_002를 생성하고 self.assertEqual(Post.objects.count(), 2)로 포스트가 2개 일시 테스트를 통과 시킨다.
# 3.2 포스트 목록 페이지를 새로고침 했을 때
1.1 포스트 목록 페이지를 가져오기
response = self.clinet.get('/blog/')
1.3 페이지 타이틀은 'Blog'
soup = Beautifulsoup(response.content, 'html.parser')
self.assertEqual(response.status_code, 200)
새로고침으로 인해 1.1 1.3을 반복하고 조건을 만족할 시 테스트를 통과 시킨다.
# 3.3 main area에 포스트 2개의 타이틀이 존재한다.
먼저 main_area 변수에 soup.find를 이용하여 id가 main-area인 div 요소를 저장하고 self.assertIn으로 post_001, post_002 포스트가 main-area 변수에 있는지 확인 후 테스트를 통과 시킨다.
# 3.4 '아직 게시물이 없습니다' 라는 문구는 보이지 않음
포스트 2개의 생성으로 '아직 게시물이 없습니다'라는 문구가 self.assertNotIn 에 의해 main area에 나타나지 않을 시 테스트를 통과 시킨다.
테스트를 반복하면서 post_list.html 수정
아직 테스트 코드만 작성하고 테스트 대상 코드를 수정하지 않았음으로 당연하게도 테스트 실패 오류가 터미널 상에 출력된다.
아직 id가 main-area 인 div 요소가 없기 때문에 29째 줄의 main_area 변수에 None이 저장되어 해당 테스트가 실패한다고 나온다. post_list.html 파일을 수정하여 이를 해결한다.
● 포스트 상세 페이지 테스트
tests.py에 테스트 할 내용 나열후 코드 작성
# 1.1 포스트가 하나 있다.
def test_post_detail(self): 함수 실행시 테스트를 위한 새 DB가 만들어지고 테스트를 위해 post_001 = Post.objects.create()를 이용하여 포스트 하나를 생성한다.
# 1.2 그 포스트의 url은 '/blog/1/'이다.
포스트 post_001이 생성되었고 자동적으로 포스트 레코드의 pk는 1로 부여된다. 따라서 URL은 /blog/1/이 되고 해당 URL을 가졌다면 테스트를 통과 시킨다.
# 2 첫 번째 포스트의 상세 페이지 테스트
# 2.1 첫 번째 포스트의 url로 접근하면 정상적으로 작동 (status code: 200)
URL /blog/1/로 접근했을때 status_code 값이 200으로 반환되는지 확인 후 테스트를 통과 시킨다. BeautifulSoup로 파싱하여 다루기 편하게 한다.
# 2.2 포스트 목록 페이지와 똑같은 내비게이션 바가 있다.
post_list 와 똑같은 내비게이션 바(Blog, About Me)가 있을시 테스트를 통과 시킨다.
# 2.3 첫 번째 포스트의 제목이 웹 브라우저 탭 타이틀에 들어있다.
생성한 포스트 post_001의 title 필드 값이 웹 브라우저 탭의 타이틀에 있는지 확인 후 테스트를 통과 시킨다.
# 2.4 첫 번째 포스트의 제목이 포스트 영역에 있다.
메인영역에서 포스트 영역만 불러온다. id=main-area 인 div 요소 중 에서 id가 post-area인 div 요소를 post_area 변수에 담고 post_001의 title 값이 post_area에 있는지 확인 후 테스트를 통과 시킨다.
# 2.5 첫 번째 포스트의 작성자가 포스트 영역에 있다. (추후 구현)
# 2.6 첫 번째 포스트의 내용이 포스트 영역에 있다.
post_001의 content 값이 post_area에 있는지 확인 후 테스트를 통과 시킨다.
테스트로 수정할 내용 파악
이미 작성한 테스트 코드에서 id가 post-area인 div 요소를 찾을 수 없어 테스트가 당연하게도 실패하게 된다. 따라서 post_detail.html 을 수정해야 하는데 일단 다음편에서 다루도록 하겠다.
'Backend > Django + Bootstrap 개발 일지' 카테고리의 다른 글
16. 다대일 관계 구현(16 ~ 18) (작성자 추가) (0) | 2022.07.29 |
---|---|
15. 템플릿 모듈화 (0) | 2022.07.27 |
13. 테스트 주도 개발(TDD)을 이용한 블로그 기능 구현 목차 개요 (0) | 2022.07.23 |
12. 템플릿 파일에서 if문 사용, 다운로드 버튼 만들기, 템플릿 필터 사용 (0) | 2022.07.19 |
11. 미디어 파일 관리 (0) | 2022.07.17 |