Asynchronous download button for ORA2 data
Conflicts: lms/djangoapps/instructor/tests/test_api.py lms/djangoapps/instructor/utils.py lms/djangoapps/instructor/views/api.py lms/djangoapps/instructor/views/api_urls.py lms/djangoapps/instructor/views/instructor_dashboard.py lms/djangoapps/instructor_task/api.py lms/djangoapps/instructor_task/tasks.py lms/djangoapps/instructor_task/tasks_helper.py lms/djangoapps/instructor_task/tests/test_api.py lms/djangoapps/instructor_task/tests/test_tasks.py lms/djangoapps/instructor_task/tests/test_tasks_helper.py lms/envs/aws.py lms/envs/common.py lms/static/coffee/src/instructor_dashboard/data_download.coffee lms/templates/instructor/instructor_dashboard_2/data_download.html
This commit is contained in:
committed by
Eric Fischer
parent
2c3b728c08
commit
2b1a7eece2
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Test for LMS instructor background task queue management
|
||||
"""
|
||||
from mock import patch, Mock
|
||||
from mock import patch, Mock, MagicMock
|
||||
from bulk_email.models import CourseEmail, SEND_TO_ALL
|
||||
from courseware.tests.factories import UserFactory
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
@@ -22,16 +22,20 @@ from instructor_task.api import (
|
||||
submit_executive_summary_report,
|
||||
submit_course_survey_report,
|
||||
generate_certificates_for_students,
|
||||
regenerate_certificates
|
||||
regenerate_certificates,
|
||||
submit_export_ora2_data,
|
||||
)
|
||||
|
||||
from instructor_task.api_helper import AlreadyRunningError
|
||||
from instructor_task.models import InstructorTask, PROGRESS
|
||||
from instructor_task.tests.test_base import (InstructorTaskTestCase,
|
||||
InstructorTaskCourseTestCase,
|
||||
InstructorTaskModuleTestCase,
|
||||
TestReportMixin,
|
||||
TEST_COURSE_KEY)
|
||||
from instructor_task.tasks import export_ora2_data
|
||||
from instructor_task.tests.test_base import (
|
||||
InstructorTaskTestCase,
|
||||
InstructorTaskCourseTestCase,
|
||||
InstructorTaskModuleTestCase,
|
||||
TestReportMixin,
|
||||
TEST_COURSE_KEY,
|
||||
)
|
||||
from certificates.models import CertificateStatuses, CertificateGenerationHistory
|
||||
|
||||
|
||||
@@ -256,6 +260,16 @@ class InstructorTaskCourseSubmitTest(TestReportMixin, InstructorTaskCourseTestCa
|
||||
)
|
||||
self._test_resubmission(api_call)
|
||||
|
||||
def test_submit_ora2_request_task(self):
|
||||
request = self.create_task_request(self.instructor)
|
||||
|
||||
with patch('instructor_task.api.submit_task') as mock_submit_task:
|
||||
mock_submit_task.return_value = MagicMock()
|
||||
submit_export_ora2_data(request, self.course.id)
|
||||
|
||||
mock_submit_task.assert_called_once_with(
|
||||
request, 'export_ora2_data', export_ora2_data, self.course.id, {}, '')
|
||||
|
||||
def test_submit_generate_certs_students(self):
|
||||
"""
|
||||
Tests certificates generation task submission api
|
||||
|
||||
@@ -11,6 +11,8 @@ from uuid import uuid4
|
||||
from mock import Mock, MagicMock, patch
|
||||
|
||||
from celery.states import SUCCESS, FAILURE
|
||||
from django.utils.translation import ugettext_noop
|
||||
from functools import partial
|
||||
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
from opaque_keys.edx.locations import i4xEncoder
|
||||
@@ -27,8 +29,12 @@ from instructor_task.tasks import (
|
||||
reset_problem_attempts,
|
||||
delete_problem_state,
|
||||
generate_certificates,
|
||||
export_ora2_data,
|
||||
)
|
||||
from instructor_task.tasks_helper import (
|
||||
UpdateProblemModuleStateError,
|
||||
upload_ora2_data,
|
||||
)
|
||||
from instructor_task.tasks_helper import UpdateProblemModuleStateError
|
||||
|
||||
PROBLEM_URL_NAME = "test_urlname"
|
||||
|
||||
@@ -471,3 +477,31 @@ class TestCertificateGenerationnstructorTask(TestInstructorTasks):
|
||||
expected_attempted=1,
|
||||
expected_total=1
|
||||
)
|
||||
|
||||
|
||||
class TestOra2ResponsesInstructorTask(TestInstructorTasks):
|
||||
"""Tests instructor task that fetches ora2 response data."""
|
||||
|
||||
def test_ora2_missing_current_task(self):
|
||||
self._test_missing_current_task(export_ora2_data)
|
||||
|
||||
def test_ora2_with_failure(self):
|
||||
self._test_run_with_failure(export_ora2_data, 'We expected this to fail')
|
||||
|
||||
def test_ora2_with_long_error_msg(self):
|
||||
self._test_run_with_long_error_msg(export_ora2_data)
|
||||
|
||||
def test_ora2_with_short_error_msg(self):
|
||||
self._test_run_with_short_error_msg(export_ora2_data)
|
||||
|
||||
def test_ora2_runs_task(self):
|
||||
task_entry = self._create_input_entry()
|
||||
task_xmodule_args = self._get_xmodule_instance_args()
|
||||
|
||||
with patch('instructor_task.tasks.run_main_task') as mock_main_task:
|
||||
export_ora2_data(task_entry.id, task_xmodule_args)
|
||||
|
||||
action_name = ugettext_noop('generated')
|
||||
task_fn = partial(upload_ora2_data, task_xmodule_args)
|
||||
|
||||
mock_main_task.assert_called_once_with_args(task_entry.id, task_fn, action_name)
|
||||
|
||||
@@ -3,10 +3,18 @@
|
||||
"""
|
||||
Unit tests for LMS instructor-initiated background tasks helper functions.
|
||||
|
||||
Tests that CSV grade report generation works with unicode emails.
|
||||
- Tests that CSV grade report generation works with unicode emails.
|
||||
- Tests all of the existing reports.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
import urllib
|
||||
|
||||
import ddt
|
||||
from freezegun import freeze_time
|
||||
from mock import Mock, patch
|
||||
import tempfile
|
||||
import json
|
||||
@@ -22,6 +30,15 @@ from course_modes.models import CourseMode
|
||||
from courseware.tests.factories import InstructorFactory
|
||||
from instructor_task.tests.test_base import InstructorTaskCourseTestCase, TestReportMixin, InstructorTaskModuleTestCase
|
||||
from openedx.core.djangoapps.course_groups.models import CourseUserGroupPartitionGroup, CohortMembership
|
||||
from django.conf import settings
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from pytz import UTC
|
||||
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
from student.tests.factories import UserFactory
|
||||
from student.models import CourseEnrollment
|
||||
from xmodule.partitions.partitions import Group, UserPartition
|
||||
|
||||
from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory
|
||||
import openedx.core.djangoapps.user_api.course_tag.api as course_tag_api
|
||||
from openedx.core.djangoapps.user_api.partition_schemes import RandomUserPartitionScheme
|
||||
@@ -45,6 +62,9 @@ from instructor_task.tasks_helper import (
|
||||
upload_exec_summary_report,
|
||||
upload_course_survey_report,
|
||||
generate_students_certificates,
|
||||
upload_ora2_data,
|
||||
UPDATE_STATUS_FAILED,
|
||||
UPDATE_STATUS_SUCCEEDED,
|
||||
)
|
||||
from instructor_analytics.basic import UNAVAILABLE
|
||||
from openedx.core.djangoapps.util.testing import ContentGroupTestCase, TestConditionalContent
|
||||
@@ -2012,3 +2032,56 @@ class TestCertificateGeneration(InstructorTaskModuleTestCase):
|
||||
},
|
||||
result
|
||||
)
|
||||
|
||||
|
||||
class TestInstructorOra2Report(SharedModuleStoreTestCase):
|
||||
"""
|
||||
Tests that ORA2 response report generation works.
|
||||
"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestInstructorOra2Report, cls).setUpClass()
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
def setUp(self):
|
||||
super(TestInstructorOra2Report, self).setUp()
|
||||
|
||||
self.current_task = Mock()
|
||||
self.current_task.update_state = Mock()
|
||||
|
||||
def tearDown(self):
|
||||
super(TestInstructorOra2Report, self).tearDown()
|
||||
if os.path.exists(settings.GRADES_DOWNLOAD['ROOT_PATH']):
|
||||
shutil.rmtree(settings.GRADES_DOWNLOAD['ROOT_PATH'])
|
||||
|
||||
def test_report_fails_if_error(self):
|
||||
with patch('instructor_task.tasks_helper.OraAggregateData.collect_ora2_data') as mock_collect_data:
|
||||
mock_collect_data.side_effect = KeyError
|
||||
|
||||
with patch('instructor_task.tasks_helper._get_current_task') as mock_current_task:
|
||||
mock_current_task.return_value = self.current_task
|
||||
|
||||
response = upload_ora2_data(None, None, self.course.id, None, 'generated')
|
||||
self.assertEqual(response, UPDATE_STATUS_FAILED)
|
||||
|
||||
@freeze_time('2001-01-01 00:00:00')
|
||||
def test_report_stores_results(self):
|
||||
test_header = ['field1', 'field2']
|
||||
test_rows = [['row1_field1', 'row1_field2'], ['row2_field1', 'row2_field2']]
|
||||
|
||||
with patch('instructor_task.tasks_helper._get_current_task') as mock_current_task:
|
||||
mock_current_task.return_value = self.current_task
|
||||
|
||||
with patch('instructor_task.tasks_helper.OraAggregateData.collect_ora2_data') as mock_collect_data:
|
||||
mock_collect_data.return_value = (test_header, test_rows)
|
||||
|
||||
with patch('instructor_task.models.LocalFSReportStore.store_rows') as mock_store_rows:
|
||||
return_val = upload_ora2_data(None, None, self.course.id, None, 'generated')
|
||||
|
||||
# pylint: disable=maybe-no-member
|
||||
timestamp_str = datetime.now(UTC).strftime('%Y-%m-%d-%H%M')
|
||||
course_id_string = urllib.quote(self.course.id.to_deprecated_string().replace('/', '_'))
|
||||
filename = u'{}_ORA_data_{}.csv'.format(course_id_string, timestamp_str)
|
||||
|
||||
self.assertEqual(return_val, UPDATE_STATUS_SUCCEEDED)
|
||||
mock_store_rows.assert_called_once_with(self.course.id, filename, [test_header] + test_rows)
|
||||
|
||||
Reference in New Issue
Block a user