EDUCATOR-4684 | The instructor course grade report should take subsection grade overrides into account.

This commit is contained in:
Alex Dusenbery
2019-09-27 09:41:41 -04:00
committed by Alex Dusenbery
parent 7c6c166e73
commit bf77974297
2 changed files with 49 additions and 8 deletions

View File

@@ -358,7 +358,6 @@ class CourseGradeReport(object):
"""
grade_results = []
for _, assignment_info in six.iteritems(context.graded_assignments):
subsection_grades, subsection_grades_results = self._user_subsection_grades(
course_grade,
assignment_info['subsection_headers'],
@@ -380,7 +379,7 @@ class CourseGradeReport(object):
grade_results = []
for subsection_location in subsection_headers:
subsection_grade = course_grade.subsection_grade(subsection_location)
if subsection_grade.attempted_graded:
if subsection_grade.attempted_graded or subsection_grade.override:
grade_result = subsection_grade.percent_graded
else:
grade_result = u'Not Attempted'

View File

@@ -35,7 +35,12 @@ from course_modes.tests.factories import CourseModeFactory
from lms.djangoapps.courseware.tests.factories import InstructorFactory
from lms.djangoapps.certificates.models import CertificateStatuses, GeneratedCertificate
from lms.djangoapps.certificates.tests.factories import CertificateWhitelistFactory, GeneratedCertificateFactory
from lms.djangoapps.grades.models import PersistentCourseGrade
from lms.djangoapps.grades.course_data import CourseData
from lms.djangoapps.grades.models import (
PersistentCourseGrade,
PersistentSubsectionGradeOverride,
)
from lms.djangoapps.grades.subsection_grade import CreateSubsectionGrade
from lms.djangoapps.grades.transformer import GradesTransformer
from lms.djangoapps.instructor_analytics.basic import UNAVAILABLE, list_problem_responses
from lms.djangoapps.instructor_task.tasks_helper.certs import generate_students_certificates
@@ -129,7 +134,7 @@ class TestInstructorGradeReport(InstructorGradeReportTestCase):
for i, email in enumerate(emails):
self.create_student('student{0}'.format(i), email)
self.current_task = Mock()
self.current_task = Mock() # pylint: disable=attribute-defined-outside-init
self.current_task.update_state = Mock()
with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task') as mock_current_task:
mock_current_task.return_value = self.current_task
@@ -424,7 +429,7 @@ class TestInstructorGradeReport(InstructorGradeReportTestCase):
self.create_student('active-student', 'active@example.com')
self.create_student('inactive-student', 'inactive@example.com', enrollment_active=False)
self.current_task = Mock()
self.current_task = Mock() # pylint: disable=attribute-defined-outside-init
self.current_task.update_state = Mock()
with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task') as mock_current_task:
@@ -1497,7 +1502,7 @@ class TestStudentReport(TestReportMixin, InstructorTaskCourseTestCase):
for i, student in enumerate(students):
self.create_student(username=student, email='student{0}@example.com'.format(i))
self.current_task = Mock()
self.current_task = Mock() # pylint: disable=attribute-defined-outside-init
self.current_task.update_state = Mock()
task_input = {
'features': [
@@ -1628,7 +1633,7 @@ class MockDefaultStorage(object):
def open(self, file_name):
"""Mock out DefaultStorage.open with standard python open"""
return open(file_name)
return open(file_name) # pylint: disable=open-builtin
@patch('lms.djangoapps.instructor_task.tasks_helper.misc.DefaultStorage', new=MockDefaultStorage)
@@ -1972,6 +1977,43 @@ class TestGradeReport(TestReportMixin, InstructorTaskModuleTestCase):
ignore_other_columns=True,
)
def test_grade_report_with_overrides(self):
course_data = CourseData(self.student, course=self.course)
subsection_grade = CreateSubsectionGrade(self.unattempted_section, course_data.structure, {}, {})
grade_model = subsection_grade.update_or_create_model(self.student, force_update_subsections=True)
_ = PersistentSubsectionGradeOverride.update_or_create_override(
self.student,
grade_model,
earned_graded_override=2.0,
)
self.addCleanup(grade_model.delete)
self.submit_student_answer(self.student.username, u'Problem1', ['Option 1'])
with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'):
result = CourseGradeReport.generate(None, None, self.course.id, None, 'graded')
self.assertDictContainsSubset(
{'action_name': 'graded', 'attempted': 1, 'succeeded': 1, 'failed': 0},
result,
)
self.verify_rows_in_csv(
[
{
u'Student ID': text_type(self.student.id),
u'Email': self.student.email,
u'Username': self.student.username,
u'Grade': '0.38',
u'Homework 1: Subsection': '0.5',
u'Homework 2: Unattempted': '1.0',
u'Homework 3: Empty': 'Not Attempted',
u'Homework (Avg)': text_type(3.0 / 6.0),
},
],
ignore_other_columns=True,
)
@ddt.data(True, False)
def test_fast_generation(self, create_non_zero_grade):
if create_non_zero_grade:
@@ -2036,7 +2078,7 @@ class TestGradeReportEnrollmentAndCertificateInfo(TestReportMixin, InstructorTas
"""
user_profile = UserFactory(username=user.username, email=user.email).profile
user_profile.allow_certificate = not is_embargoed
user_profile.save()
user_profile.save() # pylint: disable=no-member
def _verify_csv_data(self, username, expected_data):
"""