Commit 1a4fcb05 by Sarina Canelake

Make SPOC gradebook an API implementation

rather than just hacked in to the instructor_dashboard base file.
Also move the tests from the legacy implementation to the new dash API implementation.
parent d01af063
"""
Tests of the instructor dashboard gradebook
Tests of the instructor dashboard spoc gradebook
"""
from django.test.utils import override_settings
......@@ -10,7 +10,6 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from courseware.tests.tests import TEST_DATA_MIXED_MODULESTORE
from capa.tests.response_xml_factory import StringResponseXMLFactory
from courseware.tests.factories import StudentModuleFactory
from xmodule.modulestore import Location
from xmodule.modulestore.django import modulestore
......@@ -19,6 +18,11 @@ USER_COUNT = 11
@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
class TestGradebook(ModuleStoreTestCase):
"""
Test functionality of the spoc gradebook. Sets up a course with assignments and
students who've scored various scores on these assignments. Base class for further
gradebook tests.
"""
grading_policy = None
def setUp(self):
......@@ -68,7 +72,7 @@ class TestGradebook(ModuleStoreTestCase):
)
self.response = self.client.get(reverse(
'gradebook_legacy',
'spoc_gradebook',
args=(self.course.id.to_deprecated_string(),)
))
......@@ -77,6 +81,10 @@ class TestGradebook(ModuleStoreTestCase):
class TestDefaultGradingPolicy(TestGradebook):
"""
Tests that the grading policy is properly applied for all users in the course
Uses the default policy (50% passing rate)
"""
def test_all_users_listed(self):
for user in self.users:
self.assertIn(user.username, unicode(self.response.content, 'utf-8'))
......@@ -98,6 +106,10 @@ class TestDefaultGradingPolicy(TestGradebook):
class TestLetterCutoffPolicy(TestGradebook):
"""
Tests advanced grading policy (with letter grade cutoffs). Includes tests of
UX display (color, etc).
"""
grading_policy = {
"GRADER": [
{
......
......@@ -31,7 +31,7 @@ from django_comment_common.models import (
FORUM_ROLE_MODERATOR,
FORUM_ROLE_COMMUNITY_TA,
)
from edxmako.shortcuts import render_to_response
from courseware.models import StudentModule
from student.models import CourseEnrollment, unique_id_for_user, anonymous_id_for_user
import instructor_task.api
......@@ -46,6 +46,7 @@ from instructor.enrollment import (
unenroll_email
)
from instructor.access import list_with_level, allow_access, revoke_access, update_forum_role
from instructor.offline_gradecalc import student_grades
import analytics.basic
import analytics.distributions
import analytics.csvs
......@@ -1306,3 +1307,43 @@ def _split_input_list(str_list):
new_list = [s for s in new_list if s != '']
return new_list
#---- Gradebook (shown to small courses only) ----
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
def spoc_gradebook(request, course_id):
"""
Show the gradebook for this course:
- Only shown for courses with enrollment < settings.FEATURES.get("MAX_ENROLLMENT_INSTR_BUTTONS")
- Only displayed to course staff
"""
course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
course = get_course_with_access(request.user, 'staff', course_key, depth=None)
enrolled_students = User.objects.filter(
courseenrollment__course_id=course_key,
courseenrollment__is_active=1
).order_by('username').select_related("profile")
# possible extension: implement pagination to show to large courses
student_info = [
{
'username': student.username,
'id': student.id,
'email': student.email,
'grade_summary': student_grades(student, request, course),
'realname': student.profile.name,
}
for student in enrolled_students
]
return render_to_response('courseware/gradebook.html', {
'students': student_info,
'course': course,
'course_id': course_key,
# Checked above
'staff_access': True,
'ordered_grades': sorted(course.grade_cutoffs.items(), key=lambda i: i[1], reverse=True),
})
......@@ -53,4 +53,8 @@ urlpatterns = patterns('', # nopep8
'instructor.views.api.list_report_downloads', name="list_report_downloads"),
url(r'calculate_grades_csv$',
'instructor.views.api.calculate_grades_csv', name="calculate_grades_csv"),
# spoc gradebook
url(r'^gradebook$',
'instructor.views.api.spoc_gradebook', name='spoc_gradebook'),
)
......@@ -23,7 +23,6 @@ from courseware.access import has_access
from courseware.courses import get_course_by_id, get_cms_course_link, get_course_with_access
from django_comment_client.utils import has_forum_access
from django_comment_common.models import FORUM_ROLE_ADMINISTRATOR
from instructor.offline_gradecalc import student_grades
from student.models import CourseEnrollment
from bulk_email.models import CourseAuthorization
from class_dashboard.dashboard_data import get_section_display_name, get_array_section_has_problem
......@@ -263,44 +262,3 @@ def _section_metrics(course_key, access):
'post_metrics_data_csv_url': reverse('post_metrics_data_csv'),
}
return section_data
#---- Gradebook (shown to small courses only) ----
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
def spoc_gradebook(request, course_id):
"""
Show the gradebook for this course:
- Only shown for courses with enrollment < settings.FEATURES.get("MAX_ENROLLMENT_INSTR_BUTTONS")
- Only displayed to course staff
"""
course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
course = get_course_with_access(request.user, 'staff', course_key, depth=None)
enrolled_students = User.objects.filter(
courseenrollment__course_id=course_key,
courseenrollment__is_active=1
).order_by('username').select_related("profile")
# TODO (vshnayder): implement pagination to show to large courses
max_num_students = settings.FEATURES.get("MAX_ENROLLMENT_INSTR_BUTTONS")
enrolled_students = enrolled_students[:max_num_students] # HACK!
student_info = [
{
'username': student.username,
'id': student.id,
'email': student.email,
'grade_summary': student_grades(student, request, course),
'realname': student.profile.name,
}
for student in enrolled_students
]
return render_to_response('courseware/gradebook.html', {
'students': student_info,
'course': course,
'course_id': course_key,
# Checked above
'staff_access': True,
'ordered_grades': sorted(course.grade_cutoffs.items(), key=lambda i: i[1], reverse=True),
})
......@@ -273,8 +273,6 @@ if settings.COURSEWARE_ENABLED:
'instructor.views.instructor_dashboard.instructor_dashboard_2', name="instructor_dashboard"),
url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/instructor/api/',
include('instructor.views.api_urls')),
url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/gradebook$',
'instructor.views.instructor_dashboard.spoc_gradebook', name='spoc_gradebook'),
# see ENABLE_INSTRUCTOR_LEGACY_DASHBOARD section for legacy dash urls
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment