""" Integration Test for LMS instructor-initiated background tasks Runs tasks on answers to course problems to validate that code paths actually work. """ import logging import json from mock import Mock from django.contrib.auth.models import User from django.test.utils import override_settings from capa.tests.response_xml_factory import OptionResponseXMLFactory from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from student.tests.factories import CourseEnrollmentFactory, UserFactory from courseware.model_data import StudentModule from courseware.tests.tests import LoginEnrollmentTestCase, TEST_DATA_MONGO_MODULESTORE from instructor_task.views import instructor_task_status log = logging.getLogger(__name__) TEST_COURSE_ORG = 'edx' TEST_COURSE_NAME = 'Test Course' TEST_COURSE_NUMBER = '1.23x' TEST_SECTION_NAME = "Problem" @override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) class InstructorTaskTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase): """ Base test class for InstructorTask-related tests that require the setup of a course and problem. """ course = None current_user = None def initialize_course(self): """Create a course in the store, with a chapter and section.""" self.module_store = modulestore() # Create the course self.course = CourseFactory.create(org=TEST_COURSE_ORG, number=TEST_COURSE_NUMBER, display_name=TEST_COURSE_NAME) # Add a chapter to the course chapter = ItemFactory.create(parent_location=self.course.location, display_name=TEST_SECTION_NAME) # add a sequence to the course to which the problems can be added self.problem_section = ItemFactory.create(parent_location=chapter.location, template='i4x://edx/templates/sequential/Empty', display_name=TEST_SECTION_NAME) @staticmethod def get_user_email(username): """Generate email address based on username""" return '{0}@test.com'.format(username) def login_username(self, username): """Login the user, given the `username`.""" if self.current_user != username: self.login(InstructorTaskTestCase.get_user_email(username), "test") self.current_user = username def _create_user(self, username, is_staff=False): """Creates a user and enrolls them in the test course.""" email = InstructorTaskTestCase.get_user_email(username) UserFactory.create(username=username, email=email, is_staff=is_staff) thisuser = User.objects.get(username=username) CourseEnrollmentFactory.create(user=thisuser, course_id=self.course.id) return thisuser def create_instructor(self, username): """Creates an instructor for the test course.""" return self._create_user(username, is_staff=True) def create_student(self, username): """Creates a student for the test course.""" return self._create_user(username, is_staff=False) @staticmethod def problem_location(problem_url_name): """ Create an internal location for a test problem. """ if "i4x:" in problem_url_name: return problem_url_name else: return "i4x://{org}/{number}/problem/{problem_url_name}".format(org=TEST_COURSE_ORG, number=TEST_COURSE_NUMBER, problem_url_name=problem_url_name) def define_option_problem(self, problem_url_name): """Create the problem definition so the answer is Option 1""" factory = OptionResponseXMLFactory() factory_args = {'question_text': 'The correct answer is Option 1', 'options': ['Option 1', 'Option 2'], 'correct_option': 'Option 1', 'num_responses': 2} problem_xml = factory.build_xml(**factory_args) ItemFactory.create(parent_location=self.problem_section.location, template="i4x://edx/templates/problem/Blank_Common_Problem", display_name=str(problem_url_name), data=problem_xml) def redefine_option_problem(self, problem_url_name): """Change the problem definition so the answer is Option 2""" factory = OptionResponseXMLFactory() factory_args = {'question_text': 'The correct answer is Option 2', 'options': ['Option 1', 'Option 2'], 'correct_option': 'Option 2', 'num_responses': 2} problem_xml = factory.build_xml(**factory_args) location = InstructorTaskTestCase.problem_location(problem_url_name) self.module_store.update_item(location, problem_xml) def get_student_module(self, username, descriptor): """Get StudentModule object for test course, given the `username` and the problem's `descriptor`.""" return StudentModule.objects.get(course_id=self.course.id, student=User.objects.get(username=username), module_type=descriptor.location.category, module_state_key=descriptor.location.url(), ) def get_task_status(self, task_id): """Use api method to fetch task status, using mock request.""" mock_request = Mock() mock_request.REQUEST = {'task_id': task_id} response = instructor_task_status(mock_request) status = json.loads(response.content) return status def create_task_request(self, requester_username): """Generate request that can be used for submitting tasks""" request = Mock() request.user = User.objects.get(username=requester_username) request.get_host = Mock(return_value="testhost") request.META = {'REMOTE_ADDR': '0:0:0:0', 'SERVER_NAME': 'testhost'} request.is_secure = Mock(return_value=False) return request