Commit b224f4e8 by Brian Wilson

move test_tasks to test_integration.

parent c48dabc3
......@@ -10,8 +10,6 @@ from student.tests.factories import CourseEnrollmentAllowedFactory as StudentCou
from student.tests.factories import RegistrationFactory as StudentRegistrationFactory
from courseware.models import StudentModule, XModuleContentField, XModuleSettingsField
from courseware.models import XModuleStudentInfoField, XModuleStudentPrefsField
from courseware.models import CourseTask
from celery.states import PENDING
from xmodule.modulestore import Location
from pytz import UTC
......@@ -86,16 +84,3 @@ class StudentInfoFactory(DjangoModelFactory):
field_name = 'existing_field'
value = json.dumps('old_value')
student = SubFactory(UserFactory)
class CourseTaskFactory(DjangoModelFactory):
FACTORY_FOR = CourseTask
task_type = 'rescore_problem'
course_id = "MITx/999/Robot_Super_Course"
task_input = json.dumps({})
task_key = None
task_id = None
task_state = PENDING
task_output = None
requester = SubFactory(UserFactory)
......@@ -25,7 +25,6 @@ from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError
from courseware import grades
from instructor_task import api as task_api
from courseware.access import (has_access, get_access_group_name,
course_beta_test_group_name)
from courseware.courses import get_course_with_access
......@@ -36,6 +35,13 @@ from django_comment_common.models import (Role,
FORUM_ROLE_COMMUNITY_TA)
from django_comment_client.utils import has_forum_access
from instructor.offline_gradecalc import student_grades, offline_grades_available
from instructor_task.api import (get_running_instructor_tasks,
get_instructor_task_history,
submit_rescore_problem_for_all_students,
submit_rescore_problem_for_student,
submit_reset_problem_attempts_for_all_students,
submit_delete_problem_state_for_all_students)
from instructor_task.views import get_task_completion_info
from mitxmako.shortcuts import render_to_response
from psychometrics import psychoanalyze
from student.models import CourseEnrollment, CourseEnrollmentAllowed
......@@ -69,7 +75,7 @@ def instructor_dashboard(request, course_id):
msg = ''
problems = []
plots = []
datatable = None
datatable = {}
# the instructor dashboard page is modal: grades, psychometrics, admin
# keep that state in request.session (defaults to grades mode)
......@@ -250,8 +256,8 @@ def instructor_dashboard(request, course_id):
problem_urlname = request.POST.get('problem_for_all_students', '')
problem_url = get_module_url(problem_urlname)
try:
course_task = task_api.submit_rescore_problem_for_all_students(request, course_id, problem_url)
if course_task is None:
instructor_task = submit_rescore_problem_for_all_students(request, course_id, problem_url)
if instructor_task is None:
msg += '<font color="red">Failed to create a background task for rescoring "{0}".</font>'.format(problem_url)
else:
track_msg = 'rescore problem {problem} for all students in {course}'.format(problem=problem_url, course=course_id)
......@@ -266,8 +272,8 @@ def instructor_dashboard(request, course_id):
problem_urlname = request.POST.get('problem_for_all_students', '')
problem_url = get_module_url(problem_urlname)
try:
course_task = task_api.submit_reset_problem_attempts_for_all_students(request, course_id, problem_url)
if course_task is None:
instructor_task = submit_reset_problem_attempts_for_all_students(request, course_id, problem_url)
if instructor_task is None:
msg += '<font color="red">Failed to create a background task for resetting "{0}".</font>'.format(problem_url)
else:
track_msg = 'reset problem {problem} for all students in {course}'.format(problem=problem_url, course=course_id)
......@@ -288,18 +294,14 @@ def instructor_dashboard(request, course_id):
else:
problem_urlname = request.POST.get('problem_for_student', '')
problem_url = get_module_url(problem_urlname)
message, task_datatable = get_background_task_table(course_id, problem_url, student)
message, datatable = get_background_task_table(course_id, problem_url, student)
msg += message
if task_datatable is not None:
datatable = task_datatable
elif "Show Background Task History" in action:
problem_urlname = request.POST.get('problem_for_all_students', '')
problem_url = get_module_url(problem_urlname)
message, task_datatable = get_background_task_table(course_id, problem_url)
message, datatable = get_background_task_table(course_id, problem_url)
msg += message
if task_datatable is not None:
datatable = task_datatable
elif ("Reset student's attempts" in action or
"Delete student state for module" in action or
......@@ -357,8 +359,8 @@ def instructor_dashboard(request, course_id):
else:
# "Rescore student's problem submission" case
try:
course_task = task_api.submit_rescore_problem_for_student(request, course_id, module_state_key, student)
if course_task is None:
instructor_task = submit_rescore_problem_for_student(request, course_id, module_state_key, student)
if instructor_task is None:
msg += '<font color="red">Failed to create a background task for rescoring "{0}" for student {1}.</font>'.format(module_state_key, unique_student_identifier)
else:
track_msg = 'rescore problem {problem} for student {student} in {course}'.format(problem=module_state_key, student=unique_student_identifier, course=course_id)
......@@ -721,13 +723,14 @@ def instructor_dashboard(request, course_id):
msg += "<br/><font color='orange'>Grades from %s</font>" % offline_grades_available(course_id)
# generate list of pending background tasks
if settings.MITX_FEATURES.get('ENABLE_COURSE_BACKGROUND_TASKS'):
course_tasks = task_api.get_running_course_tasks(course_id)
if settings.MITX_FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
instructor_tasks = get_running_instructor_tasks(course_id)
else:
course_tasks = None
instructor_tasks = None
# display course stats only if there is no other table to display:
course_stats = None
if datatable is None:
if not datatable:
course_stats = get_course_stats_table()
#----------------------------------------
# context for rendering
......@@ -744,7 +747,7 @@ def instructor_dashboard(request, course_id):
'problems': problems, # psychometrics
'plots': plots, # psychometrics
'course_errors': modulestore().get_item_errors(course.location),
'course_tasks': course_tasks,
'instructor_tasks': instructor_tasks,
'djangopid': os.getpid(),
'mitx_version': getattr(settings, 'MITX_VERSION_STRING', ''),
'offline_grade_log': offline_grades_available(course_id),
......@@ -1299,8 +1302,8 @@ def get_background_task_table(course_id, problem_url, student=None):
Returns a tuple of (msg, datatable), where the msg is a possible error message,
and the datatable is the datatable to be used for display.
"""
history_entries = task_api.get_instructor_task_history(course_id, problem_url, student)
datatable = None
history_entries = get_instructor_task_history(course_id, problem_url, student)
datatable = {}
msg = ""
# first check to see if there is any history at all
# (note that we don't have to check that the arguments are valid; it
......@@ -1312,7 +1315,6 @@ def get_background_task_table(course_id, problem_url, student=None):
else:
msg += '<font color="red">Failed to find any background tasks for course "{course}" and module "{problem}".</font>'.format(course=course_id, problem=problem_url)
else:
datatable = {}
datatable['header'] = ["Task Type",
"Task Id",
"Requester",
......@@ -1323,23 +1325,23 @@ def get_background_task_table(course_id, problem_url, student=None):
"Task Output"]
datatable['data'] = []
for course_task in history_entries:
for instructor_task in history_entries:
# get duration info, if known:
duration_ms = 'unknown'
if hasattr(course_task, 'task_output'):
task_output = json.loads(course_task.task_output)
if hasattr(instructor_task, 'task_output'):
task_output = json.loads(instructor_task.task_output)
if 'duration_ms' in task_output:
duration_ms = task_output['duration_ms']
# get progress status message:
success, task_message = task_submit.get_task_completion_info(course_task)
success, task_message = get_task_completion_info(instructor_task)
status = "Complete" if success else "Incomplete"
# generate row for this task:
row = [str(course_task.task_type),
str(course_task.task_id),
str(course_task.requester),
course_task.created.isoformat(' '),
row = [str(instructor_task.task_type),
str(instructor_task.task_id),
str(instructor_task.requester),
instructor_task.created.isoformat(' '),
duration_ms,
str(course_task.task_state),
str(instructor_task.task_state),
status,
task_message]
datatable['data'].append(row)
......
......@@ -10,13 +10,13 @@
<script type="text/javascript" src="${static.url('js/vendor/jquery-jvectormap-1.1.1/jquery-jvectormap-world-mill-en.js')}"></script>
<script type="text/javascript" src="${static.url('js/course_groups/cohorts.js')}"></script>
%if course_tasks is not None:
%if instructor_tasks is not None:
<script type="text/javascript">
// Define a CourseTaskProgress object for updating a table on the instructor
// Define an InstructorTaskProgress object for updating a table on the instructor
// dashboard that shows the current background tasks that are currently running
// for the instructor's course. Any tasks that were running when the page is
// first displayed are passed in as course_tasks, and populate the "Pending Course
// Task" table. The CourseTaskProgress is bound to this table, and periodically
// first displayed are passed in as instructor_tasks, and populate the "Pending Instructor
// Task" table. The InstructorTaskProgress is bound to this table, and periodically
// polls the LMS to see if any of the tasks has completed. Once a task is complete,
// it is not included in any further polling.
......@@ -24,7 +24,7 @@
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
this.CourseTaskProgress = (function() {
this.InstructorTaskProgress = (function() {
// Hardcode the refresh interval to be every five seconds.
// TODO: allow the refresh interval to be set. (And if it is disabled,
......@@ -34,7 +34,7 @@
// Hardcode the initial delay before the first refresh to two seconds:
var initial_refresh_delay = 2000;
function CourseTaskProgress(element) {
function InstructorTaskProgress(element) {
this.update_progress = __bind(this.update_progress, this);
this.get_status = __bind(this.get_status, this);
this.element = element;
......@@ -42,14 +42,14 @@
if (window.queuePollerID) {
window.clearTimeout(window.queuePollerID);
}
return window.queuePollerID = window.setTimeout(this.get_status, this.initial_refresh_delay);
window.queuePollerID = window.setTimeout(this.get_status, this.initial_refresh_delay);
}
CourseTaskProgress.prototype.$ = function(selector) {
InstructorTaskProgress.prototype.$ = function(selector) {
return $(selector, this.element);
};
CourseTaskProgress.prototype.update_progress = function(response) {
InstructorTaskProgress.prototype.update_progress = function(response) {
var _this = this;
// Response should be a dict with an entry for each requested task_id,
// with a "task-state" and "in_progress" key and optionally a "message"
......@@ -75,13 +75,13 @@
// if some entries are still incomplete, then repoll:
if (something_in_progress) {
return window.queuePollerID = window.setTimeout(_this.get_status, _this.refresh_interval);
window.queuePollerID = window.setTimeout(_this.get_status, _this.refresh_interval);
} else {
delete window.queuePollerID;
}
}
CourseTaskProgress.prototype.get_status = function() {
InstructorTaskProgress.prototype.get_status = function() {
var _this = this;
var task_ids = [];
......@@ -99,20 +99,20 @@
// Note that the keyname here ends up with "[]" being appended
// in the POST parameter that shows up on the Django server.
// TODO: add error handler.
var ajax_url = '/course_task_log_status/';
var ajax_url = '/instructor_task_status/';
var data = {'task_ids': task_ids };
$.post(ajax_url, data).done(this.update_progress);
};
return CourseTaskProgress;
return InstructorTaskProgress;
})();
}).call(this);
// once the page is rendered, create the progress object
var courseTaskProgress;
var instructorTaskProgress;
$(document).ready(function() {
courseTaskProgress = new CourseTaskProgress($('#task-progress-wrapper'));
instructorTaskProgress = new InstructorTaskProgress($('#task-progress-wrapper'));
});
</script>
......@@ -302,7 +302,7 @@ function goto( mode)
<hr width="40%" style="align:left">
%endif
%if settings.MITX_FEATURES.get('ENABLE_COURSE_BACKGROUND_TASKS'):
%if settings.MITX_FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
<H2>Course-specific grade adjustment</h2>
<p>
......@@ -713,13 +713,13 @@ function goto( mode)
<table class="stat_table">
<tr>
%for hname in datatable['header']:
<th>${hname}</th>
<th>${hname | h}</th>
%endfor
</tr>
%for row in datatable['data']:
<tr>
%for value in row:
<td>${value}</td>
<td>${value | h}</td>
%endfor
</tr>
%endfor
......@@ -729,9 +729,9 @@ function goto( mode)
## Output tasks in progress
%if course_tasks is not None and len(course_tasks) > 0:
%if instructor_tasks is not None and len(instructor_tasks) > 0:
<hr width="100%">
<h2>Pending Course Tasks</h2>
<h2>Pending Instructor Tasks</h2>
<div id="task-progress-wrapper">
<table class="stat_table">
<tr>
......@@ -744,16 +744,16 @@ function goto( mode)
<th>Duration (ms)</th>
<th>Task Progress</th>
</tr>
%for tasknum, course_task in enumerate(course_tasks):
%for tasknum, instructor_task in enumerate(instructor_tasks):
<tr id="task-progress-entry-${tasknum}" class="task-progress-entry"
data-task-id="${course_task.task_id}"
data-task-id="${instructor_task.task_id}"
data-in-progress="true">
<td>${course_task.task_type}</td>
<td>${course_task.task_input}</td>
<td class="task-id">${course_task.task_id}</td>
<td>${course_task.requester}</td>
<td>${course_task.created}</td>
<td class="task-state">${course_task.task_state}</td>
<td>${instructor_task.task_type}</td>
<td>${instructor_task.task_input}</td>
<td class="task-id">${instructor_task.task_id}</td>
<td>${instructor_task.requester}</td>
<td>${instructor_task.created}</td>
<td class="task-state">${instructor_task.task_state}</td>
<td class="task-duration">unknown</td>
<td class="task-progress">unknown</td>
</tr>
......@@ -772,11 +772,11 @@ function goto( mode)
<br/>
<p>
<hr width="100%">
<h2>${course_stats['title']}</h2>
<h2>${course_stats['title'] | h}</h2>
<table class="stat_table">
<tr>
%for hname in course_stats['header']:
<th>${hname}</th>
<th>${hname | h}</th>
%endfor
</tr>
%for row in course_stats['data']:
......
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