SW 프로젝트 13주차 활동 일지

고태경·2023년 11월 21일

SW 프로젝트

목록 보기
8/10

1주차 OT 8/30
2주차 주제 선정 (타임캡슐) 9/6
3주차 주제 변경 (냉장고 관리 웹사이트) 9/13
4주차 주제 결정 및 plan A, B 설정 9/20
5주차 프로젝트 첫 번째 중간 보고 9/27 (9/21~9/26)
6주차 프로젝트 두 번째 중간 보고 9/27 (9/27~10/3)
7주차 프로젝트 계획 보고서 발표
8주차 시험 주 (자습)
9주차 프로젝트 세 번째 중간 보고
10주차 프로젝트 네 번째 중간 보고(~10/31)
11주차 프로젝트 다섯 번째 중간 보고(~11/07)
12주차 중간점검 (시연)

13주차 프로젝트 여섯 번째 중간 보고 (~11/21)

이번 주차에 한 것

1. 자동 메일 전송 코드에 대한 TDD 진행

TDD란 테스트 주도 방식으로 실제로 사이트에서 실행해보지 않아도 코드를 통한 시연이 가능하다. 나는 설정한 시간에 따른 자동 메일 전송을 수행할 때 직접 해당 시간이 될 때까지 기다려야 했기 때문에 TDD 방식이 필요했다.

# calender/tests.py


# from django.test import TestCase
from .views import send_email_function
from unittest.mock import patch, MagicMock

# calender/tests.py

from django.test import TestCase, SimpleTestCase
from django.contrib.auth.models import User
from django.test import Client

# 로그인한 사용자의 이메일을 가져오는지 확인
class UserEmailTest(TestCase):
    def setUp(self):
        # 테스트 사용자 생성
        self.user = User.objects.create_user(username='testuser', email='test@example.com', password='12345')
        self.client = Client()

    def test_user_email(self):
        # 사용자 로그인
        self.client.login(username='testuser', password='12345')

        # 로그인한 사용자의 이메일 주소 가져오기
        user_email = self.user.email

        # 이메일 주소 확인
        self.assertEqual(user_email, 'test@example.com')

# python manage.py test calender.tests.UserEmailTest

# 자동 메일 전송이 되는지 확인
class EmailTest(SimpleTestCase):
    @patch('calender.views.smtplib.SMTP')
    def test_send_email_function(self, mock_smtp):
        # Mock 객체 설정
        mock_server = MagicMock()
        mock_smtp.return_value.__enter__.return_value = mock_server

        # 함수 호출
        email = 'taegeong@naver.com'
        name = '테스트 재료'
        date = '2023-11-25 00:00:00'
        send_email_function(email, name, date)

        # 함수가 호출되었는지 검증
        mock_server.send_message.assert_called()

        # send_message가 호출된 인자 검증
        args, kwargs = mock_server.send_message.call_args
        sent_message = args[0]

        # 이메일 본문 디코딩
        payload = sent_message.get_payload(decode=True)
        decoded_payload = payload.decode('utf-8')

        self.assertIn(email, sent_message['To'])
        self.assertIn(name, decoded_payload)
        self.assertIn(date, decoded_payload)

결론 : test DB가 제대로 생성이 안돼서 접었어요..
처음에는 fk가 안 만들어졌었는데 다시 db 만들고 부터는 제대로 db를 못 만드네요..
아마 제가 수정하면 안되는 장고 설정 파일을 만져서 그런 것 같습니다..

그래서 다른 파이썬 파일을 통해 테스트 하는 것으로 변경함
자동 메일 전송은 정상적으로 작동함을 확인하였음

2. 웹 크롤링 내용 메일 내용으로 추가

# 웹 스크래핑을 통해 레시피 링크를 얻는 함수
def get_recipe_links(food):
    base_url = "https://search.naver.com/search.naver?where=view&sm=tab_jum&query="
    end = "+요리+레시피"
    search_url = base_url + food + end
    r = requests.get(search_url)
    soup = BeautifulSoup(r.text, 'html.parser')

    cook_name_and_link = soup.select(".title_link._cross_trigger")
    links = []
    for e, item in enumerate(cook_name_and_link, 1):
        if e > 10:
            break
        title = item.text
        link = item.get('href')
        links.append(f'<li><a href="{link}">{title}</a></li>')
    return '<ul>' + ''.join(links) + '</ul>'


# 이메일 전송 함수
def send_email_function(email, name, date):    # 이메일 서버 연결 정보
    smtp_server = 'smtp.gmail.com'  # SMTP 서버 주소 (Gmail의 경우)
    smtp_port = 587  # SMTP 서버 포트 (Gmail의 TLS 포트), 465와의 차이는?

    date_only = datetime.strptime(date, "%Y-%m-%d %H:%M:%S").strftime("%Y-%m-%d")
    recipe_links = get_recipe_links(name)  # 레시피 링크 가져오기

    # 이메일 메세지 설정
    subject = f' 장고 : {name}의 소비기한이 3일 남았습니다!'  # 이메일 제목
    body = f'{name}의 소비기한이 3일 남았습니다!<br>(소비기한: {date_only})<br><br>{recipe_links}'
    sender = 'sw.project.django@gmail.com'  # 발신자 이메일 주소
    # receiver = 'taegeong@naver.com'  # 수신자 이메일 주소

    # 이메일 메세지 생성
    msg = MIMEMultipart()
    msg['Subject'] = subject  # 이메일 제목 설정
    msg['From'] = sender  # 발신자 이메일 주소 설정
    msg['To'] = email  # 수신자 이메일 주소 설정
    msg.attach(MIMEText(body, 'html'))

    # 이메일 발송
    with smtplib.SMTP(smtp_server, smtp_port) as server:  # SMTP 서버 연결
        server.starttls()  # TLS(전송 계층 보안) 시작
        server.login(settings.EMAIL_HOST_USER, settings.EMAIL_HOST_PASSWORD)  # 이메일 계정 로그인
        server.send_message(msg)  # 메시지 발송


# 이메일 스케줄링 함수
def schedule_email(user_email, title, event_date):
    # 날짜 3일 전 계산
    send_date = datetime.strptime(event_date, "%Y-%m-%d %H:%M:%S") - timedelta(days=3)
    timezone = pytz.timezone('Asia/Seoul')

    scheduler = BackgroundScheduler()
    scheduler.add_job(
        send_email_function,
        'date',
        run_date=send_date.replace(tzinfo=timezone),
        args=[user_email, title, event_date]
    )
    scheduler.start()


@login_required
def add_event(request):
    # 요청으로부터 데이터 가져오기
    title = request.GET.get("title", None)
    start = request.GET.get("start", None)
    end = request.GET.get("end", None)
    f_category = request.GET.get("f_category", None)  # f_category 값 가져오기

    # 새로운 이벤트 객체 생성 및 저장
    event = Events(
        name=str(title),
        start=start,
        end=end,
        f_category=f_category,  # 카테고리 설정
        user=request.user
    )
    event.save()

    # 사용자 이메일과 이벤트 날짜 가져오기
    user_email = request.user.email
    event_date = start

    # 이메일 스케줄링
    schedule_email(user_email, title, event_date)

    # JSON 응답 반환
    data = {'id': event.id}  # 생성된 이벤트의 ID를 응답 데이터에 포함
    return JsonResponse(data)

ISSUE

1. TDD 방식 실패.. (DB 사용 부분)

test DB가 제대로 만들어지지 않음..

profile
컴퓨터정보과

0개의 댓글