MDL-27570 quiz timing: add unit test and simplify top of process_attempt
This commit is contained in:
+18
-17
@@ -2386,28 +2386,32 @@ class quiz_attempt {
|
||||
|
||||
$transaction = $DB->start_delegated_transaction();
|
||||
|
||||
// If there is only a very small amount of time left, there is no point trying
|
||||
// to show the student another page of the quiz. Just finish now.
|
||||
$graceperiodmin = null;
|
||||
// Get key times.
|
||||
$accessmanager = $this->get_access_manager($timenow);
|
||||
$timeclose = $accessmanager->get_end_time($this->get_attempt());
|
||||
$graceperiodmin = get_config('quiz', 'graceperiodmin');
|
||||
|
||||
// Don't enforce timeclose for previews.
|
||||
if ($this->is_preview()) {
|
||||
$timeclose = false;
|
||||
}
|
||||
$toolate = false;
|
||||
if ($timeclose !== false && $timenow > $timeclose - QUIZ_MIN_TIME_TO_CONTINUE) {
|
||||
$timeup = true;
|
||||
$graceperiodmin = get_config('quiz', 'graceperiodmin');
|
||||
if ($timenow > $timeclose + $graceperiodmin) {
|
||||
$toolate = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify if time is really up; time limit could have been changed.
|
||||
if ($timeup && $timenow < $timeclose - QUIZ_MIN_TIME_TO_CONTINUE) {
|
||||
$timeup = false;
|
||||
// Check where we are in relation to the end time, if there is one.
|
||||
$toolate = false;
|
||||
if ($timeclose !== false) {
|
||||
if ($timenow > $timeclose - QUIZ_MIN_TIME_TO_CONTINUE) {
|
||||
// If there is only a very small amount of time left, there is no point trying
|
||||
// to show the student another page of the quiz. Just finish now.
|
||||
$timeup = true;
|
||||
if ($timenow > $timeclose + $graceperiodmin) {
|
||||
$toolate = true;
|
||||
}
|
||||
} else {
|
||||
// If time is not close to expiring, then ignore the client-side timer's opinion
|
||||
// about whether time has expired. This can happen if the time limit has changed
|
||||
// since the student's previous interaction.
|
||||
$timeup = false;
|
||||
}
|
||||
}
|
||||
|
||||
// If time is running out, trigger the appropriate action.
|
||||
@@ -2415,9 +2419,6 @@ class quiz_attempt {
|
||||
$becomingabandoned = false;
|
||||
if ($timeup) {
|
||||
if ($this->get_quiz()->overduehandling === 'graceperiod') {
|
||||
if (is_null($graceperiodmin)) {
|
||||
$graceperiodmin = get_config('quiz', 'graceperiodmin');
|
||||
}
|
||||
if ($timenow > $timeclose + $this->get_quiz()->graceperiod + $graceperiodmin) {
|
||||
// Grace period has run out.
|
||||
$finishattempt = true;
|
||||
|
||||
@@ -34,6 +34,7 @@ require_once($CFG->dirroot . '/mod/quiz/locallib.php');
|
||||
* @copyright 2013 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @covers \quiz_attempt
|
||||
*/
|
||||
class attempt_walkthrough_test extends \advanced_testcase {
|
||||
|
||||
@@ -116,9 +117,17 @@ class attempt_walkthrough_test extends \advanced_testcase {
|
||||
$this->assertEquals(100, $gradebookgrade->grade);
|
||||
}
|
||||
|
||||
public function test_quiz_attempt_walkthrough_submit_time_recorded_correctly_when_overdue() {
|
||||
/**
|
||||
* Create a quiz containing one question and a close time.
|
||||
*
|
||||
* The question is the standard shortanswer test question.
|
||||
* The quiz is set to close 1 hour from now.
|
||||
* The quiz is set to use a grade period of 1 hour once time expires.
|
||||
*
|
||||
* @return \stdClass the quiz that was created.
|
||||
*/
|
||||
protected function create_quiz_with_one_question(): \stdClass {
|
||||
global $SITE;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Make a quiz.
|
||||
@@ -130,6 +139,7 @@ class attempt_walkthrough_test extends \advanced_testcase {
|
||||
'overduehandling' => 'graceperiod', 'graceperiod' => HOURSECS]);
|
||||
|
||||
// Create a question.
|
||||
/** @var \core_question_generator $questiongenerator */
|
||||
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
|
||||
$cat = $questiongenerator->create_question_category();
|
||||
$saq = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id));
|
||||
@@ -138,6 +148,13 @@ class attempt_walkthrough_test extends \advanced_testcase {
|
||||
quiz_add_quiz_question($saq->id, $quiz, 0, 1);
|
||||
quiz_update_sumgrades($quiz);
|
||||
|
||||
return $quiz;
|
||||
}
|
||||
|
||||
public function test_quiz_attempt_walkthrough_submit_time_recorded_correctly_when_overdue() {
|
||||
|
||||
$quiz = $this->create_quiz_with_one_question();
|
||||
|
||||
// Make a user to do the quiz.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
@@ -148,11 +165,11 @@ class attempt_walkthrough_test extends \advanced_testcase {
|
||||
|
||||
// Process some responses from the student.
|
||||
$attemptobj = quiz_attempt::create($attempt->id);
|
||||
$attemptobj->process_submitted_actions($timeclose - 30 * MINSECS, false, [1 => ['answer' => 'frog']]);
|
||||
$attemptobj->process_submitted_actions($quiz->timeclose - 30 * MINSECS, false, [1 => ['answer' => 'frog']]);
|
||||
|
||||
// Attempt goes overdue (e.g. if cron ran).
|
||||
$attemptobj = quiz_attempt::create($attempt->id);
|
||||
$attemptobj->process_going_overdue($timeclose + 2 * get_config('quiz', 'graceperiodmin'), false);
|
||||
$attemptobj->process_going_overdue($quiz->timeclose + 2 * get_config('quiz', 'graceperiodmin'), false);
|
||||
|
||||
// Verify the attempt state.
|
||||
$attemptobj = quiz_attempt::create($attempt->id);
|
||||
@@ -164,17 +181,53 @@ class attempt_walkthrough_test extends \advanced_testcase {
|
||||
|
||||
// Student submits the attempt during the grace period.
|
||||
$attemptobj = quiz_attempt::create($attempt->id);
|
||||
$attemptobj->process_attempt($timeclose + 30 * MINSECS, true, false, 1);
|
||||
$attemptobj->process_attempt($quiz->timeclose + 30 * MINSECS, true, false, 1);
|
||||
|
||||
// Verify the attempt state.
|
||||
$attemptobj = quiz_attempt::create($attempt->id);
|
||||
$this->assertEquals(1, $attemptobj->get_attempt_number());
|
||||
$this->assertEquals(true, $attemptobj->is_finished());
|
||||
$this->assertEquals($timeclose + 30 * MINSECS, $attemptobj->get_submitted_date());
|
||||
$this->assertEquals($quiz->timeclose + 30 * MINSECS, $attemptobj->get_submitted_date());
|
||||
$this->assertEquals($user->id, $attemptobj->get_userid());
|
||||
$this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question());
|
||||
}
|
||||
|
||||
public function test_quiz_attempt_walkthrough_close_time_extended_at_last_minute() {
|
||||
global $DB;
|
||||
|
||||
$quiz = $this->create_quiz_with_one_question();
|
||||
$originaltimeclose = $quiz->timeclose;
|
||||
|
||||
// Make a user to do the quiz.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
$quizobj = quiz::create($quiz->id, $user->id);
|
||||
|
||||
// Start the attempt.
|
||||
$attempt = quiz_prepare_and_start_new_attempt($quizobj, 1, null);
|
||||
|
||||
// Process some responses from the student during the attempt.
|
||||
$attemptobj = quiz_attempt::create($attempt->id);
|
||||
$attemptobj->process_submitted_actions($originaltimeclose - 30 * MINSECS, false, [1 => ['answer' => 'frog']]);
|
||||
|
||||
// Teacher edits the quiz to extend the time-limit by one minute.
|
||||
$DB->set_field('quiz', 'timeclose', $originaltimeclose + MINSECS, ['id' => $quiz->id]);
|
||||
\course_modinfo::clear_instance_cache($quiz->course);
|
||||
|
||||
// Timer expires in the student browser and thinks it is time to submit the quiz.
|
||||
// This sets $finishattempt to false - since the student did not click the button, and $timeup to true.
|
||||
$attemptobj = quiz_attempt::create($attempt->id);
|
||||
$attemptobj->process_attempt($originaltimeclose, false, true, 1);
|
||||
|
||||
// Verify the attempt state - the $timeup was ignored becuase things have changed server-side.
|
||||
$attemptobj = quiz_attempt::create($attempt->id);
|
||||
$this->assertEquals(1, $attemptobj->get_attempt_number());
|
||||
$this->assertFalse($attemptobj->is_finished());
|
||||
$this->assertEquals(quiz_attempt::IN_PROGRESS, $attemptobj->get_state());
|
||||
$this->assertEquals(0, $attemptobj->get_submitted_date());
|
||||
$this->assertEquals($user->id, $attemptobj->get_userid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a quiz with a random as well as other questions and walk through quiz attempts.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user