Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
fd72005a
Commit
fd72005a
authored
Oct 17, 2013
by
Vik Paruchuri
Committed by
Brian Wilson
Oct 28, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Ensure that peer grading modules whose linked problem is removed change over to panel mode
parent
d8447436
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
136 additions
and
67 deletions
+136
-67
common/lib/xmodule/xmodule/peer_grading_module.py
+39
-27
common/lib/xmodule/xmodule/tests/test_peer_grading.py
+97
-40
No files found.
common/lib/xmodule/xmodule/peer_grading_module.py
View file @
fd72005a
...
...
@@ -104,30 +104,28 @@ class PeerGradingModule(PeerGradingFields, XModule):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
PeerGradingModule
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
#We need to set the location here so the child modules can use it
# Copy this to a new variable so that we can edit it if needed.
# We need to edit it if the linked module cannot be found, so
# we can revert to panel model.
self
.
use_for_single_location_local
=
self
.
use_for_single_location
# We need to set the location here so the child modules can use it.
self
.
runtime
.
set
(
'location'
,
self
.
location
)
if
(
self
.
runtime
.
open_ended_grading_interface
):
self
.
peer_gs
=
PeerGradingService
(
self
.
system
.
open_ended_grading_interface
,
self
.
system
)
else
:
self
.
peer_gs
=
MockPeerGradingService
()
if
self
.
use_for_single_location
:
try
:
linked_descriptors
=
self
.
descriptor
.
get_required_module_descriptors
()
if
len
(
linked_descriptors
)
==
0
:
error_msg
=
"Peer grading module {0} is trying to use single problem mode without "
"a location specified."
.
format
(
self
.
location
)
log
.
error
(
error_msg
)
raise
InvalidLinkLocation
(
error_msg
)
if
self
.
use_for_single_location_local
:
linked_descriptors
=
self
.
descriptor
.
get_required_module_descriptors
()
if
len
(
linked_descriptors
)
==
0
:
error_msg
=
"Peer grading module {0} is trying to use single problem mode without "
"a location specified."
.
format
(
self
.
location
)
log
.
error
(
error_msg
)
# Change module over to panel mode from single problem mode.
self
.
use_for_single_location_local
=
False
else
:
self
.
linked_problem
=
self
.
system
.
get_module
(
linked_descriptors
[
0
])
except
ItemNotFoundError
:
log
.
error
(
"Linked location {0} for peer grading module {1} does not exist"
.
format
(
self
.
link_to_location
,
self
.
location
))
raise
except
NoPathToItem
:
log
.
error
(
"Linked location {0} for peer grading module {1} cannot be linked to."
.
format
(
self
.
link_to_location
,
self
.
location
))
raise
try
:
self
.
timeinfo
=
TimeInfo
(
self
.
due
,
self
.
graceperiod
)
...
...
@@ -175,7 +173,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
"""
if
self
.
closed
():
return
self
.
peer_grading_closed
()
if
not
self
.
use_for_single_location
:
if
not
self
.
use_for_single_location
_local
:
return
self
.
peer_grading
()
else
:
return
self
.
peer_grading_problem
({
'location'
:
self
.
link_to_location
})[
'html'
]
...
...
@@ -236,7 +234,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
'score'
:
score
,
'total'
:
max_score
,
}
if
not
self
.
use_for_single_location
or
not
self
.
graded
:
if
not
self
.
use_for_single_location
_local
or
not
self
.
graded
:
return
score_dict
try
:
...
...
@@ -270,7 +268,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
randomization, and 5/7 on another
'''
max_grade
=
None
if
self
.
use_for_single_location
and
self
.
graded
:
if
self
.
use_for_single_location
_local
and
self
.
graded
:
max_grade
=
self
.
weight
return
max_grade
...
...
@@ -492,7 +490,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
Show the Peer grading closed template
'''
html
=
self
.
system
.
render_template
(
'peer_grading/peer_grading_closed.html'
,
{
'use_for_single_location'
:
self
.
use_for_single_location
'use_for_single_location'
:
self
.
use_for_single_location
_local
})
return
html
...
...
@@ -578,7 +576,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
'error_text'
:
error_text
,
# Checked above
'staff_access'
:
False
,
'use_single_location'
:
self
.
use_for_single_location
,
'use_single_location'
:
self
.
use_for_single_location
_local
,
})
return
html
...
...
@@ -588,7 +586,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
Show individual problem interface
'''
if
data
is
None
or
data
.
get
(
'location'
)
is
None
:
if
not
self
.
use_for_single_location
:
if
not
self
.
use_for_single_location
_local
:
# This is an error case, because it must be set to use a single location to be called without get parameters
# This is a dev_facing_error
log
.
error
(
...
...
@@ -610,7 +608,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
# Checked above
'staff_access'
:
False
,
'track_changes'
:
getattr
(
module
,
'track_changes'
,
False
),
'use_single_location'
:
self
.
use_for_single_location
,
'use_single_location'
:
self
.
use_for_single_location
_local
,
})
return
{
'html'
:
html
,
'success'
:
True
}
...
...
@@ -656,10 +654,24 @@ class PeerGradingDescriptor(PeerGradingFields, RawDescriptor):
return
non_editable_fields
def
get_required_module_descriptors
(
self
):
"""Returns a list of XModuleDescritpor instances upon which this module depends, but are
not children of this module"""
"""
Returns a list of XModuleDescriptor instances upon which this module depends, but are
not children of this module.
"""
# If use_for_single_location is True, this is linked to an open ended problem.
if
self
.
use_for_single_location
:
return
[
self
.
system
.
load_item
(
self
.
link_to_location
)]
# Try to load the linked module.
# If we can't load it, return empty list to avoid exceptions on progress page.
try
:
linked_module
=
self
.
system
.
load_item
(
self
.
link_to_location
)
return
[
linked_module
]
except
(
NoPathToItem
,
ItemNotFoundError
):
error_message
=
(
"Cannot find the combined open ended module "
"at location {0} being linked to from peer "
"grading module {1}"
)
.
format
(
self
.
link_to_location
,
self
.
location
)
log
.
error
(
error_message
)
return
[]
else
:
return
[]
...
...
common/lib/xmodule/xmodule/tests/test_peer_grading.py
View file @
fd72005a
import
unittest
from
xmodule.modulestore
import
Location
from
.
import
get_test_system
from
test_util_open_ended
import
MockQueryDict
,
DummyModulestore
from
xmodule.open_ended_grading_classes.peer_grading_service
import
MockPeerGradingService
import
json
import
logging
from
mock
import
Mock
from
xmodule.peer_grading_module
import
PeerGradingModule
,
InvalidLinkLocation
from
xblock.field_data
import
DictFieldData
from
xblock.fields
import
ScopeIds
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
,
NoPathToItem
import
json
import
logging
from
xmodule.modulestore
import
Location
from
xmodule.tests
import
get_test_system
,
get_test_descriptor_system
from
xmodule.tests.test_util_open_ended
import
MockQueryDict
,
DummyModulestore
from
xmodule.open_ended_grading_classes.peer_grading_service
import
MockPeerGradingService
from
xmodule.peer_grading_module
import
PeerGradingModule
,
PeerGradingDescriptor
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
,
NoPathToItem
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -37,7 +38,7 @@ class PeerGradingModuleTest(unittest.TestCase, DummyModulestore):
'feedback'
:
""
,
'rubric_scores[]'
:
[
0
,
1
],
'submission_flagged'
:
False
,
'answer_unknown'
:
False
,
'answer_unknown'
:
False
,
})
def
setUp
(
self
):
...
...
@@ -57,22 +58,22 @@ class PeerGradingModuleTest(unittest.TestCase, DummyModulestore):
@return:
"""
closed
=
self
.
peer_grading
.
closed
()
self
.
assert
Equal
(
closed
,
False
)
self
.
assert
False
(
closed
)
def
test_get_html
(
self
):
"""
Test to see if the module can be rendered
@return:
"""
html
=
self
.
peer_grading
.
get_html
()
_
html
=
self
.
peer_grading
.
get_html
()
def
test_get_data
(
self
):
"""
Try getting data from the external grading service
@return:
"""
success
,
data
=
self
.
peer_grading
.
query_data_for_location
(
self
.
problem_location
.
url
())
self
.
assert
Equal
(
success
,
True
)
success
,
_
data
=
self
.
peer_grading
.
query_data_for_location
(
self
.
problem_location
.
url
())
self
.
assert
True
(
success
)
def
test_get_score
(
self
):
"""
...
...
@@ -80,7 +81,7 @@ class PeerGradingModuleTest(unittest.TestCase, DummyModulestore):
@return:
"""
score
=
self
.
peer_grading
.
get_score
()
self
.
assert
Equals
(
score
[
'score'
],
None
)
self
.
assert
IsNone
(
score
[
'score'
]
)
def
test_get_max_score
(
self
):
"""
...
...
@@ -95,7 +96,7 @@ class PeerGradingModuleTest(unittest.TestCase, DummyModulestore):
Test to see if we can get the next mock submission
@return:
"""
success
,
next_submission
=
self
.
peer_grading
.
get_next_submission
({
'location'
:
'blah'
})
success
,
_
next_submission
=
self
.
peer_grading
.
get_next_submission
({
'location'
:
'blah'
})
self
.
assertEqual
(
success
,
True
)
def
test_save_grade
(
self
):
...
...
@@ -111,9 +112,8 @@ class PeerGradingModuleTest(unittest.TestCase, DummyModulestore):
Check to see if the student has calibrated yet
@return:
"""
calibrated_dict
=
{
'location'
:
"blah"
}
response
=
self
.
peer_grading
.
is_student_calibrated
(
self
.
calibrated_dict
)
self
.
assert
Equal
(
response
[
'success'
],
True
)
self
.
assert
True
(
response
[
'success'
]
)
def
test_show_calibration_essay
(
self
):
"""
...
...
@@ -121,7 +121,7 @@ class PeerGradingModuleTest(unittest.TestCase, DummyModulestore):
@return:
"""
response
=
self
.
peer_grading
.
show_calibration_essay
(
self
.
calibrated_dict
)
self
.
assert
Equal
(
response
[
'success'
],
True
)
self
.
assert
True
(
response
[
'success'
]
)
def
test_save_calibration_essay
(
self
):
"""
...
...
@@ -129,7 +129,7 @@ class PeerGradingModuleTest(unittest.TestCase, DummyModulestore):
@return:
"""
response
=
self
.
peer_grading
.
save_calibration_essay
(
self
.
save_dict
)
self
.
assert
Equal
(
response
[
'success'
],
True
)
self
.
assert
True
(
response
[
'success'
]
)
def
test_peer_grading_problem
(
self
):
"""
...
...
@@ -137,7 +137,7 @@ class PeerGradingModuleTest(unittest.TestCase, DummyModulestore):
@return:
"""
response
=
self
.
peer_grading
.
peer_grading_problem
(
self
.
coe_dict
)
self
.
assert
Equal
(
response
[
'success'
],
True
)
self
.
assert
True
(
response
[
'success'
]
)
def
test___find_corresponding_module_for_location_exceptions
(
self
):
"""
...
...
@@ -146,7 +146,7 @@ class PeerGradingModuleTest(unittest.TestCase, DummyModulestore):
@return:
"""
with
self
.
assertRaises
(
ItemNotFoundError
):
self
.
peer_grading
.
_find_corresponding_module_for_location
(
Location
(
'i4x'
,
'a'
,
'b'
,
'c'
,
'd'
))
self
.
peer_grading
.
_find_corresponding_module_for_location
(
Location
(
'i4x'
,
'a'
,
'b'
,
'c'
,
'd'
))
def
test_get_instance_state
(
self
):
"""
...
...
@@ -155,6 +155,7 @@ class PeerGradingModuleTest(unittest.TestCase, DummyModulestore):
"""
self
.
peer_grading
.
get_instance_state
()
class
MockPeerGradingServiceProblemList
(
MockPeerGradingService
):
def
get_problem_list
(
self
,
course_id
,
grader_id
):
return
{
'success'
:
True
,
...
...
@@ -162,13 +163,16 @@ class MockPeerGradingServiceProblemList(MockPeerGradingService):
{
"num_graded"
:
3
,
"num_pending"
:
681
,
"num_required"
:
3
,
"location"
:
"i4x://edX/open_ended/combinedopenended/SampleQuestion"
,
"problem_name"
:
"Peer-Graded Essay"
},
]}
class
PeerGradingModuleScoredTest
(
unittest
.
TestCase
,
DummyModulestore
):
"""
Test peer grading xmodule at the unit level. More detailed tests are difficult, as the module relies on an
external grading service.
"""
problem_location
=
Location
([
"i4x"
,
"edX"
,
"open_ended"
,
"peergrading"
,
"PeerGradingScored"
])
problem_location
=
Location
(
[
"i4x"
,
"edX"
,
"open_ended"
,
"peergrading"
,
"PeerGradingScored"
]
)
def
setUp
(
self
):
"""
Create a peer grading module from a test system
...
...
@@ -180,7 +184,7 @@ class PeerGradingModuleScoredTest(unittest.TestCase, DummyModulestore):
def
test_metadata_load
(
self
):
peer_grading
=
self
.
get_module_from_location
(
self
.
problem_location
,
COURSE
)
self
.
assert
Equal
(
peer_grading
.
closed
(),
False
)
self
.
assert
False
(
peer_grading
.
closed
()
)
def
test_problem_list
(
self
):
"""
...
...
@@ -217,6 +221,37 @@ class PeerGradingModuleLinkedTest(unittest.TestCase, DummyModulestore):
self
.
test_system
.
open_ended_grading_interface
=
None
self
.
setup_modulestore
(
COURSE
)
@property
def
field_data
(
self
):
"""
Setup the proper field data for a peer grading module.
"""
return
DictFieldData
({
'data'
:
'<peergrading/>'
,
'location'
:
self
.
problem_location
,
'use_for_single_location'
:
True
,
'link_to_location'
:
self
.
coe_location
.
url
(),
'graded'
:
True
,
})
@property
def
scope_ids
(
self
):
"""
Return the proper scope ids for the peer grading module.
"""
return
ScopeIds
(
None
,
None
,
self
.
problem_location
,
self
.
problem_location
)
def
_create_peer_grading_descriptor_with_linked_problem
(
self
):
# Initialize the peer grading module.
system
=
get_test_descriptor_system
()
return
system
.
construct_xblock_from_class
(
PeerGradingDescriptor
,
field_data
=
self
.
field_data
,
scope_ids
=
self
.
scope_ids
)
def
_create_peer_grading_with_linked_problem
(
self
,
location
,
valid_linked_descriptor
=
True
):
"""
Create a peer grading problem with a linked location.
...
...
@@ -235,34 +270,56 @@ class PeerGradingModuleLinkedTest(unittest.TestCase, DummyModulestore):
else
:
pg_descriptor
.
get_required_module_descriptors
=
lambda
:
[]
# Setup the proper field data for the peer grading module.
field_data
=
DictFieldData
({
'data'
:
'<peergrading/>'
,
'location'
:
self
.
problem_location
,
'use_for_single_location'
:
True
,
'link_to_location'
:
self
.
coe_location
.
url
(),
'graded'
:
True
,
})
# Initialize the peer grading module.
peer_grading
=
PeerGradingModule
(
pg_descriptor
,
self
.
test_system
,
field_data
,
ScopeIds
(
None
,
None
,
self
.
problem_location
,
self
.
problem_location
)
self
.
field_data
,
self
.
scope_ids
,
)
return
peer_grading
def
_get_descriptor_with_invalid_link
(
self
,
exception_to_raise
):
"""
Ensure that a peer grading descriptor with an invalid link will return an empty list.
"""
# Create a descriptor, and make loading an item throw an error.
descriptor
=
self
.
_create_peer_grading_descriptor_with_linked_problem
()
descriptor
.
system
.
load_item
=
Mock
(
side_effect
=
exception_to_raise
)
# Ensure that modules is a list of length 0.
modules
=
descriptor
.
get_required_module_descriptors
()
self
.
assertIsInstance
(
modules
,
list
)
self
.
assertEqual
(
len
(
modules
),
0
)
def
test_descriptor_with_nopath
(
self
):
"""
Test to see if a descriptor with a NoPathToItem error when trying to get
its linked module behaves properly.
"""
self
.
_get_descriptor_with_invalid_link
(
NoPathToItem
)
def
test_descriptor_with_item_not_found
(
self
):
"""
Test to see if a descriptor with an ItemNotFound error when trying to get
its linked module behaves properly.
"""
self
.
_get_descriptor_with_invalid_link
(
ItemNotFoundError
)
def
test_invalid_link
(
self
):
"""
Ensure that a peer grading problem with no linked locations
raises an error
.
Ensure that a peer grading problem with no linked locations
stays in panel mode
.
"""
# Setup the peer grading module with no linked locations.
with
self
.
assertRaises
(
InvalidLinkLocation
):
self
.
_create_peer_grading_with_linked_problem
(
self
.
coe_location
,
valid_linked_descriptor
=
False
)
peer_grading
=
self
.
_create_peer_grading_with_linked_problem
(
self
.
coe_location
,
valid_linked_descriptor
=
False
)
self
.
assertFalse
(
peer_grading
.
use_for_single_location_local
)
self
.
assertTrue
(
peer_grading
.
use_for_single_location
)
def
test_linked_problem
(
self
):
"""
...
...
@@ -284,7 +341,7 @@ class PeerGradingModuleLinkedTest(unittest.TestCase, DummyModulestore):
peer_grading
=
self
.
_create_peer_grading_with_linked_problem
(
self
.
coe_location
)
# If we specify a location, it will render the problem for that location.
data
=
peer_grading
.
handle_ajax
(
'problem'
,
{
'location'
:
self
.
coe_location
})
data
=
peer_grading
.
handle_ajax
(
'problem'
,
{
'location'
:
self
.
coe_location
})
self
.
assertTrue
(
json
.
loads
(
data
)[
'success'
])
# If we don't specify a location, it should use the linked location.
...
...
@@ -344,5 +401,5 @@ class PeerGradingModuleTrackChangesTest(unittest.TestCase, DummyModulestore):
"""
self
.
peer_grading
.
_find_corresponding_module_for_location
=
self
.
mock_track_changes_problem
response
=
self
.
peer_grading
.
peer_grading_problem
({
'location'
:
'mocked'
})
self
.
assert
Equal
(
response
[
'success'
],
True
)
self
.
assert
True
(
response
[
'success'
]
)
self
.
assertIn
(
"'track_changes': True"
,
response
[
'html'
])
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment