From ff84545f3155c00e3824b79845e6ab3fac160b2e Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Wed, 8 May 2013 18:49:28 -0400 Subject: [PATCH] Start to add peer grading tests, make dummy system a separate thing --- .../peer_grading_service.py | 27 +++++---- .../lib/xmodule/xmodule/tests/dummy_system.py | 55 ++++++++++++++++++ .../xmodule/tests/test_combined_open_ended.py | 57 ++----------------- .../xmodule/tests/test_peer_grading.py | 49 ++++++++++++++++ .../test/data/open_ended/course/2012_Fall.xml | 1 + .../peergrading/PeerGradingSample.xml | 1 + .../data/open_ended/policies/2012_Fall.json | 5 +- 7 files changed, 131 insertions(+), 64 deletions(-) create mode 100644 common/lib/xmodule/xmodule/tests/dummy_system.py create mode 100644 common/lib/xmodule/xmodule/tests/test_peer_grading.py create mode 100644 common/test/data/open_ended/peergrading/PeerGradingSample.xml diff --git a/common/lib/xmodule/xmodule/open_ended_grading_classes/peer_grading_service.py b/common/lib/xmodule/xmodule/open_ended_grading_classes/peer_grading_service.py index 85c7a98132..19cc013cb7 100644 --- a/common/lib/xmodule/xmodule/open_ended_grading_classes/peer_grading_service.py +++ b/common/lib/xmodule/xmodule/open_ended_grading_classes/peer_grading_service.py @@ -100,29 +100,29 @@ without making actual service calls to the grading controller class MockPeerGradingService(object): def get_next_submission(self, problem_location, grader_id): - return json.dumps({'success': True, + return {'success': True, 'submission_id': 1, 'submission_key': "", 'student_response': 'fake student response', 'prompt': 'fake submission prompt', 'rubric': 'fake rubric', - 'max_score': 4}) + 'max_score': 4} def save_grade(self, location, grader_id, submission_id, score, feedback, submission_key, rubric_scores, submission_flagged): - return json.dumps({'success': True}) + return {'success': True} def is_student_calibrated(self, problem_location, grader_id): - return json.dumps({'success': True, 'calibrated': True}) + return {'success': True, 'calibrated': True} def show_calibration_essay(self, problem_location, grader_id): - return json.dumps({'success': True, + return {'success': True, 'submission_id': 1, 'submission_key': '', 'student_response': 'fake student response', 'prompt': 'fake submission prompt', 'rubric': 'fake rubric', - 'max_score': 4}) + 'max_score': 4} def save_calibration_essay(self, problem_location, grader_id, calibration_essay_id, submission_key, score, @@ -130,10 +130,13 @@ class MockPeerGradingService(object): return {'success': True, 'actual_score': 2} def get_problem_list(self, course_id, grader_id): - return json.dumps({'success': True, + return {'success': True, 'problem_list': [ - json.dumps({'location': 'i4x://MITx/3.091x/problem/open_ended_demo1', - 'problem_name': "Problem 1", 'num_graded': 3, 'num_pending': 5}), - json.dumps({'location': 'i4x://MITx/3.091x/problem/open_ended_demo2', - 'problem_name': "Problem 2", 'num_graded': 1, 'num_pending': 5}) - ]}) + {'location': 'i4x://MITx/3.091x/problem/open_ended_demo1', + 'problem_name': "Problem 1", 'num_graded': 3, 'num_pending': 5}, + {'location': 'i4x://MITx/3.091x/problem/open_ended_demo2', + 'problem_name': "Problem 2", 'num_graded': 1, 'num_pending': 5} + ]} + + def get_data_for_location(self, problem_location, student_id): + return {"version": 1, "count_graded": 3, "count_required": 3, "success": True, "student_sub_count": 1} diff --git a/common/lib/xmodule/xmodule/tests/dummy_system.py b/common/lib/xmodule/xmodule/tests/dummy_system.py new file mode 100644 index 0000000000..b4ca6136eb --- /dev/null +++ b/common/lib/xmodule/xmodule/tests/dummy_system.py @@ -0,0 +1,55 @@ +from . import test_system +import unittest +from xmodule.modulestore import Location +from xmodule.modulestore.xml import ImportSystem, XMLModuleStore +from xmodule.tests.test_export import DATA_DIR +from fs.memoryfs import MemoryFS +from mock import patch, Mock + +class DummySystem(ImportSystem): + + @patch('xmodule.modulestore.xml.OSFS', lambda dir: MemoryFS()) + def __init__(self, load_error_modules, org, course): + + xmlstore = XMLModuleStore("data_dir", course_dirs=[], load_error_modules=load_error_modules) + course_id = "/".join([org, course, 'test_run']) + course_dir = "test_dir" + policy = {} + error_tracker = Mock() + parent_tracker = Mock() + + super(DummySystem, self).__init__( + xmlstore, + course_id, + course_dir, + policy, + error_tracker, + parent_tracker, + load_error_modules=load_error_modules, + ) + + def render_template(self, template, context): + raise Exception("Shouldn't be called") + +class DummySystemUser(object): + test_system = test_system() + @staticmethod + def get_import_system(org, course, load_error_modules=True): + '''Get a dummy system''' + return DummySystem(load_error_modules, org, course) + + def get_course(self, name): + """Get a test course by directory name. If there's more than one, error.""" + + modulestore = XMLModuleStore(DATA_DIR, course_dirs=[name]) + courses = modulestore.get_courses() + self.modulestore = modulestore + self.assertEquals(len(courses), 1) + return courses[0] + + def get_module_from_location(self, location, course): + course = self.get_course(course) + if not isinstance(location, Location): + location = Location(location) + descriptor = self.modulestore.get_instance(course.id, location, depth=None) + return descriptor.xmodule(self.test_system) \ No newline at end of file diff --git a/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py b/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py index 3b8019290f..fdbd37c6ab 100644 --- a/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py +++ b/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py @@ -5,6 +5,8 @@ import unittest from fs.memoryfs import MemoryFS from mock import patch +from dummy_system import DummySystemUser + from xmodule.open_ended_grading_classes.openendedchild import OpenEndedChild from xmodule.open_ended_grading_classes.open_ended_module import OpenEndedModule from xmodule.open_ended_grading_classes.combined_open_ended_modulev1 import CombinedOpenEndedV1Module @@ -42,31 +44,6 @@ class MockQueryDict(dict): return [] return default -class DummySystem(ImportSystem): - - @patch('xmodule.modulestore.xml.OSFS', lambda dir: MemoryFS()) - def __init__(self, load_error_modules): - - xmlstore = XMLModuleStore("data_dir", course_dirs=[], load_error_modules=load_error_modules) - course_id = "/".join([ORG, COURSE, 'test_run']) - course_dir = "test_dir" - policy = {} - error_tracker = Mock() - parent_tracker = Mock() - - super(DummySystem, self).__init__( - xmlstore, - course_id, - course_dir, - policy, - error_tracker, - parent_tracker, - load_error_modules=load_error_modules, - ) - - def render_template(self, template, context): - raise Exception("Shouldn't be called") - """ Tests for the various pieces of the CombinedOpenEndedGrading system @@ -514,7 +491,7 @@ class CombinedOpenEndedModuleTest(unittest.TestCase): self.assertEqual(score_dict['score'], 15.0) self.assertEqual(score_dict['total'], 15.0) -class OpenEndedModuleXmlTest(unittest.TestCase): +class OpenEndedModuleXmlTest(unittest.TestCase, DummySystemUser): problem_location = Location(["i4x", "edX", "oe_test", "combinedopenended", "SampleQuestion"]) answer = "blah blah" assessment = [0,1] @@ -525,37 +502,15 @@ class OpenEndedModuleXmlTest(unittest.TestCase): send_to_queue = Mock(side_effect=[1,"queued"]) ) - @staticmethod - def get_import_system(load_error_modules=True): - '''Get a dummy system''' - return DummySystem(load_error_modules) - - def get_course(self, name): - """Get a test course by directory name. If there's more than one, error.""" - print "Importing {0}".format(name) - - modulestore = XMLModuleStore(DATA_DIR, course_dirs=[name]) - courses = modulestore.get_courses() - self.modulestore = modulestore - self.assertEquals(len(courses), 1) - return courses[0] - - def get_module_from_location(self, location): - course = self.get_course('open_ended') - if not isinstance(location, Location): - location = Location(location) - descriptor = self.modulestore.get_instance(course.id, location, depth=None) - return descriptor.xmodule(self.test_system) - def test_open_ended_load_and_save(self): - module = self.get_module_from_location(self.problem_location) + module = self.get_module_from_location(self.problem_location, COURSE) module.handle_ajax("save_answer", {"student_answer" : self.answer}) task_one_json = json.loads(module.task_states[0]) self.assertEqual(task_one_json['child_history'][0]['answer'], self.answer) def test_open_ended_flow_reset(self): assessment = [0,1] - module = self.get_module_from_location(self.problem_location) + module = self.get_module_from_location(self.problem_location, COURSE) #Simulate a student saving an answer module.handle_ajax("save_answer", {"student_answer" : self.answer}) @@ -578,7 +533,7 @@ class OpenEndedModuleXmlTest(unittest.TestCase): def test_open_ended_flow_correct(self): assessment = [1,1] - module = self.get_module_from_location(self.problem_location) + module = self.get_module_from_location(self.problem_location, COURSE) #Simulate a student saving an answer module.handle_ajax("save_answer", {"student_answer" : self.answer}) diff --git a/common/lib/xmodule/xmodule/tests/test_peer_grading.py b/common/lib/xmodule/xmodule/tests/test_peer_grading.py new file mode 100644 index 0000000000..01b3da0778 --- /dev/null +++ b/common/lib/xmodule/xmodule/tests/test_peer_grading.py @@ -0,0 +1,49 @@ +import unittest +from xmodule.modulestore import Location +import json +from lxml import etree +from mock import Mock +from . import test_system +from dummy_system import DummySystem, DummySystemUser + +from xmodule.peer_grading_module import PeerGradingModule, PeerGradingDescriptor +from xmodule.open_ended_grading_classes.grading_service_module import GradingServiceError + +ORG = "edX" +COURSE="open_ended" + + +class PeerGradingModuleTest(unittest.TestCase, DummySystemUser): + location = Location(["i4x", "edX", "open_ended", "peergrading", + "SampleQuestion"]) + max_score = 1 + + definition = "" + descriptor = Mock(data=definition) + + def setUp(self): + self.test_system = test_system() + self.test_system.open_ended_grading_interface = None + self.peer_grading = PeerGradingModule(self.test_system, self.location,self.descriptor, model_data={'data': self.definition}) + + def test_module_closed(self): + closed = self.peer_grading.closed() + self.assertEqual(closed, False) + + def test_get_html(self): + html = self.peer_grading.get_html() + + def test_get_data(self): + try: + success, data = self.peer_grading.query_data_for_location() + except GradingServiceError: + pass + + def test_get_score(self): + score = self.peer_grading.get_score() + + def test_get_max_score(self): + max_score = self.peer_grading.max_score() + + def get_next_submission(self): + success, next_submission = self.peer_grading.get_next_submission({'location' : 'blah'}) \ No newline at end of file diff --git a/common/test/data/open_ended/course/2012_Fall.xml b/common/test/data/open_ended/course/2012_Fall.xml index f2d16488a7..34369979ca 100644 --- a/common/test/data/open_ended/course/2012_Fall.xml +++ b/common/test/data/open_ended/course/2012_Fall.xml @@ -1,5 +1,6 @@ + diff --git a/common/test/data/open_ended/peergrading/PeerGradingSample.xml b/common/test/data/open_ended/peergrading/PeerGradingSample.xml new file mode 100644 index 0000000000..7e3afddf3a --- /dev/null +++ b/common/test/data/open_ended/peergrading/PeerGradingSample.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/common/test/data/open_ended/policies/2012_Fall.json b/common/test/data/open_ended/policies/2012_Fall.json index 09b68ab400..8f8ba13437 100644 --- a/common/test/data/open_ended/policies/2012_Fall.json +++ b/common/test/data/open_ended/policies/2012_Fall.json @@ -9,6 +9,9 @@ "display_name": "Overview" }, "combinedopenended/SampleQuestion": { - "display_name": "Sample Question", + "display_name": "Sample Question" }, + "peergrading/PeerGradingSample": { + "display_name": "Sample Question" + } }