def test_other_data_types(self): # We'll submit one problem, and then muck with the student_answers # dict inside its state to try different data types (str, int, float, # none) self.submit_question_answer('p1', {'2_1': u'Correct'}) # Now fetch the state entry for that problem. student_module = StudentModule.objects.get( course_id=self.course.id, student=self.student_user ) for val in ('Correct', True, False, 0, 0.0, 1, 1.0, None): state = json.loads(student_module.state) state["student_answers"]['{}_2_1'.format(self.p1_html_id)] = val student_module.state = json.dumps(state) student_module.save() self.assertEqual( grades.answer_distributions(self.course.id), { ('p1', 'p1', '{}_2_1'.format(self.p1_html_id)): { str(val): 1 }, } )
def test_multiple_students(self): # Our test class is based around making requests for a particular user, # so we're going to cheat by creating another user and copying and # modifying StudentModule entries to make them from other users. It's # a little hacky, but it seemed the simpler way to do this. self.submit_question_answer('p1', {'2_1': u'Correct'}) self.submit_question_answer('p2', {'2_1': u'Incorrect'}) self.submit_question_answer('p3', {'2_1': u'Correct'}) # Make the above submissions owned by user2 user2 = UserFactory.create() problems = StudentModule.objects.filter(course_id=self.course.id, student=self.student_user) for problem in problems: problem.student_id = user2.id problem.save() # Now make more submissions by our original user self.submit_question_answer('p1', {'2_1': u'Correct'}) self.submit_question_answer('p2', {'2_1': u'Correct'}) self.assertEqual( grades.answer_distributions(self.course.id), { ('p1', 'p1', '{}_2_1'.format(self.p1_html_id)): { 'Correct': 2 }, ('p2', 'p2', '{}_2_1'.format(self.p2_html_id)): { 'Correct': 1, 'Incorrect': 1 }, ('p3', 'p3', '{}_2_1'.format(self.p3_html_id)): { 'Correct': 1 } })
def test_multiple_students(self): # Our test class is based around making requests for a particular user, # so we're going to cheat by creating another user and copying and # modifying StudentModule entries to make them from other users. It's # a little hacky, but it seemed the simpler way to do this. self.submit_question_answer("p1", {"2_1": u"Correct"}) self.submit_question_answer("p2", {"2_1": u"Incorrect"}) self.submit_question_answer("p3", {"2_1": u"Correct"}) # Make the above submissions owned by user2 user2 = UserFactory.create() problems = StudentModule.objects.filter(course_id=self.course.id, student=self.student_user) for problem in problems: problem.student_id = user2.id problem.save() # Now make more submissions by our original user self.submit_question_answer("p1", {"2_1": u"Correct"}) self.submit_question_answer("p2", {"2_1": u"Correct"}) self.assertEqual( grades.answer_distributions(self.course.id), { ("p1", "p1", "{}_2_1".format(self.p1_html_id)): {"Correct": 2}, ("p2", "p2", "{}_2_1".format(self.p2_html_id)): {"Correct": 1, "Incorrect": 1}, ("p3", "p3", "{}_2_1".format(self.p3_html_id)): {"Correct": 1}, }, )
def test_broken_state(self): # Missing or broken state for a problem should be skipped without # causing the whole answer_distribution call to explode. # Submit p1 self.submit_question_answer('p1', {'2_1': u'Correct'}) # Now fetch the StudentModule entry for p1 so we can corrupt its state prb1 = StudentModule.objects.get( course_id=self.course.id, student_id=self.student_user.id ) # Submit p2 self.submit_question_answer('p2', {'2_1': u'Incorrect'}) for new_p1_state in ('{"student_answers": {}}', "invalid json!", None): prb1.state = new_p1_state prb1.save() # p1 won't show up, but p2 should still work self.assertEqual( grades.answer_distributions(self.course.id), { ('p2', 'p2', 'i4x-MITx-100-problem-p2_2_1'): { 'Incorrect': 1 }, } )
def test_other_data_types(self): # We'll submit one problem, and then muck with the student_answers # dict inside its state to try different data types (str, int, float, # none) problem_name = 'p1' self.submit_question_answer(problem_name, {'2_1': u'Correct'}) # Now fetch the state entry for that problem. student_modules = StudentModule.objects.filter( course_id=self.course.id, student=self.student_user ) for student_module in student_modules: if student_module.module_state_key.name == problem_name: for val in ('Correct', True, False, 0, 0.0, 1, 1.0, None): state = json.loads(student_module.state) state["student_answers"]['{}_2_1'.format(self.p1_html_id)] = val student_module.state = json.dumps(state) student_module.save() self.assertEqual( grades.answer_distributions(self.course.id), { ('p1', 'p1', '{}_2_1'.format(self.p1_html_id)): { str(val): 1 }, } )
def test_other_data_types(self): # We'll submit one problem, and then muck with the student_answers # dict inside its state to try different data types (str, int, float, # none) self.submit_question_answer('p1', {'2_1': u'Correct'}) # Now fetch the state entry for that problem. student_module = StudentModule.objects.get( course_id=self.course.id, student_id=self.student_user.id ) for val in ('Correct', True, False, 0, 0.0, 1, 1.0, None): state = json.loads(student_module.state) state["student_answers"]['i4x-MITx-100-problem-p1_2_1'] = val student_module.state = json.dumps(state) student_module.save() self.assertEqual( grades.answer_distributions(self.course.id), { ('p1', 'p1', 'i4x-MITx-100-problem-p1_2_1'): { str(val): 1 }, } )
def test_broken_state(self): # Missing or broken state for a problem should be skipped without # causing the whole answer_distribution call to explode. # Submit p1 prb1_name = 'p1' self.submit_question_answer(prb1_name, {'2_1': u'Correct'}) # Now fetch the StudentModule entry for p1 so we can corrupt its state student_modules = StudentModule.objects.filter( course_id=self.course.id, student=self.student_user ) for student_module in student_modules: if student_module.module_state_key.name == prb1_name: prb1 = student_module break # Submit p2 self.submit_question_answer('p2', {'2_1': u'Incorrect'}) for new_p1_state in ('{"student_answers": {}}', "invalid json!", None): prb1.state = new_p1_state prb1.save() # p1 won't show up, but p2 should still work self.assertEqual( grades.answer_distributions(self.course.id), { ('p2', 'p2', '{}_2_1'.format(self.p2_html_id)): { 'Incorrect': 1 }, } )
def test_broken_state(self): # Missing or broken state for a problem should be skipped without # causing the whole answer_distribution call to explode. # Submit p1 self.submit_question_answer('p1', {'2_1': u'Correct'}) # Now fetch the StudentModule entry for p1 so we can corrupt its state prb1 = StudentModule.objects.get( course_id=self.course.id, student=self.student_user ) # Submit p2 self.submit_question_answer('p2', {'2_1': u'Incorrect'}) for new_p1_state in ('{"student_answers": {}}', "invalid json!", None): prb1.state = new_p1_state prb1.save() # p1 won't show up, but p2 should still work self.assertEqual( grades.answer_distributions(self.course.id), { ('p2', 'p2', '{}_2_1'.format(self.p2_html_id)): { 'Incorrect': 1 }, } )
def test_one_student(self): # Basic test to make sure we have simple behavior right for a student # Throw in a non-ASCII answer self.submit_question_answer("p1", {"2_1": u"ⓤⓝⓘⓒⓞⓓⓔ"}) self.submit_question_answer("p2", {"2_1": "Correct"}) distributions = grades.answer_distributions(self.course.id) self.assertEqual( distributions, { ("p1", "p1", "{}_2_1".format(self.p1_html_id)): {u"ⓤⓝⓘⓒⓞⓓⓔ": 1}, ("p2", "p2", "{}_2_1".format(self.p2_html_id)): {"Correct": 1}, }, )
def test_missing_content(self): # If there's a StudentModule entry for content that no longer exists, # we just quietly ignore it (because we can't display a meaningful url # or name for it). self.submit_question_answer("p1", {"2_1": "Incorrect"}) # Now fetch the state entry for that problem and alter it so it points # to a non-existent problem. student_module = StudentModule.objects.get(course_id=self.course.id, student_id=self.student_user.id) student_module.module_state_key += "_fake" student_module.save() # It should be empty (ignored) empty_distribution = grades.answer_distributions(self.course.id) self.assertFalse(empty_distribution) # should be empty
def test_missing_content(self): # If there's a StudentModule entry for content that no longer exists, # we just quietly ignore it (because we can't display a meaningful url # or name for it). self.submit_question_answer('p1', {'2_1': 'Incorrect'}) # Now fetch the state entry for that problem and alter it so it points # to a non-existent problem. student_module = StudentModule.objects.get( course_id=self.course.id, student_id=self.student_user.id) student_module.module_state_key += "_fake" student_module.save() # It should be empty (ignored) empty_distribution = grades.answer_distributions(self.course.id) self.assertFalse(empty_distribution) # should be empty
def test_one_student(self): # Basic test to make sure we have simple behavior right for a student # Throw in a non-ASCII answer self.submit_question_answer('p1', {'2_1': u'ⓤⓝⓘⓒⓞⓓⓔ'}) self.submit_question_answer('p2', {'2_1': 'Correct'}) distributions = grades.answer_distributions(self.course.id) self.assertEqual( distributions, { ('p1', 'p1', '{}_2_1'.format(self.p1_html_id)): { u'ⓤⓝⓘⓒⓞⓓⓔ': 1 }, ('p2', 'p2', '{}_2_1'.format(self.p2_html_id)): { 'Correct': 1 } })
def test_other_data_types(self): # We'll submit one problem, and then muck with the student_answers # dict inside its state to try different data types (str, int, float, # none) self.submit_question_answer("p1", {"2_1": u"Correct"}) # Now fetch the state entry for that problem. student_module = StudentModule.objects.get(course_id=self.course.id, student=self.student_user) for val in ("Correct", True, False, 0, 0.0, 1, 1.0, None): state = json.loads(student_module.state) state["student_answers"]["{}_2_1".format(self.p1_html_id)] = val student_module.state = json.dumps(state) student_module.save() self.assertEqual( grades.answer_distributions(self.course.id), {("p1", "p1", "{}_2_1".format(self.p1_html_id)): {str(val): 1}}, )
def test_one_student(self): # Basic test to make sure we have simple behavior right for a student # Throw in a non-ASCII answer self.submit_question_answer('p1', {'2_1': u'ⓤⓝⓘⓒⓞⓓⓔ'}) self.submit_question_answer('p2', {'2_1': 'Correct'}) distributions = grades.answer_distributions(self.course.id) self.assertEqual( distributions, { ('p1', 'p1', '{}_2_1'.format(self.p1_html_id)): { u'ⓤⓝⓘⓒⓞⓓⓔ': 1 }, ('p2', 'p2', '{}_2_1'.format(self.p2_html_id)): { 'Correct': 1 } } )
def get_answers_distribution(request, course_key): """ Get the distribution of answers for all graded problems in the course. Return a dict with two keys: 'header': a header row 'data': a list of rows """ course = get_course_with_access(request.user, "staff", course_key) course_answer_distributions = grades.answer_distributions(course.id) dist = {} dist["header"] = ["url_name", "display name", "answer id", "answer", "count"] dist["data"] = [ [url_name, display_name, answer_id, a, answers[a]] for (url_name, display_name, answer_id), answers in sorted(course_answer_distributions.items()) for a in answers ] return dist
def get_answers_distribution(request, course_key): """ Get the distribution of answers for all graded problems in the course. Return a dict with two keys: 'header': a header row 'data': a list of rows """ course = get_course_with_access(request.user, 'staff', course_key) dist = grades.answer_distributions(course.id) dist = {} dist['header'] = ['url_name', 'display name', 'answer id', 'answer', 'count'] dist['data'] = [ [url_name, display_name, answer_id, a, answers[a]] for (url_name, display_name, answer_id), answers in sorted(dist.items()) for a in answers ] return dist
def get_answers_distribution(request, course_key): """ Get the distribution of answers for all graded problems in the course. Return a dict with two keys: 'header': a header row 'data': a list of rows """ course = get_course_with_access(request.user, 'staff', course_key) course_answer_distributions = grades.answer_distributions(course.id) dist = {} dist['header'] = ['url_name', 'display name', 'answer id', 'answer', 'count'] dist['data'] = [ [url_name, display_name, answer_id, a, answers[a]] for (url_name, display_name, answer_id), answers in sorted(course_answer_distributions.items()) for a in answers ] return dist
def test_broken_state(self): # Missing or broken state for a problem should be skipped without # causing the whole answer_distribution call to explode. # Submit p1 self.submit_question_answer("p1", {"2_1": u"Correct"}) # Now fetch the StudentModule entry for p1 so we can corrupt its state prb1 = StudentModule.objects.get(course_id=self.course.id, student=self.student_user) # Submit p2 self.submit_question_answer("p2", {"2_1": u"Incorrect"}) for new_p1_state in ('{"student_answers": {}}', "invalid json!", None): prb1.state = new_p1_state prb1.save() # p1 won't show up, but p2 should still work self.assertEqual( grades.answer_distributions(self.course.id), {("p2", "p2", "{}_2_1".format(self.p2_html_id)): {"Incorrect": 1}}, )
def test_multiple_students(self): # Our test class is based around making requests for a particular user, # so we're going to cheat by creating another user and copying and # modifying StudentModule entries to make them from other users. It's # a little hacky, but it seemed the simpler way to do this. self.submit_question_answer('p1', {'2_1': u'Correct'}) self.submit_question_answer('p2', {'2_1': u'Incorrect'}) self.submit_question_answer('p3', {'2_1': u'Correct'}) # Make the above submissions owned by user2 user2 = UserFactory.create() problems = StudentModule.objects.filter( course_id=self.course.id, student_id=self.student_user.id ) for problem in problems: problem.student_id = user2.id problem.save() # Now make more submissions by our original user self.submit_question_answer('p1', {'2_1': u'Correct'}) self.submit_question_answer('p2', {'2_1': u'Correct'}) self.assertEqual( grades.answer_distributions(self.course.id), { ('p1', 'p1', 'i4x-MITx-100-problem-p1_2_1'): { 'Correct': 2 }, ('p2', 'p2', 'i4x-MITx-100-problem-p2_2_1'): { 'Correct': 1, 'Incorrect': 1 }, ('p3', 'p3', 'i4x-MITx-100-problem-p3_2_1'): { 'Correct': 1 } } )
def test_missing_content(self): # If there's a StudentModule entry for content that no longer exists, # we just quietly ignore it (because we can't display a meaningful url # or name for it). problem_name = 'p1' self.submit_question_answer(problem_name, {'2_1': 'Incorrect'}) # Now fetch the state entry for that problem and alter it so it points # to a non-existent problem. student_modules = StudentModule.objects.filter( course_id=self.course.id, student=self.student_user ) for student_module in student_modules: if student_module.module_state_key.name == problem_name: student_module.module_state_key = student_module.module_state_key.replace( name=student_module.module_state_key.name + "_fake" ) student_module.save() # It should be empty (ignored) empty_distribution = grades.answer_distributions(self.course.id) self.assertFalse(empty_distribution) # should be empty
def test_empty(self): # Just make sure we can process this without errors. empty_distribution = grades.answer_distributions(self.course.id) self.assertFalse(empty_distribution) # should be empty