MDL-63185 mod_quiz: add custom behat step to create user attempts
authorSimey Lameze <simey@moodle.com>
Thu, 27 Sep 2018 02:13:47 +0000 (10:13 +0800)
committerSimey Lameze <simey@moodle.com>
Fri, 28 Sep 2018 03:07:21 +0000 (11:07 +0800)
Thanks to Tim Hunt for all the help.

Part of MDL-62610

mod/quiz/tests/behat/behat_mod_quiz.php

index 0450293..ee8dc58 100644 (file)
@@ -561,4 +561,80 @@ class behat_mod_quiz extends behat_question_base {
                 "contains(., {$questionnumberliteral}) and contains(preceding-sibling::h3[1], {$headingliteral})]";
         $this->find('xpath', $xpath);
     }
                 "contains(., {$questionnumberliteral}) and contains(preceding-sibling::h3[1], {$headingliteral})]";
         $this->find('xpath', $xpath);
     }
+
+    /**
+     * Attempt a quiz.
+     *
+     * The first row should be column names:
+     * | slot | actualquestion | variant | response |
+     * The first two of those are required. The others are optional.
+     *
+     * slot           The slot
+     * actualquestion This column is optional, and is only needed if the quiz contains
+     *                random questions. If so, this will let you control which acutal
+     *                question gets picked when this slot is 'randomised' at the
+     *                start of the attempt. If you don't specify, then one will be picked
+     *                at random (which might make the reponse meaningless).
+     * variant        This column is similar, and also options. It is only needed if
+     *                the question that ends up in this slot returns something greater
+     *                than 1 for $question->get_num_variants(). Like with actualquestion,
+     *                if you specify a value here it is used the fix the 'random' choice
+     *                made when the quiz is started.
+     * response       The response that was submitted. How this is interpreted depends on
+     *                the question type. It gets passed to
+     *                {@link core_question_generator::get_simulated_post_data_for_question_attempt()
+     *                and therefore to the un_summarise_response method of the question to decode.
+     *
+     * Then there should be a number of rows of data, one for each question you want to add.
+     * There is no need to supply answers to all questions. If so, other qusetions will be
+     * left unanswered.
+     *
+     * @param string $quizname the name of the quiz the user will attempt.
+     * @param string $username the username of the user that will attempt.
+     * @param TableNode $attemptinfo information about the questions to add, as above.
+     * @Given /^I attempt quiz "([^"]*)" as "([^"]*)" with the following responses:$/
+     */
+    public function i_attempt_quiz_as_user_setting_the_following_responses($quizname, $username, TableNode $attemptinfo) {
+        global $DB, $USER;
+
+        /** @var mod_quiz_generator $quizgenerator */
+        $quizgenerator = behat_util::get_data_generator()->get_plugin_generator('mod_quiz');
+
+        $quizid = $DB->get_field('quiz', 'id', ['name' => $quizname], MUST_EXIST);
+        $user = $DB->get_record('user', ['username' => $username], '*', MUST_EXIST);
+
+        $forcedrandomquestions = [];
+        $forcedvariants = [];
+        $responses = [];
+        foreach ($attemptinfo->getHash() as $slotinfo) {
+            if (empty($slotinfo['slot'])) {
+                throw new ExpectationException('When simulating a quiz attempt, ' .
+                        'the slot column is required.', $this->getSession());
+            }
+            if (!array_key_exists('response', $slotinfo)) {
+                throw new ExpectationException('When simulating a quiz attempt, ' .
+                        'the response column is required.', $this->getSession());
+            }
+            $responses[$slotinfo['slot']] = $slotinfo['response'];
+
+            if (!empty($slotinfo['actualquestion'])) {
+                $forcedrandomquestions[$slotinfo['slot']] = $DB->get_field('question', 'id',
+                        ['name' => $slotinfo['actualquestion']], MUST_EXIST);
+            }
+
+            if (!empty($slotinfo['variant'])) {
+                $forcedvariants[$slotinfo['slot']] = (int) $slotinfo['variant'];
+            }
+        }
+
+        $saveduser = $USER; // TODO there is probably a better way to do this. If not, there should be.
+        $USER = $user;
+
+        $attempt = $quizgenerator->create_attempt($quizid, $user->id,
+                $forcedrandomquestions, $forcedvariants);
+
+        $quizgenerator->submit_responses($attempt->id, $responses, true);
+
+        $USER = $saveduser;
+    }
 }
 }