MDL-87340 mod_quiz: make test_question_shuffle more robust

This commit improves test_question_shuffle by retrying if questions
remains in the same order after shuffling.
This commit is contained in:
Simey Lameze
2025-12-09 07:34:19 +08:00
parent 48c9857449
commit a45cfb7c7b
+34 -13
View File
@@ -584,7 +584,7 @@ final class attempt_test extends \advanced_testcase {
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
// Create quiz with two sections using create_test_quiz.
// Create quiz with two sections (shuffled, non-shuffled) using create_test_quiz.
$quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
$quizobj = $quizgenerator->create_test_quiz([
'Shuffled section*',
@@ -601,26 +601,47 @@ final class attempt_test extends \advanced_testcase {
['Q10', 2, 'shortanswer'],
]);
// Start two attempts.
// Start the reference attempt (Attempt 1).
$attempt1 = quiz_prepare_and_start_new_attempt($quizobj, 1, null, false, [], [], $user->id);
$attempt2 = quiz_prepare_and_start_new_attempt($quizobj, 2, null, false, [], [], $user->id);
$attemptobj1 = quiz_attempt::create($attempt1->id);
$attemptobj2 = quiz_attempt::create($attempt2->id);
// Get slot numbers for each section in both attempts.
// Shuffled section
$slots1a = $attemptobj1->get_slots(0);
$slots1b = $attemptobj2->get_slots(0);
// Non-shuffled section
$slots2a = $attemptobj1->get_slots(1);
$slots2b = $attemptobj2->get_slots(1);
// Get question order for each section in both attempts.
// Get reference orders.
$order1a = array_map(fn($slot) => $attemptobj1->get_question_attempt($slot)->get_question()->id, $slots1a);
$order1b = array_map(fn($slot) => $attemptobj2->get_question_attempt($slot)->get_question()->id, $slots1b);
$order2a = array_map(fn($slot) => $attemptobj1->get_question_attempt($slot)->get_question()->id, $slots2a);
$order2b = array_map(fn($slot) => $attemptobj2->get_question_attempt($slot)->get_question()->id, $slots2b);
// Assert shuffled section is different, non-shuffled is the same.
$this->assertNotEquals($order1a, $order1b, 'Shuffled section should have different order between attempts.');
// Start comparison attempt (Attempt 2) with a retry mechanism.
// We try up to 5 times to get a different shuffle.
// If it matches 5 times in a row, the shuffle feature is likely broken.
$maxretries = 5;
$isshuffled = false;
for ($i = 0; $i < $maxretries; $i++) {
$attempt2 = quiz_prepare_and_start_new_attempt($quizobj, 2 + $i, null, false, [], [], $user->id);
$attemptobj2 = quiz_attempt::create($attempt2->id);
$slots1b = $attemptobj2->get_slots(0);
$order1b = array_map(fn($slot) => $attemptobj2->get_question_attempt($slot)->get_question()->id, $slots1b);
// If the orders are different, the shuffle is working.
if ($order1a !== $order1b) {
$isshuffled = true;
break;
}
// Otherwise try again.
}
// Assert that we eventually found a different order.
$message = "Shuffled section should have different order between attempts after $maxretries tries.";
$this->assertTrue($isshuffled, $message);
// Verify the non-shuffled section on the final attempt used.
// We only need to check this on the last attempt generated, as it should never change.
$slots2b = $attemptobj2->get_slots(1);
$order2b = array_map(fn($slot) => $attemptobj2->get_question_attempt($slot)->get_question()->id, $slots2b);
$this->assertEquals($order2a, $order2b, 'Non-shuffled section should have same order between attempts.');
}
}