137 lines
4.2 KiB
Python
137 lines
4.2 KiB
Python
"""
|
|
Tests for the LTI outcome service handlers, both in outcomes.py and in tasks.py
|
|
"""
|
|
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import ddt
|
|
from django.test import TestCase
|
|
from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator
|
|
|
|
import lms.djangoapps.lti_provider.tasks as tasks
|
|
from common.djangoapps.student.tests.factories import UserFactory
|
|
from lms.djangoapps.lti_provider.models import GradedAssignment, LtiConsumer, OutcomeService
|
|
|
|
|
|
class BaseOutcomeTest(TestCase):
|
|
"""
|
|
Super type for tests of both the leaf and composite outcome celery tasks.
|
|
"""
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.course_key = CourseLocator(
|
|
org='some_org',
|
|
course='some_course',
|
|
run='some_run'
|
|
)
|
|
self.usage_key = BlockUsageLocator(
|
|
course_key=self.course_key,
|
|
block_type='problem',
|
|
block_id='block_id'
|
|
)
|
|
self.user = UserFactory.create()
|
|
self.consumer = LtiConsumer(
|
|
consumer_name='Lti Consumer Name',
|
|
consumer_key='consumer_key',
|
|
consumer_secret='consumer_secret',
|
|
instance_guid='tool_instance_guid'
|
|
)
|
|
self.consumer.save()
|
|
outcome = OutcomeService(
|
|
lis_outcome_service_url='http://example.com/service_url',
|
|
lti_consumer=self.consumer
|
|
)
|
|
outcome.save()
|
|
self.assignment = GradedAssignment(
|
|
user=self.user,
|
|
course_key=self.course_key,
|
|
usage_key=self.usage_key,
|
|
outcome_service=outcome,
|
|
lis_result_sourcedid='sourcedid',
|
|
version_number=1,
|
|
)
|
|
self.assignment.save()
|
|
|
|
self.send_score_update_mock = self.setup_patch(
|
|
'lms.djangoapps.lti_provider.outcomes.send_score_update', None
|
|
)
|
|
|
|
def setup_patch(self, function_name, return_value):
|
|
"""
|
|
Patch a method with a given return value, and return the mock
|
|
"""
|
|
mock = MagicMock(return_value=return_value)
|
|
new_patch = patch(function_name, new=mock)
|
|
new_patch.start()
|
|
self.addCleanup(new_patch.stop)
|
|
return mock
|
|
|
|
|
|
@ddt.ddt
|
|
class SendLeafOutcomeTest(BaseOutcomeTest):
|
|
"""
|
|
Tests for the send_leaf_outcome method in tasks.py
|
|
"""
|
|
|
|
@ddt.data(
|
|
(2.0, 2.0, 1.0),
|
|
(2.0, 0.0, 0.0),
|
|
(1, 2, 0.5),
|
|
)
|
|
@ddt.unpack
|
|
def test_outcome_with_score(self, earned, possible, expected):
|
|
tasks.send_leaf_outcome(
|
|
self.assignment.id,
|
|
earned,
|
|
possible
|
|
)
|
|
self.send_score_update_mock.assert_called_once_with(self.assignment, expected)
|
|
|
|
|
|
@ddt.ddt
|
|
class SendCompositeOutcomeTest(BaseOutcomeTest):
|
|
"""
|
|
Tests for the send_composite_outcome method in tasks.py
|
|
"""
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.descriptor = MagicMock()
|
|
self.descriptor.location = BlockUsageLocator(
|
|
course_key=self.course_key,
|
|
block_type='problem',
|
|
block_id='problem',
|
|
)
|
|
self.course_grade = MagicMock()
|
|
self.course_grade_mock = self.setup_patch(
|
|
'lms.djangoapps.lti_provider.tasks.CourseGradeFactory.read', self.course_grade
|
|
)
|
|
self.module_store = MagicMock()
|
|
self.module_store.get_item = MagicMock(return_value=self.descriptor)
|
|
self.check_result_mock = self.setup_patch(
|
|
'lms.djangoapps.lti_provider.tasks.modulestore',
|
|
self.module_store
|
|
)
|
|
|
|
@ddt.data(
|
|
(2.0, 2.0, 1.0),
|
|
(2.0, 0.0, 0.0),
|
|
(1, 2, 0.5),
|
|
)
|
|
@ddt.unpack
|
|
def test_outcome_with_score_score(self, earned, possible, expected):
|
|
self.course_grade.score_for_module = MagicMock(return_value=(earned, possible))
|
|
tasks.send_composite_outcome(
|
|
self.user.id, str(self.course_key), self.assignment.id, 1
|
|
)
|
|
self.send_score_update_mock.assert_called_once_with(self.assignment, expected)
|
|
|
|
def test_outcome_with_outdated_version(self):
|
|
self.assignment.version_number = 2
|
|
self.assignment.save()
|
|
tasks.send_composite_outcome(
|
|
self.user.id, str(self.course_key), self.assignment.id, 1
|
|
)
|
|
assert self.course_grade_mock.call_count == 0
|