diff --git a/lms/djangoapps/support/tasks.py b/lms/djangoapps/support/tasks.py index 29b1ed7d6a..82140124ea 100644 --- a/lms/djangoapps/support/tasks.py +++ b/lms/djangoapps/support/tasks.py @@ -3,7 +3,6 @@ from datetime import datetime import logging from celery import shared_task -from submissions import api as sub_api from edx_django_utils.monitoring import set_code_owner_attribute from common.djangoapps.student.models.course_enrollment import CourseEnrollment @@ -17,7 +16,7 @@ from lms.djangoapps.support.models import CourseResetAudit log = logging.getLogger(__name__) -def update_audit_fields(audit_instance, status, completed_at=False): +def update_audit_status(audit_instance, status, completed_at=False): audit_instance.status = status if completed_at: audit_instance.completed_at = datetime.now() @@ -39,7 +38,7 @@ def reset_student_course(course_id, learner_email, reset_by_user_email): ) course_overview = enrollment.course_overview course_reset_audit = CourseResetAudit.objects.filter(course_enrollment=enrollment).first() - update_audit_fields(course_reset_audit, CourseResetAudit.CourseResetStatus.IN_PROGRESS) + update_audit_status(course_reset_audit, CourseResetAudit.CourseResetStatus.IN_PROGRESS) try: course = get_course(course_overview.id, depth=4) @@ -49,7 +48,7 @@ def reset_student_course(course_id, learner_email, reset_by_user_email): reset_student_attempts(course.id, user, data.scope_ids.usage_id, reset_by_user, True) except StudentModule.DoesNotExist: pass - update_audit_fields(course_reset_audit, CourseResetAudit.CourseResetStatus.COMPLETE, True) - except sub_api.SubmissionError as e: + update_audit_status(course_reset_audit, CourseResetAudit.CourseResetStatus.COMPLETE, True) + except Exception as e: # pylint: disable=broad-except logging.exception(e) - update_audit_fields(course_reset_audit, CourseResetAudit.CourseResetStatus.FAILED) + update_audit_status(course_reset_audit, CourseResetAudit.CourseResetStatus.FAILED) diff --git a/lms/djangoapps/support/tests/test_tasks.py b/lms/djangoapps/support/tests/test_tasks.py index 4c9f3eb4a0..2b03bd2028 100644 --- a/lms/djangoapps/support/tests/test_tasks.py +++ b/lms/djangoapps/support/tests/test_tasks.py @@ -3,22 +3,20 @@ Unit tests for reset_student_course task """ -from datetime import datetime, timedelta -from pytz import UTC - -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase - -from xmodule.modulestore.tests.factories import CourseFactory +from unittest.mock import patch, Mock +from xmodule.modulestore.tests.factories import BlockFactory +from lms.djangoapps.courseware.tests.test_submitting_problems import TestSubmittingProblems +from lms.djangoapps.courseware.models import StudentModule from lms.djangoapps.support.tasks import reset_student_course from lms.djangoapps.support.tests.factories import CourseResetAuditFactory, CourseResetCourseOptInFactory from lms.djangoapps.support.models import CourseResetAudit -from openedx.core.djangoapps.content.course_overviews.models import CourseOverview +from common.djangoapps.student.models.course_enrollment import CourseEnrollment from common.djangoapps.student.roles import SupportStaffRole -from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory +from common.djangoapps.student.tests.factories import UserFactory -class ResetStudentCourse(ModuleStoreTestCase): +class ResetStudentCourse(TestSubmittingProblems): """ Test expire_waiting_enrollments task """ USERNAME = "support" EMAIL = "support@example.com" @@ -31,16 +29,8 @@ class ResetStudentCourse(ModuleStoreTestCase): super().setUp() self.user = UserFactory(username=self.USERNAME, email=self.EMAIL, password=self.PASSWORD) SupportStaffRole().add_users(self.user) - self.now = datetime.now().replace(tzinfo=UTC) - - self.course = CourseFactory.create( - start=self.now - timedelta(days=90), - end=self.now + timedelta(days=90), - ) self.course_id = str(self.course.id) - self.course_overview = CourseOverview.get_from_id(self.course.id) - self.learner = UserFactory.create() - self.enrollment = CourseEnrollmentFactory.create(user=self.learner, course_id=self.course.id) + self.enrollment = CourseEnrollment.objects.filter(user=self.student_user, course_id=self.course.id).first() self.opt_in = CourseResetCourseOptInFactory.create(course_id=self.course.id) self.audit = CourseResetAuditFactory.create( course=self.opt_in, @@ -49,7 +39,61 @@ class ResetStudentCourse(ModuleStoreTestCase): status=CourseResetAudit.CourseResetStatus.FAILED ) + def basic_setup(self, late=False, reset=False, showanswer=False): + """ + Set up a simple course for testing basic grading functionality. + """ + grading_policy = { + "GRADER": [{ + "type": "Homework", + "min_count": 1, + "drop_count": 0, + "short_label": "HW", + "weight": 1.0 + }], + "GRADE_CUTOFFS": { + 'A': .9, + 'B': .33 + } + } + self.add_grading_policy(grading_policy) + + # set up a simple course with four problems + homework = self.add_graded_section_to_course('homework', late=late, reset=reset, showanswer=showanswer) + vertical = BlockFactory.create( + parent_location=homework.location, + category='vertical', + display_name='Subsection 1', + ) + self.add_dropdown_to_section(vertical.location, 'p1', 1) + self.add_dropdown_to_section(vertical.location, 'p2', 1) + self.add_dropdown_to_section(vertical.location, 'p3', 1) + + self.refresh_course() + def test_reset_student_course(self): - reset_student_course(self.course_id, self.learner.email, self.user.email) + self.basic_setup() + reset_student_course(self.course_id, self.student_user.email, self.user.email) course_reset_audit = CourseResetAudit.objects.filter(course_enrollment=self.enrollment).first() self.assertTrue(course_reset_audit.completed_at) + self.assertEqual(course_reset_audit.status, CourseResetAudit.CourseResetStatus.COMPLETE) + + def test_reset_student_course_student_module_not_found(self): + with patch( + 'lms.djangoapps.support.tasks.reset_student_attempts', + Mock(side_effect=StudentModule.DoesNotExist('An error occurred')) + ): + reset_student_course(self.course_id, self.student_user.email, self.user.email) + course_reset_audit = CourseResetAudit.objects.filter(course_enrollment=self.enrollment).first() + self.assertTrue(course_reset_audit.completed_at) + self.assertEqual(course_reset_audit.status, CourseResetAudit.CourseResetStatus.COMPLETE) + + def test_reset_student_course_fail(self): + with patch( + 'lms.djangoapps.support.tasks.SubmissionHistoryView.get_problem_blocks', + Mock(side_effect=Exception('An error occurred')) + ): + reset_student_course(self.course_id, self.student_user.email, self.user.email) + course_reset_audit = CourseResetAudit.objects.filter(course_enrollment=self.enrollment).first() + self.assertFalse(course_reset_audit.completed_at) + self.assertEqual(course_reset_audit.status, CourseResetAudit.CourseResetStatus.FAILED)