def test_get_pearson_exam_status(self, profile_status, expected_status, make_exam_run, make_profile, make_auth, log_error_called, log_mock): """ test get_pearson_exam_status """ now = now_in_utc() exam_run = None if make_exam_run: exam_run = ExamRunFactory.create( course=self.course, date_first_eligible=now - timedelta(weeks=1), date_last_eligible=now + timedelta(weeks=1), ) if make_profile: ExamProfileFactory.create( profile=self.user.profile, status=profile_status, ) if make_auth: ExamAuthorizationFactory.create( user=self.user, status=ExamAuthorization.STATUS_SUCCESS, exam_run=exam_run, ) mmtrack = MMTrack( user=self.user, program=self.program, edx_user_data=self.cached_edx_user_data ) assert mmtrack.get_pearson_exam_status() == expected_status assert log_mock.error.called is log_error_called
def test_exam_authorization_attempts_consumed(self): """ test exam_authorization when user passed and paid, but used all their attempts """ create_order(self.user, self.course_run) mmtrack = get_mmtrack(self.user, self.program) self.assertTrue(mmtrack.has_paid(self.course_run.edx_course_key)) self.assertTrue( mmtrack.has_passed_course(self.course_run.edx_course_key)) old_run = ExamRunFactory.create(course=self.course_run.course) ExamAuthorizationFactory.create_batch( ATTEMPTS_PER_PAID_RUN, exam_run=old_run, user=mmtrack.user, course=self.course_run.course, exam_taken=True, ) assert ExamAuthorization.objects.filter( user=mmtrack.user, course=self.course_run.course).count() == 2 with self.assertRaises(ExamAuthorizationException): authorize_for_exam_run(self.user, self.course_run, self.exam_run) # assert no new authorizations got created assert ExamAuthorization.objects.filter( user=mmtrack.user, course=self.course_run.course).count() == 2
def test_get_exam_card_status_for_edx_exams(self, profile_status, expected_status, make_exam_run, make_profile, make_auth): """ test get_exam_card_status """ now = now_in_utc() exam_run = None if make_exam_run: exam_run = ExamRunFactory.create( course=self.course, date_first_eligible=now - timedelta(weeks=1), date_last_eligible=now + timedelta(weeks=1), ) if make_profile: ExamProfileFactory.create( profile=self.user.profile, status=profile_status, ) if make_auth: ExamAuthorizationFactory.create( user=self.user, status=ExamAuthorization.STATUS_SUCCESS, exam_run=exam_run, ) mmtrack = MMTrack( user=self.user, program=self.program, edx_user_data=self.cached_edx_user_data ) assert mmtrack.get_exam_card_status() == expected_status
def test_exam_authorization_attempts_consumed(self): """ test exam_authorization when user passed and paid, but used all their attempts """ create_order(self.user, self.course_run) mmtrack = get_mmtrack(self.user, self.program) self.assertTrue(mmtrack.has_paid(self.course_run.edx_course_key)) self.assertTrue(mmtrack.has_passed_course(self.course_run.edx_course_key)) old_run = ExamRunFactory.create(course=self.course_run.course) ExamAuthorizationFactory.create_batch( ATTEMPTS_PER_PAID_RUN, exam_run=old_run, user=mmtrack.user, course=self.course_run.course, exam_taken=True, ) assert ExamAuthorization.objects.filter( user=mmtrack.user, course=self.course_run.course ).count() == 2 with self.assertRaises(ExamAuthorizationException): authorize_for_exam_run(mmtrack, self.course_run, self.exam_run) # assert no new authorizations got created assert ExamAuthorization.objects.filter( user=mmtrack.user, course=self.course_run.course ).count() == 2
def two_no_show_exam_attempts(self): """Passed and later failed course, and two exam attempts""" self.make_fa_program_enrollment(FinancialAidStatus.AUTO_APPROVED) course = Course.objects.get(title='Digital Learning 200') course_run = CourseRunFactory(course=course, edx_course_key='course-passed') call_command( "alter_data", 'set_to_passed', '--username', 'staff', '--course-run-key', course_run.edx_course_key ) ExamProfileFactory.create(status='success', profile=self.user.profile) # run 1 exam_run = ExamRunFactory.create(course=course, eligibility_past=True, scheduling_past=True) ExamAuthorizationFactory.create( user=self.user, course=course, exam_run=exam_run, status='success', exam_taken=True, exam_no_show=True ) # run 2 exam_run = ExamRunFactory.create(course=course, eligibility_past=True, scheduling_past=True) ExamAuthorizationFactory.create( user=self.user, course=course, exam_run=exam_run, status='success', exam_taken=True, exam_no_show=True ) # another offered course_run = CourseRunFactory.create(course=course, edx_course_key='course-enrollable') call_command( "alter_data", 'set_to_offered', '--username', 'staff', '--course-run-key', course_run.edx_course_key ) course_run = CourseRunFactory.create(course=course, edx_course_key='course-failed') call_command( "alter_data", 'set_to_failed', '--username', 'staff', '--course-run-key', course_run.edx_course_key, '--audit', )
def test_process_result_exam(self): """Test that the authorization is marked as taken and a ProctoredExamGrade created""" exam_results = [] auths = [] # create a bunch of results that are passes for auth in ExamAuthorizationFactory.create_batch(5, course=self.course): exam_results.append( EXAMResultFactory.create( passed=True, client_candidate_id=auth.user.profile.student_id, client_authorization_id=auth.id, )) auths.append(auth) # create a bunch of results that are failed for auth in ExamAuthorizationFactory.create_batch(5, course=self.course): exam_results.append( EXAMResultFactory.create( failed=True, client_candidate_id=auth.user.profile.student_id, client_authorization_id=auth.id, )) auths.append(auth) grades = ProctoredExamGrade.objects.filter(course=self.course) assert grades.count() == 0 with patch('exams.pearson.download.EXAMReader.read', return_value=(exam_results, [])): assert self.processor.process_exam_file("/tmp/file.ext") == (True, []) for auth in auths: auth.refresh_from_db() assert auth.exam_no_show is False assert auth.exam_taken is True sorted_exam_results = sorted( exam_results, key=lambda result: result.client_authorization_id) sorted_grades = list(grades.order_by('client_authorization_id')) assert len(sorted_grades) == len(sorted_exam_results) for grade, exam_result in zip(sorted_grades, sorted_exam_results): assert grade.exam_date == exam_result.exam_date assert grade.passing_score == exam_result.passing_score assert grade.grade == exam_result.grade assert grade.score == exam_result.score assert grade.passed is (exam_result.grade == EXAM_GRADE_PASS) assert grade.percentage_grade == float(exam_result.score / 100.0) expected_data = dict( exam_result._asdict()) # _asdict() returns an OrderedDict expected_data['exam_date'] = expected_data['exam_date'].isoformat() assert grade.row_data == expected_data
def test_process_result_exam(self): """Test that the authorization is marked as taken and a ProctoredExamGrade created""" exam_results = [] auths = [] # create a bunch of results that are passes for auth in ExamAuthorizationFactory.create_batch(5, course=self.course): exam_results.append(EXAMResultFactory.create( passed=True, client_candidate_id=auth.user.profile.student_id, client_authorization_id=auth.id, )) auths.append(auth) # create a bunch of results that are failed for auth in ExamAuthorizationFactory.create_batch(5, course=self.course): exam_results.append(EXAMResultFactory.create( failed=True, client_candidate_id=auth.user.profile.student_id, client_authorization_id=auth.id, )) auths.append(auth) grades = ProctoredExamGrade.objects.filter(course=self.course) assert grades.count() == 0 with patch('exams.pearson.download.EXAMReader.read', return_value=(exam_results, [])): assert self.processor.process_exam_file("/tmp/file.ext") == (True, []) for auth in auths: auth.refresh_from_db() assert auth.exam_no_show is False assert auth.exam_taken is True sorted_exam_results = sorted(exam_results, key=lambda result: result.client_authorization_id) sorted_grades = list(grades.order_by('client_authorization_id')) assert len(sorted_grades) == len(sorted_exam_results) for grade, exam_result in zip(sorted_grades, sorted_exam_results): assert grade.exam_date == exam_result.exam_date assert grade.passing_score == exam_result.passing_score assert grade.grade == exam_result.grade assert grade.score == exam_result.score assert grade.passed is (exam_result.grade == EXAM_GRADE_PASS) assert grade.percentage_grade == float(exam_result.score / 100.0) expected_data = dict(exam_result._asdict()) # _asdict() returns an OrderedDict expected_data['exam_date'] = expected_data['exam_date'].isoformat() assert grade.row_data == expected_data
def test_write_ead_file(self): """ Tests that write_ead_file outputs correctly """ kwargs = { 'id': 143, 'operation': 'add', 'exam_run__exam_series_code': 'MM-DEDP', 'exam_run__date_first_eligible': date(2016, 5, 15), 'exam_run__date_last_eligible': date(2016, 10, 15), } with mute_signals(post_save): profile = ProfileFactory(id=14879) exam_auths = [ExamAuthorizationFactory.create(user=profile.user, **kwargs)] exam_auths[0].updated_on = FIXED_DATETIME self.ead_writer.write(self.tsv_file, exam_auths) assert self.tsv_rows[0] == ( "add\t143\t" "14879\tMM-DEDP\t\t" "\t2016/05/15\t2016/10/15\t" # accommodation blank intentionally "2016/05/15 15:02:55" )
def test_write_ead_file(self): """ Tests that write_ead_file outputs correctly """ kwargs = { 'id': 143, 'operation': 'add', 'exam_run__exam_series_code': 'MM-DEDP', 'exam_run__date_first_eligible': date(2016, 5, 15), 'exam_run__date_last_eligible': date(2016, 10, 15), } with mute_signals(post_save): profile = ProfileFactory(id=14879) exam_auths = [ ExamAuthorizationFactory.create(user=profile.user, **kwargs) ] exam_auths[0].updated_on = FIXED_DATETIME self.ead_writer.write(self.tsv_file, exam_auths) assert self.tsv_rows[0] == ( "add\t143\t" "14879\tMM-DEDP\t\t" "\t2016/05/15\t2016/10/15\t" # accommodation blank intentionally "2016/05/15 15:02:55")
def test_get_exam_card_status_eligible(self): """ test get_exam_card_status against valid eligibility dates """ ExamProfileFactory.create( profile=self.user.profile, status=ExamProfile.PROFILE_SUCCESS, ) now = datetime(2016, 3, 15, tzinfo=pytz.UTC) past = datetime(2016, 3, 10, tzinfo=pytz.UTC) future = datetime(2016, 3, 20, tzinfo=pytz.UTC) valid_dates = [ past - timedelta(days=1), past, now, future, ] invalid_dates = [ future + timedelta(days=1), ] ExamAuthorizationFactory.create( user=self.user, status=ExamAuthorization.STATUS_SUCCESS, exam_run__course=self.course, exam_run__date_first_eligible=past.date(), exam_run__date_last_eligible=future.date(), ) mmtrack = MMTrack( user=self.user, program=self.program, edx_user_data=self.cached_edx_user_data ) # should be considered schedulable if past <= datetime.now() <= future for now_value in valid_dates: mmtrack.now = now_value assert mmtrack.get_exam_card_status() == ExamProfile.PROFILE_SCHEDULABLE # not eligible for now_value in invalid_dates: mmtrack.now = now_value assert mmtrack.get_exam_card_status() == ExamProfile.PROFILE_SUCCESS
def test_update_authorizations_for_exam_run(self, is_future, is_past): """Tests update_authorizations_for_exam_run()""" exam_run = ExamRunFactory.create(scheduling_future=is_future, scheduling_past=is_past) taken_auth = ExamAuthorizationFactory.create( exam_run=exam_run, exam_taken=True, status=ExamAuthorization.STATUS_SUCCESS, operation=ExamAuthorization.OPERATION_ADD, ) pending_auth = ExamAuthorizationFactory.create( exam_run=exam_run, status=ExamAuthorization.STATUS_PENDING, operation=ExamAuthorization.OPERATION_ADD, ) nonpending_auths = [] for status in [ ExamAuthorization.STATUS_IN_PROGRESS, ExamAuthorization.STATUS_FAILED, ExamAuthorization.STATUS_SUCCESS, ]: nonpending_auths.append( ExamAuthorizationFactory.create( exam_run=exam_run, status=status, operation=ExamAuthorization.OPERATION_ADD, )) update_authorizations_for_exam_run(exam_run) taken_auth.refresh_from_db() assert taken_auth.status == ExamAuthorization.STATUS_SUCCESS assert taken_auth.operation == ExamAuthorization.OPERATION_ADD pending_auth.refresh_from_db() assert pending_auth.status == ExamAuthorization.STATUS_PENDING assert pending_auth.operation == ExamAuthorization.OPERATION_ADD for auth in nonpending_auths: auth.refresh_from_db() if is_past or is_future: assert auth.status != ExamAuthorization.STATUS_PENDING assert auth.operation == ExamAuthorization.OPERATION_ADD else: assert auth.status == ExamAuthorization.STATUS_PENDING assert auth.operation == ExamAuthorization.OPERATION_UPDATE
def test_get_pearson_exam_status_eligible(self): """ test get_pearson_exam_status against valid eligibility dates """ ExamProfileFactory.create( profile=self.user.profile, status=ExamProfile.PROFILE_SUCCESS, ) now = datetime(2016, 3, 15, tzinfo=pytz.UTC) past = datetime(2016, 3, 10, tzinfo=pytz.UTC) future = datetime(2016, 3, 20, tzinfo=pytz.UTC) valid_dates = [ past - timedelta(days=1), past, now, future, ] invalid_dates = [ future + timedelta(days=1), ] ExamAuthorizationFactory.create( user=self.user, status=ExamAuthorization.STATUS_SUCCESS, exam_run__course=self.course, exam_run__date_first_eligible=past.date(), exam_run__date_last_eligible=future.date(), ) mmtrack = MMTrack( user=self.user, program=self.program, edx_user_data=self.cached_edx_user_data ) # should be considered schedulable if past <= datetime.now() <= future for now_value in valid_dates: mmtrack.now = now_value assert mmtrack.get_pearson_exam_status() == ExamProfile.PROFILE_SCHEDULABLE # not eligible for now_value in invalid_dates: mmtrack.now = now_value assert mmtrack.get_pearson_exam_status() == ExamProfile.PROFILE_SUCCESS
def test_update_authorizations_for_exam_run(self, is_future, is_past): """Tests update_authorizations_for_exam_run()""" exam_run = ExamRunFactory.create(scheduling_future=is_future, scheduling_past=is_past) taken_auth = ExamAuthorizationFactory.create( exam_run=exam_run, exam_taken=True, status=ExamAuthorization.STATUS_SUCCESS, operation=ExamAuthorization.OPERATION_ADD, ) pending_auth = ExamAuthorizationFactory.create( exam_run=exam_run, status=ExamAuthorization.STATUS_PENDING, operation=ExamAuthorization.OPERATION_ADD, ) nonpending_auths = [] for status in [ ExamAuthorization.STATUS_IN_PROGRESS, ExamAuthorization.STATUS_FAILED, ExamAuthorization.STATUS_SUCCESS, ]: nonpending_auths.append(ExamAuthorizationFactory.create( exam_run=exam_run, status=status, operation=ExamAuthorization.OPERATION_ADD, )) update_authorizations_for_exam_run(exam_run) taken_auth.refresh_from_db() assert taken_auth.status == ExamAuthorization.STATUS_SUCCESS assert taken_auth.operation == ExamAuthorization.OPERATION_ADD pending_auth.refresh_from_db() assert pending_auth.status == ExamAuthorization.STATUS_PENDING assert pending_auth.operation == ExamAuthorization.OPERATION_ADD for auth in nonpending_auths: auth.refresh_from_db() if is_past or is_future: assert auth.status != ExamAuthorization.STATUS_PENDING assert auth.operation == ExamAuthorization.OPERATION_ADD else: assert auth.status == ExamAuthorization.STATUS_PENDING assert auth.operation == ExamAuthorization.OPERATION_UPDATE
def setUpTestData(cls): sftp = Mock() cls.processor = download.ArchivedResponseProcessor(sftp) cls.course = course = CourseFactory.create() cls.success_auths = ExamAuthorizationFactory.create_batch( 2, course=course) cls.failure_auths = ExamAuthorizationFactory.create_batch( 2, course=course) cls.success_results = ([ EACResult( client_authorization_id=auth.id, client_candidate_id=auth.user.profile.student_id, date=FIXED_DATETIME, status=EAC_SUCCESS_STATUS, message='', ) for auth in cls.success_auths ], []) cls.failed_results = ([ EACResult( client_authorization_id=cls.failure_auths[0].id, client_candidate_id=cls.failure_auths[0].user.profile. student_id, date=FIXED_DATETIME, status=EAC_FAILURE_STATUS, message='', ), EACResult( client_authorization_id=cls.failure_auths[1].id, client_candidate_id=cls.failure_auths[1].user.profile. student_id, date=FIXED_DATETIME, status=EAC_FAILURE_STATUS, message='wrong username', ), ], []) cls.all_results = ( cls.success_results[0] + cls.failed_results[0], cls.success_results[1] + cls.failed_results[1], )
def setUpTestData(cls): sftp = Mock() cls.processor = download.ArchivedResponseProcessor(sftp) cls.course = course = CourseFactory.create() cls.success_auths = ExamAuthorizationFactory.create_batch(2, course=course) cls.failure_auths = ExamAuthorizationFactory.create_batch(2, course=course) cls.success_results = ([ EACResult( client_authorization_id=auth.id, client_candidate_id=auth.user.profile.student_id, date=FIXED_DATETIME, status=EAC_SUCCESS_STATUS, message='', ) for auth in cls.success_auths ], []) cls.failed_results = ([ EACResult( client_authorization_id=cls.failure_auths[0].id, client_candidate_id=cls.failure_auths[0].user.profile.student_id, date=FIXED_DATETIME, status=EAC_FAILURE_STATUS, message='', ), EACResult( client_authorization_id=cls.failure_auths[1].id, client_candidate_id=cls.failure_auths[1].user.profile.student_id, date=FIXED_DATETIME, status=EAC_FAILURE_STATUS, message='wrong username', ), ], []) cls.all_results = ( cls.success_results[0] + cls.failed_results[0], cls.success_results[1] + cls.failed_results[1], )
def test_process_result_exam_no_show(self): """Test process_exam_file against no-show rows""" exam_auth = ExamAuthorizationFactory.create(course=self.course) exam_result = EXAMResultFactory.create( noshow=True, client_candidate_id=exam_auth.user.profile.student_id, client_authorization_id=exam_auth.id, ) with patch('exams.pearson.download.EXAMReader.read', return_value=([exam_result], [])): assert self.processor.process_exam_file("/tmp/file.ext") == (True, []) exam_auth.refresh_from_db() assert exam_auth.exam_no_show is True assert exam_auth.exam_taken is True assert not ProctoredExamGrade.objects.filter(course=self.course).exists()
def test_process_result_exam_no_show(self): """Test process_exam_file against no-show rows""" exam_auth = ExamAuthorizationFactory.create(course=self.course) exam_result = EXAMResultFactory.create( noshow=True, client_candidate_id=exam_auth.user.profile.student_id, client_authorization_id=exam_auth.id, ) with patch('exams.pearson.download.EXAMReader.read', return_value=([exam_result], [])): assert self.processor.process_exam_file("/tmp/file.ext") == (True, []) exam_auth.refresh_from_db() assert exam_auth.exam_no_show is True assert exam_auth.exam_taken is True assert not ProctoredExamGrade.objects.filter( course=self.course).exists()
def setUpTestData(cls): with mute_signals(post_save): cls.exam_auths = ExamAuthorizationFactory.create_batch( 10, status=ExamAuthorization.STATUS_PENDING)
def setUpTestData(cls): with mute_signals(post_save): cls.exam_auths = ExamAuthorizationFactory.create_batch(10, status=ExamAuthorization.STATUS_PENDING)
def create_exams(self, current, edx_passed, exam_passed, new_offering, can_schedule, future_exam, need_to_pay): """Create an exam and mark it and the related course as passed or not passed""" # pylint: disable-msg=too-many-arguments self.make_fa_program_enrollment(FinancialAidStatus.AUTO_APPROVED) course = Course.objects.get(title='Digital Learning 200') if current: course_run = CourseRunFactory(course=course) call_command( "alter_data", 'set_to_enrolled', '--username', 'staff', '--course-run-key', course_run.edx_course_key ) FinalGradeFactory.create( user=self.user, course_run=course_run, grade=0.8 if edx_passed else 0.2, passed=True ) else: if edx_passed: call_command( "alter_data", 'set_to_passed', '--username', 'staff', '--course-title', 'Digital Learning 200', '--grade', '75', ) else: call_command( "alter_data", 'set_to_failed', '--username', 'staff', '--course-title', 'Digital Learning 200', '--grade', '45', ) course_run = course.courserun_set.first() ExamProfileFactory.create(status='success', profile=self.user.profile) exam_run = ExamRunFactory.create(course=course, eligibility_past=True, scheduling_past=True) ExamAuthorizationFactory.create( user=self.user, course=course, exam_run=exam_run, status='success', exam_taken=True ) LineFactory.create( order__status=Order.FULFILLED, course_key=course_run ) ProctoredExamGradeFactory.create( user=self.user, course=course, exam_run=exam_run, passed=exam_passed, percentage_grade=0.8 if exam_passed else 0.3 ) if new_offering: CourseRunFactory.create(course=course) if can_schedule: exam_run = ExamRunFactory.create( scheduling_past=False, scheduling_future=False, authorized=True, course=course ) ExamAuthorizationFactory.create( user=self.user, course=course, exam_run=exam_run, status='success', ) if future_exam: ExamRunFactory.create( scheduling_past=False, scheduling_future=True, authorized=True, course=course ) if need_to_pay: exam_run = ExamRunFactory.create(course=course, eligibility_past=True, scheduling_past=True) ExamAuthorizationFactory.create( user=self.user, course=course, exam_run=exam_run, status='success', exam_taken=True ) ProctoredExamGradeFactory.create( user=self.user, course=course, exam_run=exam_run, passed=False, percentage_grade=0.3 )