인프런 커뮤니티 질문&답변

너굴너굴너구리님의 프로필 이미지
너굴너굴너구리

작성한 질문수

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

포스트 목록 페이지 수정하기 1

에러가 나는데 이유를 모르겠습니다

작성

·

1.2K

0

Traceback (most recent call last):

  File "F:\PG\Python\Do_it_DJango\do_it_DJango\blog\tests.py", line 69, in test_post_list_with_posts

    self.navbar_test(soup)

  File "F:\PG\Python\Do_it_DJango\do_it_DJango\blog\tests.py", line 53, in navbar_test

    self.assertEqual(home_btn.attrs['href'], '/')

AttributeError: 'NoneType' object has no attribute 'attrs'

======================================================================

ERROR: test_post_list_without_post (blog.tests.TestView)

----------------------------------------------------------------------

Traceback (most recent call last):

  File "F:\PG\Python\Do_it_DJango\do_it_DJango\blog\tests.py", line 99, in test_post_list_without_post

    self.navbar_test(soup)

  File "F:\PG\Python\Do_it_DJango\do_it_DJango\blog\tests.py", line 53, in navbar_test

    self.assertEqual(home_btn.attrs['href'], '/')

AttributeError: 'NoneType' object has no attribute 'attrs'

원래는 에러가 안났었는데 어느 순간 에러가 납니다.

어디가 잘못된걸까요...?

from django.test import TestCase, Client
from django.contrib.auth.models import User
from bs4 import BeautifulSoup
from .models import Post, Category


class TestView(TestCase):
    def setUp(self):
        self.client = Client()
        self.user_trump = User.objects.create_user(
            username='trump',
            password='fkqls1004!',
        )
        self.user_obama = User.objects.create_user(
            username='obama',
            password='fkqls1234!',
        )

        self.category_programming = Category.objects.create(
            name='programming', slug='programming'
        )
        self.category_music = Category.objects.create(
            name='music', slug='music'
        )

        self.post_001 = Post.objects.create(
            title='첫 번째 포스트 입니다.',
            content='Hello, World. We are the World',
            category=self.category_programming,
            author=self.user_trump,
        )
        self.post_002 = Post.objects.create(
            title='두 번째 포스트 입니다.',
            content='저는 떡볶이를 좋아합니다.',
            category=self.category_music,
            author=self.user_obama,
        )
        self.post_003 = Post.objects.create(
            title='세 번째 포스트 입니다.',
            content='카테고리가 없을 수도 있죠',
            author=self.user_obama,
        )

    def navbar_test(self, soup):
        navbar = soup.nav
        self.assertIn('Blog', navbar.text)
        self.assertIn('About me', navbar.text)

        logo_btn = navbar.find('a', text='Do It Django')
        self.assertEqual(logo_btn.attrs['href'], '/')

        home_btn = navbar.find('a', text='Home')
        self.assertEqual(home_btn.attrs['href'], '/')

        blog_btn = navbar.find('a', text='Blog')
        self.assertEqual(blog_btn.attrs['href'], '/blog/')

        about_me_btn = navbar.find('a', text='About me')
        self.assertEqual(about_me_btn.attrs['href'], '/about_me/')

    def category_card_test(self, soup):
        categories_card = soup.find('div', id='categories-card')
        self.assertIn('Categories', categories_card.text)
        self.assertIn(
            f'{self.category_programming} ({self.category_programming.post_set.count()})',
            categories_card.text
        )
        self.assertIn(
            f'{self.category_music} ({self.category_music.post_set.count()})',
            categories_card.text
        )
        self.assertIn(
            f'미분류 ({Post.objects.filter(category=None).count()})',
            categories_card.text
        )

    def test_post_list_with_posts(self):
        self.assertEqual(Post.objects.count(), 3)

        response = self.client.get('/blog/')
        self.assertEqual(response.status_code, 200)

        soup = BeautifulSoup(response.content, 'html.parser')
        self.assertIn('Blog', soup.title.text)
        self.navbar_test(soup)
        self.category_card_test(soup)

        main_area = soup.find('div', id='main-area')
        # 3.4 "아직 게시물이 없습니다." 라는 문구가 없어야 한다.
        self.assertNotIn('아직 게시물이 없습니다.', main_area.text)

        post_001_card = main_area.find('div', id='post-1')
        self.assertIn(self.post_001.title, post_001_card.text)
        self.assertIn(self.post_001.category.name, post_001_card.text)

        post_002_card = main_area.find('div', id='post-2')
        self.assertIn(self.post_002.title, post_002_card.text)
        self.assertIn(self.post_002.category.name, post_002_card.text)

        post_003_card = main_area.find('div', id='post-3')
        self.assertIn(self.post_003.title, post_003_card.text)
        self.assertIn('미분류', post_003_card.text)

        self.assertIn(self.post_001.author.username.upper(), main_area.text)
        self.assertIn(self.post_002.author.username.upper(), main_area.text)

    def test_post_list_without_post(self):
        Post.objects.all().delete()
        self.assertEqual(Post.objects.count(), 0)

        response = self.client.get('/blog/')
        self.assertEqual(response.status_code, 200)

        soup = BeautifulSoup(response.content, 'html.parser')
        self.assertIn('Blog', soup.title.text)
        self.navbar_test(soup)

        main_area = soup.find('div', id='main-area')
        self.assertIn('아직 게시물이 없습니다.', main_area.text)

    def test_post_detail(self):
        self.assertEqual(Post.objects.count(), 3)
        # 1.2 그 포스트의 url은 '/blog/1/' 이다.
        self.assertEqual(self.post_001.get_absolute_url(), '/blog/1/')

        # 2. 첫 번째 포스트의 상세 피이지 테스트
        # 2.1 첫 번째 포스트의 url로 접근하면 정상적으로 response가 온다(status code: 200).
        response = self.client.get(self.post_001.get_absolute_url())
        self.assertEqual(response.status_code, 200)

        soup = BeautifulSoup(response.content, 'html.parser')
        # 2.2 포스트 목록 페이지와 똑같은 네비게이션 바가 있다.
        navbar = soup.nav
        self.assertIn('Blog', navbar.text)
        self.assertIn('About me', navbar.text)
        # 2.3 첫 번째 포스트의 제목이 웹 브라우저 웹 타이틀에 들어 있다.
        self.assertIn(self.post_001.title, soup.title.text)
        # 2.4 첫 번째 포스트의 제목이 포스트 영역에 있다.
        main_area = soup.find('div', id='main-area')
        post_area = main_area.find('div', id='post-area')
        self.assertIn(self.post_001.title, post_area.text)
        # 2.5 첫 번째 포스트의 작성자(author)가 포스트 영역에 있다(아직 구현할 수 없음).
        self.assertIn(self.user_trump.username.upper(), post_area.text)
        # 2.6 첫 번째 포스트의 내용(content)이 포스트 영역에 있다.
        self.assertIn(self.post_001.content, post_area.text)

답변 1

0

SungYong Lee님의 프로필 이미지
SungYong Lee
지식공유자

home_btn을 찾지 못해서 발생하는 에러 같아요. 

home_btn이 <a>태그이고, 그 안에 문자가 Home이라고 되어 있는걸 찾으라는 뜻인데, html에 그렇게 되어 있는지 확인이 필요해보입니다. 

html파일에서 home_btn을 찾지 못해서 None으로 되어 있고, 거기에 당연히 attr이 없는거겠죠? 

너굴너굴너구리님의 프로필 이미지
너굴너굴너구리

작성한 질문수

질문하기