diff --git a/lms/djangoapps/instructor_task/tasks_helper.py b/lms/djangoapps/instructor_task/tasks_helper.py index 8e54d77fecca04e17bcc08c820d612e3fa0722bf..8287432d70707f19aaa1c4f26ee8bbe9e28fe538 100644 --- a/lms/djangoapps/instructor_task/tasks_helper.py +++ b/lms/djangoapps/instructor_task/tasks_helper.py @@ -836,7 +836,7 @@ def _order_problems(blocks): an OrderedDict that maps a problem id to its headers in the final report. """ problems = OrderedDict() - assignments = dict() + assignments = OrderedDict() # First, sort out all the blocks into their correct assignments and all the # assignments into their correct types. for block in blocks: diff --git a/lms/djangoapps/instructor_task/tests/test_base.py b/lms/djangoapps/instructor_task/tests/test_base.py index 6b9eb872f0f7cc0473751410af3c797165d06fd1..4561d3dcceb4f915b2f5b714f3ff2c715bbaf85b 100644 --- a/lms/djangoapps/instructor_task/tests/test_base.py +++ b/lms/djangoapps/instructor_task/tests/test_base.py @@ -330,3 +330,13 @@ class TestReportMixin(object): self.assertEqual(csv_rows, expected_rows) else: self.assertItemsEqual(csv_rows, expected_rows) + + def get_csv_row_with_headers(self): + """ + Helper function to return list with the column names from the CSV file (the first row) + """ + report_store = ReportStore.from_config(config_name='GRADES_DOWNLOAD') + report_csv_filename = report_store.links_for(self.course.id)[0][0] + with open(report_store.path_to(self.course.id, report_csv_filename)) as csv_file: + rows = unicodecsv.reader(csv_file, encoding='utf-8') + return rows.next() diff --git a/lms/djangoapps/instructor_task/tests/test_tasks_helper.py b/lms/djangoapps/instructor_task/tests/test_tasks_helper.py index 1d05a83dec863f333f29f009c77eaf04107c0c8b..4fa14d321586df52b3b1eb2d61c691e85914d497 100644 --- a/lms/djangoapps/instructor_task/tests/test_tasks_helper.py +++ b/lms/djangoapps/instructor_task/tests/test_tasks_helper.py @@ -17,7 +17,6 @@ import ddt from freezegun import freeze_time from mock import Mock, patch import tempfile -import json from openedx.core.djangoapps.course_groups import cohorts import unicodecsv from django.core.urlresolvers import reverse @@ -34,11 +33,7 @@ from django.conf import settings from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from pytz import UTC -from xmodule.modulestore.tests.factories import CourseFactory -from student.tests.factories import UserFactory -from student.models import CourseEnrollment -from xmodule.partitions.partitions import Group, UserPartition - +from student.tests.factories import CourseEnrollmentFactory, UserFactory from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory import openedx.core.djangoapps.user_api.course_tag.api as course_tag_api from openedx.core.djangoapps.user_api.partition_schemes import RandomUserPartitionScheme @@ -734,6 +729,71 @@ class TestProblemReportSplitTestContent(TestReportMixin, TestConditionalContent, )) ]) + def test_problem_grade_report_valid_columns_order(self): + """ + Test that in the CSV grade report columns are placed in the proper order + """ + grader_num = 7 + + self.course = CourseFactory.create( + grading_policy={ + "GRADER": [{ + "type": "Homework %d" % i, + "min_count": 1, + "drop_count": 0, + "short_label": "HW %d" % i, + "weight": 1.0 + } for i in xrange(1, grader_num)] + } + ) + + # Create users + self.student_a = UserFactory.create(username='student_a', email='student_a@example.com') + CourseEnrollmentFactory.create(user=self.student_a, course_id=self.course.id) + self.student_b = UserFactory.create(username='student_b', email='student_b@example.com') + CourseEnrollmentFactory.create(user=self.student_b, course_id=self.course.id) + + problem_vertical_list = [] + + for i in xrange(1, grader_num): + chapter_name = 'Chapter %d' % i + problem_section_name = 'Problem section %d' % i + problem_section_format = 'Homework %d' % i + problem_vertical_name = 'Problem Unit %d' % i + + chapter = ItemFactory.create(parent_location=self.course.location, + display_name=chapter_name) + + # Add a sequence to the course to which the problems can be added + problem_section = ItemFactory.create(parent_location=chapter.location, + category='sequential', + metadata={'graded': True, + 'format': problem_section_format}, + display_name=problem_section_name) + + # Create a vertical + problem_vertical = ItemFactory.create( + parent_location=problem_section.location, + category='vertical', + display_name=problem_vertical_name + ) + problem_vertical_list.append(problem_vertical) + + problem_names = [] + for i in xrange(1, grader_num): + problem_url = 'test_problem_%d' % i + self.define_option_problem(problem_url, parent=problem_vertical_list[i - 1]) + title = 'Homework %d 1: Problem section %d - %s' % (i, i, problem_url) + problem_names.append(title) + + header_row = [u'Student ID', u'Email', u'Username', u'Final Grade'] + for problem in problem_names: + header_row += [problem + ' (Earned)', problem + ' (Possible)'] + + with patch('instructor_task.tasks_helper._get_current_task'): + upload_problem_grade_report(None, None, self.course.id, None, 'graded') + self.assertEquals(self.get_csv_row_with_headers(), header_row) + class TestProblemReportCohortedContent(TestReportMixin, ContentGroupTestCase, InstructorTaskModuleTestCase): """