-
Notifications
You must be signed in to change notification settings - Fork 85
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #978 from edx/alangsto/allow_practice_exams_to_tri…
…gger_grades fix: practice exam updates should trigger grade and credit updates
- Loading branch information
Showing
7 changed files
with
223 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
edx_proctoring/management/commands/tests/test_update_attempts_for_exam.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
""" | ||
Tests for the update_attempts_for_exam management command | ||
""" | ||
|
||
from mock import patch | ||
|
||
from django.contrib.auth import get_user_model | ||
from django.core.management import call_command | ||
|
||
from edx_proctoring.api import create_exam, create_exam_attempt, update_attempt_status | ||
from edx_proctoring.models import ProctoredExamStudentAttempt | ||
from edx_proctoring.runtime import set_runtime_service | ||
from edx_proctoring.statuses import ProctoredExamStudentAttemptStatus | ||
from edx_proctoring.tests.test_services import MockCertificateService, MockCreditService, MockGradesService | ||
from edx_proctoring.tests.utils import LoggedInTestCase | ||
|
||
User = get_user_model() | ||
|
||
|
||
class TestUpdateAttemptsForExam(LoggedInTestCase): | ||
""" | ||
Coverage of the update_attempts_for_exam.py file | ||
""" | ||
|
||
def setUp(self): | ||
""" | ||
Build up test data | ||
""" | ||
super().setUp() | ||
set_runtime_service('credit', MockCreditService()) | ||
set_runtime_service('grades', MockGradesService()) | ||
set_runtime_service('certificates', MockCertificateService()) | ||
|
||
def test_run_command(self): | ||
""" | ||
Run the management command | ||
""" | ||
exam_id = create_exam( | ||
course_id='foo', | ||
content_id='bar', | ||
exam_name='Test Exam 1', | ||
time_limit_mins=90 | ||
) | ||
|
||
# create three users and three exam attempts | ||
for i in range(3): | ||
other_user = User.objects.create(username='otheruser'+str(i), password='test') | ||
attempt_id = create_exam_attempt(exam_id, other_user.id, taking_as_proctored=True) | ||
update_attempt_status(attempt_id, ProctoredExamStudentAttemptStatus.verified) | ||
|
||
with patch.object(MockCreditService, 'set_credit_requirement_status') as mock_credit: | ||
call_command( | ||
'update_attempts_for_exam', | ||
batch_size=2, | ||
sleep_time=0, | ||
exam_id=exam_id | ||
) | ||
mock_credit.assert_called() | ||
|
||
# make sure status stays the same | ||
attempts = ProctoredExamStudentAttempt.objects.filter(status=ProctoredExamStudentAttemptStatus.verified) | ||
self.assertEqual(len(attempts), 3) |
78 changes: 78 additions & 0 deletions
78
edx_proctoring/management/commands/update_attempts_for_exam.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
""" | ||
Django management command to re-trigger the status update of a ProctoredExamStudentAttempt | ||
for a specific proctored exam. | ||
""" | ||
|
||
import logging | ||
import time | ||
|
||
from django.core.management.base import BaseCommand | ||
|
||
from edx_proctoring.api import update_attempt_status | ||
from edx_proctoring.models import ProctoredExamStudentAttempt | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
class Command(BaseCommand): | ||
""" | ||
Django Management command to update is_attempt_active field on review models | ||
""" | ||
|
||
def add_arguments(self, parser): | ||
parser.add_argument( | ||
'--batch_size', | ||
action='store', | ||
dest='batch_size', | ||
type=int, | ||
default=300, | ||
help='Maximum number of attempts to process. ' | ||
'This helps avoid overloading the database while updating large amount of data.' | ||
) | ||
parser.add_argument( | ||
'--sleep_time', | ||
action='store', | ||
dest='sleep_time', | ||
type=int, | ||
default=10, | ||
help='Sleep time in seconds between update of batches' | ||
) | ||
|
||
parser.add_argument( | ||
'--exam_id', | ||
action='store', | ||
dest='exam_id', | ||
type=int, | ||
help='Exam ID to process attempts for.' | ||
) | ||
|
||
def handle(self, *args, **options): | ||
""" | ||
Management command entry point, simply call into the signal firing | ||
""" | ||
|
||
batch_size = options['batch_size'] | ||
sleep_time = options['sleep_time'] | ||
exam_id = options['exam_id'] | ||
|
||
# get all attempts for specific exam id | ||
exam_attempts = ProctoredExamStudentAttempt.objects.filter(proctored_exam_id=exam_id) | ||
|
||
attempt_count = 0 | ||
|
||
# for each of those attempts, get id and status | ||
for attempt in exam_attempts: | ||
current_status = attempt.status | ||
current_id = attempt.id | ||
|
||
log.info( | ||
'Triggering attempt status update for attempt_id=%(attempt_id)s with status=%(status)s', | ||
{'attempt_id': current_id, 'status': current_status} | ||
) | ||
# need to use update_attempt_status because this function will trigger grade + credit updates | ||
update_attempt_status(current_id, current_status) | ||
attempt_count += 1 | ||
|
||
if attempt_count == batch_size: | ||
attempt_count = 0 | ||
time.sleep(sleep_time) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters