diff --git a/app/apply/tests.py b/app/apply/tests.py index e69de29..4168093 100644 --- a/app/apply/tests.py +++ b/app/apply/tests.py @@ -0,0 +1,140 @@ +from datetime import timedelta +import datetime +from unittest.mock import patch +from django.test import TestCase +from django.contrib.auth.models import User +from django.urls import reverse +from user.models import Applicant +from django.utils import timezone +from rest_framework.test import APIClient +from apply.models import InterviewTime, RecruitProcess, Recruitment, Resume + + +class GetResultAPITest(TestCase): + def setUp(self): + # 'APPLY' 상태의 Recruitment 인스턴스 생성 + # start_time, document_deadline 등 필요한 필드 값 설정 + start_time = timezone.now().date() - timedelta(days=1) # 어제 시작 + document_deadline = timezone.now().date() + timedelta(days=1) # 내일 마감 + announce_middle_time = timezone.now() + timedelta(days=2) + interview_start_time = timezone.now().date() + timedelta(days=3) + interview_end_time = timezone.now().date() + timedelta(days=4) + announce_final_time = timezone.now() + timedelta(days=5) + + self.recruitment = Recruitment.objects.create( + year=2023, + term="Spring", + start_time=start_time, + document_deadline=document_deadline, + announce_middle_time=announce_middle_time, + interview_start_time=interview_start_time, + interview_end_time=interview_end_time, + announce_final_time=announce_final_time, + process=RecruitProcess.APPLY, + ) + self.client = APIClient() + self.user = Applicant.objects.create_user( + student_id="testuser", password="tmppassword" + ) + + self.interview = InterviewTime.objects.create( + time="2024-02-20 10:00:00", is_fixed=True + ) + # self.resume = Resume.objects.create( + # applicant=self.user, + # phone="01011112222", + # name="홍길동", + # semester=2, + # introduce="hi", + # motivate="hoho", + # to_do="todo", + # etc="etcc", + # ) # 적절한 필드값 전달해야 함 + + self.get_recuit_session_url = reverse("get_recuit_session") + self.get_interview_time_list_url = reverse("get_interview_time_list") + self.get_result_url = reverse("get_result") + self.resume_api_url = reverse("resume_api") + + def test_get_result_authenticated(self): + """ + 인증받은 결과이면 200을 반환하는지 확인합니다. + """ + self.client.force_login(self.user) + response = self.client.get(self.get_result_url) + self.assertEqual(response.status_code, 200) + + def test_get_result_unauthenticated(self): + """ + 인증받지 못한 결과이면 401을 반환하는지 확인합니다. + """ + response = self.client.get(self.get_result_url) + self.assertEqual(response.status_code, 401) + + def test_get_recruit_session_with_existing_session(self): + """ + 존재하는 채용 세션 데이터가 있으면 200 반환하는지 확인합니다. + """ + response = self.client.get(self.get_recuit_session_url) + self.assertEqual(response.status_code, 200) + + # 응답 데이터에는 채용 세션 정보가 포함되어야 합니다. + self.assertIn("year", response.data) + self.assertIn("term", response.data) + + def test_get_recruit_session_without_existing_session(self): + """ + 존재하지 않는 채용 세션 데이터면 404 반환하는지 확인합니다. + """ + response = self.client.get(self.get_recuit_session_url) + self.assertEqual(response.status_code, 404) + + @patch("apply.views.get_object_or_404") + @patch("apply.views.RecruitSerializer") + def test_get_recruit_session_check_process_called( + self, mock_serializer, mock_get_object_or_404 + ): + # Mock 객체를 설정합니다. + mock_recruitment = mock_get_object_or_404.return_value + mock_serializer_instance = mock_serializer.return_value + mock_serializer_instance.data = { + "year": 2024, + "term": "Spring", + "start_time": timezone.now().date() - timedelta(days=1), + "document_deadline": timezone.now().date() + timedelta(days=1), + "announce_middle_time": timezone.now() + timedelta(days=2), + "interview_start_time": timezone.now().date() + timedelta(days=3), + "interview_end_time": timezone.now().date() + timedelta(days=4), + "announce_final_time": timezone.now() + timedelta(days=5), + "process": RecruitProcess.CLOSE, + } + response = self.client.get(self.get_recuit_session_url) + + # RecruitSerializer와 get_object_or_404가 올바르게 호출되었는지 확인합니다. + mock_get_object_or_404.assert_called_once_with(Recruitment) + mock_recruitment.check_process.assert_called_once() + self.assertEqual(response.status_code, 200) + + # 응답 데이터에는 채용 세션 정보가 포함되어야 합니다. + self.assertIn("year", response.data) + self.assertIn("term", response.data) + + def test_get_interview_time_list_without_existing_data(self): + """ + 존재하는 인터뷰 시간 데이터가 없을 때 200 반환하는지 확인합니다. + """ + response = self.client.get(self.get_interview_time_list_url) + self.assertEqual(response.status_code, 200) + + # 응답 데이터가 비어 있어야 합니다. + self.assertEqual(len(response.data), 0) + + def test_get_interview_time_list_with_existing_data(self): + """ + 존재하는 인터뷰 시간 데이터가 있으면 200 반환하는지 확인합니다. + """ + response = self.client.get(self.get_interview_time_list_url) + self.assertEqual(response.status_code, 200) + + # Resume 관련해서는 하다가 "interview_time_choice"와 같은 + # 여러개 복수 선택 부분을 어떻게 테스트 해야 할지 모르겠어서 일단 보류했습니다... diff --git a/app/user/factories.py b/app/user/factories.py new file mode 100644 index 0000000..860203f --- /dev/null +++ b/app/user/factories.py @@ -0,0 +1,17 @@ +# user/factories.py + +import factory +from django.contrib.auth import get_user_model +from faker import Faker + +fake = Faker() +User = get_user_model() + + +class UserFactory(factory.django.DjangoModelFactory): + class Meta: + model = User + + # 지원자를 위한 필드 + student_id = factory.Sequence(lambda n: f"202415{n:02d}") + password = factory.PostGenerationMethodCall("set_password", "testpassword123") diff --git a/app/user/migrations/0003_alter_applicant_managers.py b/app/user/migrations/0003_alter_applicant_managers.py new file mode 100644 index 0000000..06c1784 --- /dev/null +++ b/app/user/migrations/0003_alter_applicant_managers.py @@ -0,0 +1,20 @@ +# Generated by Django 4.1.5 on 2024-02-14 22:57 + +from django.db import migrations +import user.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('user', '0002_alter_applicant_managers'), + ] + + operations = [ + migrations.AlterModelManagers( + name='applicant', + managers=[ + ('objects', user.models.UserManager()), + ], + ), + ] diff --git a/app/user/models.py b/app/user/models.py index 1ebdc22..0d51b01 100644 --- a/app/user/models.py +++ b/app/user/models.py @@ -38,7 +38,7 @@ class Applicant(AbstractUser): username = None USERNAME_FIELD = "student_id" REQUIRED_FIELDS = [] - object = UserManager() + objects = UserManager() def __str__(self): return self.student_id diff --git a/app/user/tests.py b/app/user/tests.py index 7ce503c..982e1a3 100644 --- a/app/user/tests.py +++ b/app/user/tests.py @@ -1,3 +1,128 @@ from django.test import TestCase +from django.urls import reverse +from rest_framework import status +from rest_framework.test import APITestCase +from user.models import Applicant, LabMaster +from django.contrib.auth import get_user_model +from django.utils import timezone +from datetime import timedelta +from apply.models import Recruitment, RecruitProcess +from .factories import UserFactory +from datetime import datetime -# Create your tests here. +User = get_user_model() + + +class UserTests(APITestCase): + def setUp(self): + super().setUp() + # 'APPLY' 상태의 Recruitment 인스턴스 생성 + # start_time, document_deadline 등 필요한 필드 값 설정 + start_time = timezone.now().date() - timedelta(days=1) # 어제 시작 + document_deadline = timezone.now().date() + timedelta(days=1) # 내일 마감 + announce_middle_time = timezone.now() + timedelta(days=2) + interview_start_time = timezone.now().date() + timedelta(days=3) + interview_end_time = timezone.now().date() + timedelta(days=4) + announce_final_time = timezone.now() + timedelta(days=5) + + self.recruitment = Recruitment.objects.create( + year=2023, + term="Spring", + start_time=start_time, + document_deadline=document_deadline, + announce_middle_time=announce_middle_time, + interview_start_time=interview_start_time, + interview_end_time=interview_end_time, + announce_final_time=announce_final_time, + process=RecruitProcess.APPLY, + ) + + self.check_applicant_url = reverse("check_applicant") + self.get_master_info_url = reverse("get_master_info") + + # UserFactory를 사용하여 테스트용 사용자 생성 + # 동적으로 student_id 생성 + unique_suffix = datetime.now().strftime("%Y%m%d%H%M%S%f") + dynamic_student_id = f"student_{unique_suffix}" + + # UserFactory를 사용하여 테스트용 사용자 생성 (동적 student_id 사용) + self.user = UserFactory(student_id=dynamic_student_id) + + def test_existing_applicant_login_success(self): + """ + 기존 지원자가 로그인 성공한 경우, 상태 코드 500을 반환하는지 확인합니다. + """ + Applicant.objects.create_user( + student_id="20240000", password="existingpassword" + ) + data = {"student_id": "20240000", "password": "existingpassword"} + response = self.client.post(self.check_applicant_url, data, format="json") + print(response) + self.assertEqual(response.status_code, 500) + + def test_new_applicant_with_apply_status(self): + """ + 신규 지원자가 'APPLY' 상태에서 지원할 때, 상태 코드 200을 반환하는지 확인합니다. + """ + data = {"student_id": "20241111", "password": "itsnewpassword"} + response = self.client.post(self.check_applicant_url, data, format="json") + print(response) + + self.assertEqual(response.status_code, 200) + + def test_new_applicant_not_apply_status(self): + """ + 신규 지원자가 'APPLY' 상태가 아닐 때 지원하려고 하면, 상태 코드 405를 반환하는지 확인합니다. + """ + # Recruitment 상태를 변경합니다. + self.recruitment.process = RecruitProcess.CLOSE + self.recruitment.save() + + data = {"student_id": "20242222", "password": "notapply"} + response = self.client.post(self.check_applicant_url, data, format="json") + print(response) + + self.assertEqual(response.status_code, 405) + + def test_applicant_exists_return_status_201(self): + """ + 사용자가 이미 존재하는 경우, 상태 코드 201을 반환하는지 확인합니다. + """ + # 미리 사용자 생성 + Applicant.objects.create_user(student_id="20243333", password="correcting") + data = {"student_id": "20243333", "password": "correcting"} + response = self.client.post(self.check_applicant_url, data, format="json") + print(response) + + self.assertEqual(response.status_code, 201) + + def test_missing_student_id_or_password_return_status_404(self): + """ + 이름과 패스워드를 추출하지 못한 경우, 상태 코드 404를 반환하는지 확인합니다. + """ + data = {} # student_id와 password를 전달하지 않음 + response = self.client.post(self.check_applicant_url, data, format="json") + print(response) + + self.assertEqual(response.status_code, 404) + + # def test_none_of_labmasters_not_active(self): + # """ + # 활성화된 랩장이 없는 경우, 상태 코드 404를 반환하는지 확인합니다. + # """ + # LabMaster.objects.create_master( + # name="김서강", + # email="sogangCom@gmail.com", + # phone="01012345678", + # is_active=False, + # ) + # data = { + # "name": "김서강", + # "email": "sogangCom@gmail.com", + # "phone": "01012345678", + # "is_active": False, + # } + # response = self.client.post(self.get_master_info_url, data, format="jason") + # print(response) + + # self.assertEqual(response.status_code, 404) diff --git a/app/user/urls.py b/app/user/urls.py index 083d5fc..60f78e3 100644 --- a/app/user/urls.py +++ b/app/user/urls.py @@ -2,6 +2,6 @@ from user.views import check_applicant, get_master_info urlpatterns = [ - path("check-id/", check_applicant), - path("master/", get_master_info), + path("check-id/", check_applicant, name="check_applicant"), + path("master/", get_master_info, name="get_master_info"), ] diff --git a/app/user/views.py b/app/user/views.py index 9702383..e1c3fe6 100644 --- a/app/user/views.py +++ b/app/user/views.py @@ -16,8 +16,8 @@ def check_applicant(request): try: # request에서 이름, 패스워드 추출 - student_id = request.data["student_id"] - password = request.data["password"] + student_id = request.data.get("student_id") + password = request.data.get("password") user = authenticate(username=student_id, password=password) if user is None: