Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 401 and 402] [Versions 401 and 403]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * Helper trait for quiz question unit tests.
  19   *
  20   * This trait helps to execute different tests for quiz, for example if it needs to create a quiz, add question
  21   * to the question, add random quetion to the quiz, do a backup or restore.
  22   *
  23   * @package    mod_quiz
  24   * @category   test
  25   * @copyright  2021 Catalyst IT Australia Pty Ltd
  26   * @author     Safat Shahin <safatshahin@catalyst-au.net>
  27   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  28   */
  29  trait quiz_question_helper_test_trait {
  30  
  31      /** @var \stdClass $course Test course to contain quiz. */
  32      protected $course;
  33  
  34      /** @var \stdClass $quiz A test quiz. */
  35      protected $quiz;
  36  
  37      /** @var \stdClass $user A test logged-in user. */
  38      protected $user;
  39  
  40      /**
  41       * Create a test quiz for the specified course.
  42       *
  43       * @param \stdClass $course
  44       * @return  \stdClass
  45       */
  46      protected function create_test_quiz(\stdClass $course): \stdClass {
  47  
  48          /** @var mod_quiz_generator $quizgenerator */
  49          $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
  50  
  51          return $quizgenerator->create_instance([
  52              'course' => $course->id,
  53              'questionsperpage' => 0,
  54              'grade' => 100.0,
  55              'sumgrades' => 2,
  56          ]);
  57      }
  58  
  59      /**
  60       * Helper method to add regular questions in quiz.
  61       *
  62       * @param component_generator_base $questiongenerator
  63       * @param \stdClass $quiz
  64       * @param array $override
  65       */
  66      protected function add_two_regular_questions($questiongenerator, \stdClass $quiz, $override = null): void {
  67          // Create a couple of questions.
  68          $cat = $questiongenerator->create_question_category($override);
  69  
  70          $saq = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id));
  71          // Create another version.
  72          $questiongenerator->update_question($saq);
  73          quiz_add_quiz_question($saq->id, $quiz);
  74          $numq = $questiongenerator->create_question('numerical', null, array('category' => $cat->id));
  75          // Create two version.
  76          $questiongenerator->update_question($numq);
  77          $questiongenerator->update_question($numq);
  78          quiz_add_quiz_question($numq->id, $quiz);
  79      }
  80  
  81      /**
  82       * Helper method to add random question to quiz.
  83       *
  84       * @param component_generator_base $questiongenerator
  85       * @param \stdClass $quiz
  86       * @param array $override
  87       */
  88      protected function add_one_random_question($questiongenerator, \stdClass $quiz, $override = []): void {
  89          // Create a random question.
  90          $cat = $questiongenerator->create_question_category($override);
  91          $questiongenerator->create_question('truefalse', null, array('category' => $cat->id));
  92          $questiongenerator->create_question('essay', null, array('category' => $cat->id));
  93          quiz_add_random_questions($quiz, 0, $cat->id, 1, false);
  94      }
  95  
  96      /**
  97       * Attempt questions for a quiz and user.
  98       *
  99       * @param \stdClass $quiz Quiz to attempt.
 100       * @param \stdClass $user A user to attempt the quiz.
 101       * @param int $attemptnumber
 102       * @return array
 103       */
 104      protected function attempt_quiz(\stdClass $quiz, \stdClass $user, $attemptnumber = 1): array {
 105          $this->setUser($user);
 106  
 107          $starttime = time();
 108          $quizobj = quiz::create($quiz->id, $user->id);
 109  
 110          $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
 111          $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
 112  
 113          // Start the attempt.
 114          $attempt = quiz_create_attempt($quizobj, $attemptnumber, null, $starttime, false, $user->id);
 115          quiz_start_new_attempt($quizobj, $quba, $attempt, $attemptnumber, $starttime);
 116          quiz_attempt_save_started($quizobj, $quba, $attempt);
 117  
 118          // Finish the attempt.
 119          $attemptobj = quiz_attempt::create($attempt->id);
 120          $attemptobj->process_finish($starttime, false);
 121  
 122          $this->setUser();
 123          return [$quizobj, $quba, $attemptobj];
 124      }
 125  
 126      /**
 127       * A helper method to backup test quiz.
 128       *
 129       * @param \stdClass $quiz Quiz to attempt.
 130       * @param \stdClass $user A user to attempt the quiz.
 131       * @return string A backup ID ready to be restored.
 132       */
 133      protected function backup_quiz(\stdClass $quiz, \stdClass $user): string {
 134          global $CFG;
 135  
 136          // Get the necessary files to perform backup and restore.
 137          require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
 138          require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
 139  
 140          $backupid = 'test-question-backup-restore';
 141  
 142          $bc = new backup_controller(backup::TYPE_1ACTIVITY, $quiz->cmid, backup::FORMAT_MOODLE,
 143              backup::INTERACTIVE_NO, backup::MODE_GENERAL, $user->id);
 144          $bc->execute_plan();
 145  
 146          $results = $bc->get_results();
 147          $file = $results['backup_destination'];
 148          $fp = get_file_packer('application/vnd.moodle.backup');
 149          $filepath = $CFG->dataroot . '/temp/backup/' . $backupid;
 150          $file->extract_to_pathname($fp, $filepath);
 151          $bc->destroy();
 152  
 153          return $backupid;
 154      }
 155  
 156      /**
 157       * A helper method to restore provided backup.
 158       *
 159       * @param string $backupid Backup ID to restore.
 160       * @param stdClass $course
 161       * @param stdClass $user
 162       */
 163      protected function restore_quiz(string $backupid, stdClass $course, stdClass $user): void {
 164          $rc = new restore_controller($backupid, $course->id,
 165              backup::INTERACTIVE_NO, backup::MODE_GENERAL, $user->id, backup::TARGET_CURRENT_ADDING);
 166          $this->assertTrue($rc->execute_precheck());
 167          $rc->execute_plan();
 168          $rc->destroy();
 169      }
 170  
 171      /**
 172       * A helper method to emulate duplication of the quiz.
 173       *
 174       * @param stdClass $course
 175       * @param stdClass $quiz
 176       * @return \cm_info|null
 177       */
 178      protected function duplicate_quiz($course, $quiz): ?\cm_info {
 179          return duplicate_module($course, get_fast_modinfo($course)->get_cm($quiz->cmid));
 180      }
 181  }