def test_build_feedback_options_cell(self): # Test with one assessment and one option assessment1 = AssessmentFactory() option1_text = "Test Feedback" option1 = AssessmentFeedbackOptionFactory(text=option1_text) AssessmentFeedbackFactory(assessments=(assessment1, ), options=(option1, )) # pylint: disable=protected-access feedback_option_cell = OraAggregateData._build_feedback_options_cell( [assessment1]) self.assertEqual(feedback_option_cell, option1_text + '\n') assessment2 = AssessmentFactory() option2_text = "More test feedback" option2 = AssessmentFeedbackOptionFactory(text=option2_text) AssessmentFeedbackFactory(assessments=(assessment2, ), options=(option1, option2)) # pylint: disable=protected-access feedback_option_cell = OraAggregateData._build_feedback_options_cell( [assessment1, assessment2]) self.assertEqual( feedback_option_cell, "\n".join([option1_text, option1_text, option2_text]) + "\n")
def test_map_sudents_and_scorers_ids_to_usernames(self): test_submission_information = [ ( dict( student_id=STUDENT_ID, course_id=COURSE_ID, item_id="some_id", item_type="openassessment", ), sub_api.create_submission(STUDENT_ITEM, ANSWER), (), ), ( dict( student_id=SCORER_ID, course_id=COURSE_ID, item_id="some_id", item_type="openassessment", ), sub_api.create_submission(SCORER_ITEM, ANSWER), (), ), ] with patch( "openassessment.data.OraAggregateData._map_anonymized_ids_to_usernames" ) as map_mock: # pylint: disable=protected-access OraAggregateData._map_sudents_and_scorers_ids_to_usernames( test_submission_information) map_mock.assert_called_once_with([STUDENT_ID, SCORER_ID])
def test_build_assessments_parts_cell(self): assessment1 = self._build_criteria_and_assessment_parts() a1_cell = u"Assessment #{}\n".format(assessment1.id) for part in assessment1.parts.all(): a1_cell += self._assessment_part_cell(part) # pylint: disable=protected-access assessment_part_cell = OraAggregateData._build_assessments_parts_cell( [assessment1]) self.assertEqual(a1_cell, assessment_part_cell) # Second assessment with 2 component parts and individual option feedback assessment2 = self._build_criteria_and_assessment_parts( num_criteria=2, feedback="Test feedback") a2_cell = u"Assessment #{}\n".format(assessment2.id) for part in assessment2.parts.all(): a2_cell += self._assessment_part_cell(part, feedback="Test feedback") # pylint: disable=protected-access assessment_part_cell = OraAggregateData._build_assessments_parts_cell( [assessment1, assessment2]) self.assertEqual(assessment_part_cell, a1_cell + a2_cell)
def handle(self, *args, **options): """ Run the command. """ if not args: raise CommandError("Course ID must be specified to fetch data") course_id = args[0] if options['file_name']: file_name = options['file_name'] else: file_name = ("%s-ora2.csv" % course_id).replace("/", "-") if options['output_dir']: csv_file = open(os.path.join(options['output_dir'], file_name), 'wb') else: csv_file = self.stdout writer = csv.writer(csv_file, dialect='excel', quotechar='"', quoting=csv.QUOTE_ALL) header, rows = OraAggregateData.collect_ora2_data(course_id) writer.writerow(header) for row in rows: writer.writerow(_encode_row(row))
def handle(self, *args, **options): """ Run the command. """ if not options['course_id']: raise CommandError("Course ID must be specified to fetch data") course_id = options['course_id'] if options['file_name']: file_name = options['file_name'] else: file_name = ("%s-ora2.csv" % course_id).replace("/", "-") if options['output_dir']: csv_file = open(os.path.join(options['output_dir'], file_name), 'wb') else: csv_file = self.stdout writer = csv.writer(csv_file, dialect='excel', quotechar='"', quoting=csv.QUOTE_ALL) header, rows = OraAggregateData.collect_ora2_data(course_id) writer.writerow(header) for row in rows: writer.writerow(_encode_row(row))
def get_ora2_responses(self, request, suffix=''): # pylint: disable=unused-argument """ Get information about all ora2 blocks in the course with response count for each step. """ responses = OraAggregateData.collect_ora2_responses( unicode(self.course_id)) return Response(json.dumps(responses), content_type='application/json')
def get_ora2_responses(self, request, suffix=''): # pylint: disable=unused-argument """ Get information about all ora2 blocks in the course with response count for each step. """ # Import is placed here to avoid model import at project startup. from openassessment.data import OraAggregateData responses = OraAggregateData.collect_ora2_responses(six.text_type(self.course_id)) return Response(json.dumps(responses), content_type='application/json', charset='UTF-8')
def get_ora2_responses(self, request, suffix=''): # pylint: disable=unused-argument """ Get information about all ora2 blocks in the course with response count for each step. """ # Import is placed here to avoid model import at project startup. from openassessment.data import OraAggregateData responses = OraAggregateData.collect_ora2_responses(unicode(self.course_id)) return Response(json.dumps(responses), content_type='application/json')
def test_build_feedback_options_cell(self): # Test with one assessment and one option assessment1 = AssessmentFactory() option1_text = "Test Feedback" option1 = AssessmentFeedbackOptionFactory(text=option1_text) AssessmentFeedbackFactory(assessments=(assessment1,), options=(option1,)) # pylint: disable=protected-access feedback_option_cell = OraAggregateData._build_feedback_options_cell([assessment1]) self.assertEqual(feedback_option_cell, option1_text+'\n') assessment2 = AssessmentFactory() option2_text = "More test feedback" option2 = AssessmentFeedbackOptionFactory(text=option2_text) AssessmentFeedbackFactory(assessments=(assessment2,), options=(option1, option2)) # pylint: disable=protected-access feedback_option_cell = OraAggregateData._build_feedback_options_cell([assessment1, assessment2]) self.assertEqual(feedback_option_cell, "\n".join([option1_text, option1_text, option2_text]) + "\n")
def test_build_feedback_cell(self): assessment1 = AssessmentFactory() test_text = "Test feedback text" AssessmentFeedbackFactory( assessments=(assessment1,), feedback_text=test_text, submission_uuid=assessment1.submission_uuid ) # pylint: disable=protected-access feedback_cell = OraAggregateData._build_feedback_cell(assessment1.submission_uuid) self.assertEqual(feedback_cell, test_text) assessment2 = AssessmentFactory() # pylint: disable=protected-access feedback_cell = OraAggregateData._build_feedback_cell(assessment2.submission_uuid) self.assertEqual(feedback_cell, "")
def test_build_assessments_cell(self): # One assessment assessment1 = self._build_criteria_and_assessment_parts() # pylint: disable=protected-access assessment_cell = OraAggregateData._build_assessments_cell([assessment1]) a1_cell = self._assessment_cell(assessment1) self.assertEqual(assessment_cell, a1_cell) # Multiple assessments assessment2 = self._build_criteria_and_assessment_parts(feedback="Test feedback") # pylint: disable=protected-access assessment_cell = OraAggregateData._build_assessments_cell([assessment1, assessment2]) a2_cell = self._assessment_cell(assessment2, feedback="Test feedback") self.assertEqual(assessment_cell, a1_cell + a2_cell)
def generate_report_data(self, user_state_iterator, limit_responses=None): """ Return a list of student responses and assessments for this block in a readable way. Arguments: user_state_iterator: iterator over UserStateClient objects. E.g. the result of user_state_client.iter_all_for_block(block_key) limit_responses (int|None): maximum number of responses to include. Set to None (default) to include all. Returns: each call yields a tuple like: ("my_username", { 'Submission ID': 'c6551...', 'Item ID': 5, 'Anonymized Student ID': 'c801..', 'Assessment ID': 4, 'Assessment Scored Date': '2020-02-01', 'Assessment Scored Time': '10:03:07.218280+00:00', 'Assessment Type': 'PE', 'Anonymous Scorer Id': '6e9a...', 'Criterion 1: Ideas": 'Poor', 'Points 1': 0, 'Median Score 1': 0, 'Feedback 1': 'Does not answer the question.', 'Criterion 2: Content": 'Excellent', 'Points 2': 3, 'Median Score 2': 3.0, 'Feedback 2': 'Well described.', 'Criteria Count': 'Well described.', 'Overall Feedback': 'try again', 'Date/Time Final Score Given': 2020-02-01 10:03:07.218280+00:00',, 'Final Score Points Earned': 1, 'Final Score Points Possible': 5, 'Feedback Statements Selected': "", 'Feedback on Assessment': "", 'Response files': 'http://lms.url/...', 'Response': '{"file_descriptions"...}', 'Assessment scored At': 2020-02-01 10:03:07.218280+00:00',, }) """ from openassessment.data import OraAggregateData xblock_id = self.get_xblock_id() num_rows = 0 for user_state in user_state_iterator: submission_uuid = user_state.state.get('submission_uuid') for row in OraAggregateData.generate_assessment_data( xblock_id, submission_uuid): num_rows += 1 yield (user_state.username, row) if limit_responses is not None and num_rows >= limit_responses: # End the iterator here break
def test_build_assessments_parts_cell(self): assessment1 = self._build_criteria_and_assessment_parts() a1_cell = "Assessment #{}\n".format(assessment1.id) # pylint: disable=no-member for part in assessment1.parts.all(): # pylint: disable=no-member a1_cell += self._assessment_part_cell(part) # pylint: disable=protected-access assessment_part_cell = OraAggregateData._build_assessments_parts_cell([assessment1]) self.assertEqual(a1_cell, assessment_part_cell) # Second assessment with 2 component parts and individual option feedback assessment2 = self._build_criteria_and_assessment_parts(num_criteria=2, feedback="Test feedback") a2_cell = "Assessment #{}\n".format(assessment2.id) # pylint: disable=no-member for part in assessment2.parts.all(): # pylint: disable=no-member a2_cell += self._assessment_part_cell(part, feedback="Test feedback") # pylint: disable=protected-access assessment_part_cell = OraAggregateData._build_assessments_parts_cell([assessment1, assessment2]) self.assertEqual(assessment_part_cell, a1_cell + a2_cell)
def test_collect_ora2_data_with_special_characters(self, answer): """ Scenario: Verify the data collection for ORA2 works with special or non-ascii characters. Given the submission object Then update its answer with a non-ascii value And the submission is saved When the ORA2 data for the submissions is obtained Then the data's answer will be same as json dumped answer """ submission = sub_api._get_submission_model(self.submission['uuid']) # pylint: disable=protected-access submission.answer = answer submission.save() _, rows = OraAggregateData.collect_ora2_data(COURSE_ID) self.assertEqual(json.dumps(answer, ensure_ascii=False), rows[1][4])
def test_collect_ora2_data_with_special_characters(self, answer): """ Scenario: Verify the data collection for ORA2 works with special or non-ascii characters. Given the submission object Then update its answer with a non-ascii value And the submission is saved When the ORA2 data for the submissions is obtained Then the data's answer will be same as json dumped answer """ submission = sub_api._get_submission_model(self.submission['uuid']) # pylint: disable=protected-access submission.answer = answer submission.save() with patch( 'openassessment.data.OraAggregateData._map_anonymized_ids_to_usernames' ) as map_mock: map_mock.return_value = USERNAME_MAPPING _, rows = OraAggregateData.collect_ora2_data(COURSE_ID) self.assertEqual(json.dumps(answer, ensure_ascii=False), rows[1][7])
def test_map_anonymized_ids_to_usernames(self): with patch( 'openassessment.data.get_user_model') as get_user_model_mock: get_user_model_mock.return_value.objects.filter.return_value.annotate.return_value.values.return_value = [ { 'anonymous_id': STUDENT_ID, 'username': STUDENT_USERNAME }, { 'anonymous_id': SCORER_ID, 'username': SCORER_USERNAME }, { 'anonymous_id': TEST_SCORER_ID, 'username': TEST_SCORER_USERNAME }, ] # pylint: disable=protected-access mapping = OraAggregateData._map_anonymized_ids_to_usernames( [STUDENT_ID, SCORER_ID, TEST_SCORER_ID]) self.assertEqual(mapping, USERNAME_MAPPING)
def waiting_step_data(self, data, suffix=''): # pylint: disable=unused-argument """ Retrieves waiting step details and aggregates information required by the view. This returns a dict containing a list of users stuck on the waiting step, along with information about staff grading and staff overrides applied. """ student_item = self.get_student_item_dict() peer_step_config = self.get_assessment_module('peer-assessment') # Import is placed here to avoid model import at project startup. from openassessment.assessment.api import peer as peer_api from openassessment.assessment.api import staff as staff_api from openassessment.workflow.api import get_workflows_for_status from openassessment.data import OraAggregateData # Retrieve all items in the `waiting` and `done` steps workflows_waiting = get_workflows_for_status( student_item["course_id"], student_item["item_id"], ["waiting", "done"], ) submission_uuids = [ item['submission_uuid'] for item in workflows_waiting ] # Using the workflows retrieved above, filter out all items that # haven't received the required number of peer reviews and retrieve their details. waiting_student_list = peer_api.get_waiting_step_details( student_item["course_id"], student_item["item_id"], submission_uuids, peer_step_config.get('must_be_graded_by'), ) # Get external_id to username map # pylint: disable=protected-access username_map = OraAggregateData._map_anonymized_ids_to_usernames( [item['student_id'] for item in waiting_student_list]) # Get staff assessment details staff_assessment_data = {} if "staff-assessment" in self.assessment_steps: # Only retrieve this if there's a staff assessment step enabled # when disabled, the UI should only show "Not Applicable" # This function will return either `submitted` or `not_submitted`, # depending on the status on the Staff grading. staff_assessment_data = staff_api.bulk_retrieve_workflow_status( course_id=student_item["course_id"], item_id=student_item["item_id"], # Only retrieve status for assessments that are stuck in the waiting step. submission_uuids=[ item['submission_uuid'] for item in waiting_student_list ], ) # Status to readable strings mappings workflow_status_map = { "waiting": self._("Pending"), "done": self._("Complete/Overwritten"), } staff_status_map = { "not_applicable": self._("Not applicable"), "not_submitted": self._("Not submitted"), "submitted": self._("Submitted"), } def _get_submission_status(submission_uuid): """ Retrieves the workflow submission status from the list of submissions """ return next( (workflow['status'] for workflow in workflows_waiting if workflow["submission_uuid"] == submission_uuid), "waiting", ) # Create user statistics waiting_count = 0 overwritten_count = 0 # Update waiting step details with username mappings for item in waiting_student_list: # Retrieve values from grade status and workflow status staff_grade_status = staff_assessment_data.get( item['submission_uuid'], "not_applicable") workflow_status = _get_submission_status(item['submission_uuid']) if workflow_status == 'waiting': waiting_count += 1 else: overwritten_count += 1 # Append to waiting step data, and map status to readable strings item.update({ "username": username_map[item['student_id']], "staff_grade_status": staff_status_map.get(staff_grade_status), "workflow_status": workflow_status_map.get(workflow_status), }) waiting_step_data = { "display_name": self.display_name, "must_grade": peer_step_config.get('must_grade'), "must_be_graded_by": peer_step_config.get('must_be_graded_by'), "waiting_count": waiting_count, "overwritten_count": overwritten_count, "student_data": waiting_student_list, } return Response(json_body=waiting_step_data)
def test_collect_ora2_data(self): headers, data = OraAggregateData.collect_ora2_data(COURSE_ID) self.assertEqual(headers, [ 'Submission ID', 'Item ID', 'Anonymized Student ID', 'Date/Time Response Submitted', 'Response', 'Assessment Details', 'Assessment Scores', 'Date/Time Final Score Given', 'Final Score Points Earned', 'Final Score Points Possible', 'Feedback Statements Selected', 'Feedback on Peer Assessments' ]) self.assertEqual(data[0], [ self.scorer_submission['uuid'], self.scorer_submission['student_item'], SCORER_ID, self.scorer_submission['submitted_at'], self.scorer_submission['answer'], u'', u'', u'', u'', u'', u'', u'', ]) self.assertEqual(data[1], [ self.submission['uuid'], self.submission['student_item'], STUDENT_ID, self.submission['submitted_at'], self.submission['answer'], u"Assessment #{id}\n-- scored_at: {scored_at}\n-- type: PE\n".format( id=self.assessment['id'], scored_at=self.assessment['scored_at'], ) + u"-- scorer_id: {scorer}\n-- overall_feedback: {feedback}\n".format( scorer=self.assessment['scorer_id'], feedback=self.assessment['feedback'] ), u"Assessment #{id}\n-- {label}: {option_label} ({points})\n".format( id=self.assessment['id'], label=self.assessment['parts'][1]['criterion']['label'], option_label=self.assessment['parts'][1]['criterion']['options'][0]['label'], points=self.assessment['parts'][1]['criterion']['options'][0]['points'], ) + u"-- {label}: {option_label} ({points})\n-- feedback: {feedback}\n".format( label=self.assessment['parts'][0]['criterion']['label'], option_label=self.assessment['parts'][0]['criterion']['options'][1]['label'], points=self.assessment['parts'][0]['criterion']['options'][1]['points'], feedback=self.assessment['parts'][0]['feedback'], ), self.score['created_at'], self.score['points_earned'], self.score['points_possible'], FEEDBACK_OPTIONS['options'][0] + '\n' + FEEDBACK_OPTIONS['options'][1]+'\n', FEEDBACK_TEXT, ])
def test_collect_ora2_data(self): with patch( 'openassessment.data.OraAggregateData._map_anonymized_ids_to_usernames' ) as map_mock: map_mock.return_value = USERNAME_MAPPING headers, data = OraAggregateData.collect_ora2_data(COURSE_ID) self.assertEqual(headers, [ 'Submission ID', 'Location', 'Problem Name', 'Item ID', 'Username', 'Anonymized Student ID', 'Date/Time Response Submitted', 'Response', 'Assessment Details', 'Assessment Scores', 'Date/Time Final Score Given', 'Final Score Points Earned', 'Final Score Points Possible', 'Feedback Statements Selected', 'Feedback on Peer Assessments' ]) self.assertEqual(data[0], [ self.scorer_submission['uuid'], ITEM_ID, ITEM_DISPLAY_NAME, self.scorer_submission['student_item'], SCORER_USERNAME, SCORER_ID, self.scorer_submission['submitted_at'], json.dumps(self.scorer_submission['answer']), u'', u'', u'', u'', u'', u'', u'', ]) self.assertEqual(data[1], [ self.submission['uuid'], ITEM_ID, ITEM_DISPLAY_NAME, self.submission['student_item'], STUDENT_USERNAME, STUDENT_ID, self.submission['submitted_at'], json.dumps(self.submission['answer']), u"Assessment #{id}\n-- scored_at: {scored_at}\n-- type: PE\n". format( id=self.assessment['id'], scored_at=self.assessment['scored_at'], ) + u"-- scorer_username: {scorer_username}\n".format( scorer_username=USERNAME_MAPPING[self.assessment['scorer_id']]) + u"-- scorer_id: {scorer_id}\n-- overall_feedback: {feedback}\n". format(scorer_id=self.assessment['scorer_id'], feedback=self.assessment['feedback']), u"Assessment #{id}\n-- {label}: {option_label} ({points})\n". format( id=self.assessment['id'], label=self.assessment['parts'][0]['criterion']['label'], option_label=self.assessment['parts'][0]['criterion'] ['options'][0]['label'], points=self.assessment['parts'][0]['criterion']['options'][0] ['points'], ) + u"-- {label}: {option_label} ({points})\n-- feedback: {feedback}\n" .format( label=self.assessment['parts'][1]['criterion']['label'], option_label=self.assessment['parts'][1]['criterion'] ['options'][1]['label'], points=self.assessment['parts'][1]['criterion']['options'][1] ['points'], feedback=self.assessment['parts'][1]['feedback'], ), self.score['created_at'], self.score['points_earned'], self.score['points_possible'], FEEDBACK_OPTIONS['options'][0] + '\n' + FEEDBACK_OPTIONS['options'][1] + '\n', FEEDBACK_TEXT, ])
def test_collect_ora2_data_when_usernames_disabled(self): """ Tests that ``OraAggregateData.collect_ora2_data`` generated report without usernames when `ENABLE_ORA_USERNAMES_ON_DATA_EXPORT` settings toggle equals ``False``. """ with patch.dict('django.conf.settings.FEATURES', {'ENABLE_ORA_USERNAMES_ON_DATA_EXPORT': False}): headers, data = OraAggregateData.collect_ora2_data(COURSE_ID) self.assertEqual(headers, [ 'Submission ID', 'Location', 'Problem Name', 'Item ID', 'Anonymized Student ID', 'Date/Time Response Submitted', 'Response', 'Assessment Details', 'Assessment Scores', 'Date/Time Final Score Given', 'Final Score Points Earned', 'Final Score Points Possible', 'Feedback Statements Selected', 'Feedback on Peer Assessments' ]) self.assertEqual(data[0], [ self.scorer_submission['uuid'], ITEM_ID, ITEM_DISPLAY_NAME, self.scorer_submission['student_item'], SCORER_ID, self.scorer_submission['submitted_at'], json.dumps(self.scorer_submission['answer']), u'', u'', u'', u'', u'', u'', u'', ]) self.assertEqual(data[1], [ self.submission['uuid'], ITEM_ID, ITEM_DISPLAY_NAME, self.submission['student_item'], STUDENT_ID, self.submission['submitted_at'], json.dumps(self.submission['answer']), u"Assessment #{id}\n-- scored_at: {scored_at}\n-- type: PE\n". format( id=self.assessment['id'], scored_at=self.assessment['scored_at'], ) + u"-- scorer_id: {scorer_id}\n-- overall_feedback: {feedback}\n" .format(scorer_id=self.assessment['scorer_id'], feedback=self.assessment['feedback']), u"Assessment #{id}\n-- {label}: {option_label} ({points})\n". format( id=self.assessment['id'], label=self.assessment['parts'][0]['criterion']['label'], option_label=self.assessment['parts'][0]['criterion'] ['options'][0]['label'], points=self.assessment['parts'][0]['criterion']['options'][0] ['points'], ) + u"-- {label}: {option_label} ({points})\n-- feedback: {feedback}\n" .format( label=self.assessment['parts'][1]['criterion']['label'], option_label=self.assessment['parts'][1]['criterion'] ['options'][1]['label'], points=self.assessment['parts'][1]['criterion']['options'][1] ['points'], feedback=self.assessment['parts'][1]['feedback'], ), self.score['created_at'], self.score['points_earned'], self.score['points_possible'], FEEDBACK_OPTIONS['options'][0] + '\n' + FEEDBACK_OPTIONS['options'][1] + '\n', FEEDBACK_TEXT, ])
def test_collect_ora2_responses(self): item_id2 = self._other_item(2) item_id3 = self._other_item(3) student_id2 = self._other_student(2) student_id3 = self._other_student(3) self._create_submission(dict( student_id=STUDENT_ID, course_id=COURSE_ID, item_id=item_id2, item_type="openassessment" ), ['self']) self._create_submission(dict( student_id=student_id2, course_id=COURSE_ID, item_id=item_id2, item_type="openassessment" ), STEPS) self._create_submission(dict( student_id=STUDENT_ID, course_id=COURSE_ID, item_id=item_id3, item_type="openassessment" ), ['self']) self._create_submission(dict( student_id=student_id2, course_id=COURSE_ID, item_id=item_id3, item_type="openassessment" ), ['self']) self._create_submission(dict( student_id=student_id3, course_id=COURSE_ID, item_id=item_id3, item_type="openassessment" ), STEPS) data = OraAggregateData.collect_ora2_responses(COURSE_ID) self.assertIn(ITEM_ID, data) self.assertIn(item_id2, data) self.assertIn(item_id3, data) for item in [ITEM_ID, item_id2, item_id3]: self.assertEqual({'total', 'training', 'peer', 'self', 'staff', 'waiting', 'done', 'cancelled'}, set(data[item].keys())) self.assertEqual(data[ITEM_ID], { 'total': 2, 'training': 0, 'peer': 2, 'self': 0, 'staff': 0, 'waiting': 0, 'done': 0, 'cancelled': 0 }) self.assertEqual(data[item_id2], { 'total': 2, 'training': 0, 'peer': 1, 'self': 1, 'staff': 0, 'waiting': 0, 'done': 0, 'cancelled': 0 }) self.assertEqual(data[item_id3], { 'total': 3, 'training': 0, 'peer': 1, 'self': 2, 'staff': 0, 'waiting': 0, 'done': 0, 'cancelled': 0 }) data = OraAggregateData.collect_ora2_responses(COURSE_ID, ['staff', 'peer']) self.assertIn(ITEM_ID, data) self.assertIn(item_id2, data) self.assertIn(item_id3, data) for item in [ITEM_ID, item_id2, item_id3]: self.assertEqual({'total', 'peer', 'staff'}, set(data[item].keys())) self.assertEqual(data[ITEM_ID], {'total': 2, 'peer': 2, 'staff': 0}) self.assertEqual(data[item_id2], {'total': 1, 'peer': 1, 'staff': 0}) self.assertEqual(data[item_id3], {'total': 1, 'peer': 1, 'staff': 0})
def upload_ora2_data( _xmodule_instance_args, _entry_id, course_id, _task_input, action_name ): """ Collect ora2 responses and upload them to S3 as a CSV """ start_date = datetime.now(UTC) start_time = time() num_attempted = 1 num_total = 1 fmt = u'Task: {task_id}, InstructorTask ID: {entry_id}, Course: {course_id}, Input: {task_input}' task_info_string = fmt.format( task_id=_xmodule_instance_args.get('task_id') if _xmodule_instance_args is not None else None, entry_id=_entry_id, course_id=course_id, task_input=_task_input ) TASK_LOG.info(u'%s, Task type: %s, Starting task execution', task_info_string, action_name) task_progress = TaskProgress(action_name, num_total, start_time) task_progress.attempted = num_attempted curr_step = {'step': "Collecting responses"} TASK_LOG.info( u'%s, Task type: %s, Current step: %s for all submissions', task_info_string, action_name, curr_step, ) task_progress.update_task_state(extra_meta=curr_step) try: header, datarows = OraAggregateData.collect_ora2_data(course_id) rows = [header] + [row for row in datarows] # Update progress to failed regardless of error type except Exception: # pylint: disable=broad-except TASK_LOG.exception('Failed to get ORA data.') task_progress.failed = 1 curr_step = {'step': "Error while collecting data"} task_progress.update_task_state(extra_meta=curr_step) return UPDATE_STATUS_FAILED task_progress.succeeded = 1 curr_step = {'step': "Uploading CSV"} TASK_LOG.info( u'%s, Task type: %s, Current step: %s', task_info_string, action_name, curr_step, ) task_progress.update_task_state(extra_meta=curr_step) upload_csv_to_report_store(rows, 'ORA_data', course_id, start_date) curr_step = {'step': 'Finalizing ORA data report'} task_progress.update_task_state(extra_meta=curr_step) TASK_LOG.info(u'%s, Task type: %s, Upload complete.', task_info_string, action_name) return UPDATE_STATUS_SUCCEEDED
def test_collect_ora2_responses(self): item_id2 = self._other_item(2) item_id3 = self._other_item(3) team_item_id = self._other_item(4) student_id2 = self._other_student(2) student_id3 = self._other_student(3) team_1_ids = [STUDENT_ID, student_id2, student_id3] student_id4 = self._other_student(4) student_id5 = self._other_student(5) team_2_ids = [student_id4, student_id5] student_model_1 = UserFactory.create() student_model_2 = UserFactory.create() self._create_submission( dict(student_id=STUDENT_ID, course_id=COURSE_ID, item_id=item_id2, item_type="openassessment"), ['self']) self._create_submission( dict(student_id=student_id2, course_id=COURSE_ID, item_id=item_id2, item_type="openassessment"), STEPS) self._create_submission( dict(student_id=STUDENT_ID, course_id=COURSE_ID, item_id=item_id3, item_type="openassessment"), ['self']) self._create_submission( dict(student_id=student_id2, course_id=COURSE_ID, item_id=item_id3, item_type="openassessment"), ['self']) self._create_submission( dict(student_id=student_id3, course_id=COURSE_ID, item_id=item_id3, item_type="openassessment"), STEPS) self._create_team_submission( COURSE_ID, team_item_id, 'team_1', student_model_1.id, team_1_ids, ) self._create_team_submission(COURSE_ID, team_item_id, 'team_2', student_model_2.id, team_2_ids) data = OraAggregateData.collect_ora2_responses(COURSE_ID) self.assertIn(ITEM_ID, data) self.assertIn(item_id2, data) self.assertIn(item_id3, data) self.assertIn(team_item_id, data) for item in [ITEM_ID, item_id2, item_id3, team_item_id]: self.assertEqual( { 'total', 'training', 'peer', 'self', 'staff', 'waiting', 'done', 'cancelled', 'teams' }, set(data[item].keys())) self.assertEqual( data[ITEM_ID], { 'total': 2, 'training': 0, 'peer': 2, 'self': 0, 'staff': 0, 'waiting': 0, 'done': 0, 'cancelled': 0, 'teams': 0 }) self.assertEqual( data[item_id2], { 'total': 2, 'training': 0, 'peer': 1, 'self': 1, 'staff': 0, 'waiting': 0, 'done': 0, 'cancelled': 0, 'teams': 0 }) self.assertEqual( data[item_id3], { 'total': 3, 'training': 0, 'peer': 1, 'self': 2, 'staff': 0, 'waiting': 0, 'done': 0, 'cancelled': 0, 'teams': 0 }) self.assertEqual( data[team_item_id], { 'total': 2, 'training': 0, 'peer': 0, 'self': 0, 'staff': 0, 'waiting': 0, 'done': 0, 'cancelled': 0, 'teams': 2 }) data = OraAggregateData.collect_ora2_responses(COURSE_ID, ['staff', 'peer']) self.assertIn(ITEM_ID, data) self.assertIn(item_id2, data) self.assertIn(item_id3, data) for item in [ITEM_ID, item_id2, item_id3]: self.assertEqual({'total', 'peer', 'staff'}, set(data[item].keys())) self.assertEqual(data[ITEM_ID], {'total': 2, 'peer': 2, 'staff': 0}) self.assertEqual(data[item_id2], {'total': 1, 'peer': 1, 'staff': 0}) self.assertEqual(data[item_id3], {'total': 1, 'peer': 1, 'staff': 0})