From 92caa214efb672583613f29f782c041eedf9a9a8 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 27 Feb 2015 14:40:44 +0000 Subject: [PATCH 1/3] MDL-49335 Behat: new question selector So you can say things like And I click on "True" "radio" in the "First question" "question" --- lib/behat/classes/behat_selectors.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/behat/classes/behat_selectors.php b/lib/behat/classes/behat_selectors.php index 74de1714714..5fd807e9351 100644 --- a/lib/behat/classes/behat_selectors.php +++ b/lib/behat/classes/behat_selectors.php @@ -45,6 +45,7 @@ class behat_selectors { 'dialogue' => 'dialogue', 'fieldset' => 'fieldset', 'list_item' => 'list_item', + 'question' => 'question', 'region' => 'region', 'section' => 'section', 'table' => 'table', @@ -71,6 +72,7 @@ class behat_selectors { 'list_item' => 'list_item', 'optgroup' => 'optgroup', 'option' => 'option', + 'question' => 'question', 'radio' => 'radio', 'region' => 'region', 'section' => 'section', @@ -113,6 +115,10 @@ XPATH XPATH , 'list_item' => << << << Date: Fri, 27 Feb 2015 14:44:03 +0000 Subject: [PATCH 2/3] MDL-49335 quiz behat: improved step for adding questions to a quiz Explicit headings make the script more readable, and pave the way for new options that are due to be added. --- mod/quiz/tests/behat/behat_mod_quiz.php | 87 +++++++++++++++++++------ 1 file changed, 67 insertions(+), 20 deletions(-) diff --git a/mod/quiz/tests/behat/behat_mod_quiz.php b/mod/quiz/tests/behat/behat_mod_quiz.php index 6e4fabad543..1e073e2c845 100644 --- a/mod/quiz/tests/behat/behat_mod_quiz.php +++ b/mod/quiz/tests/behat/behat_mod_quiz.php @@ -43,9 +43,20 @@ class behat_mod_quiz extends behat_question_base { /** * Put the specified questions on the specified pages of a given quiz. * - * Give the question name in the first column, and that page number in the - * second column. You may optionally give the desired maximum mark for each - * question in a third column. + * The first row should be column names: + * | question | page | maxmark | + * The first two of those are required. The others are optional. + * + * question needs to uniquely match a question name. + * page is a page number. Must start at 1, and on each following + * row should be the same as the previous, or one more. + * maxmark What the question is marked out of. Defaults to question.defaultmark. + * + * Then there should be a number of rows of data, one for each question you want to add. + * + * For backwards-compatibility reasons, specifying the column names is optional + * (but strongly encouraged). If not specified, the columns are asseumed to be + * | question | page | maxmark |. * * @param string $quizname the name of the quiz to add questions to. * @param TableNode $data information about the questions to add. @@ -57,34 +68,70 @@ class behat_mod_quiz extends behat_question_base { $quiz = $DB->get_record('quiz', array('name' => $quizname), '*', MUST_EXIST); - // The action depends on the field type. - foreach ($data->getRows() as $questiondata) { - if (count($questiondata) < 2 || count($questiondata) > 3) { + // Deal with backwards-compatibility, optional first row. + $firstrow = $data->getRow(0); + if (!in_array('question', $firstrow) && !in_array('page', $firstrow)) { + if (count($firstrow) == 2) { + $headings = array('question', 'page'); + } else if (count($firstrow) == 3) { + $headings = array('question', 'page', 'maxmark'); + } else { throw new ExpectationException('When adding questions to a quiz, you should give 2 or three 3 things: ' . - ' the question name, the page number, and optionally a the maxiumum mark. ' . - count($questiondata) . ' values passed.', $this->getSession()); + ' the question name, the page number, and optionally the maxiumum mark. ' . + count($firstrow) . ' values passed.', $this->getSession()); + } + $rows = $data->getRows(); + array_unshift($rows, $headings); + $data->setRows($rows); + } + + // Add the questions. + $lastpage = 0; + foreach ($data->getHash() as $questiondata) { + if (!array_key_exists('question', $questiondata)) { + throw new ExpectationException('When adding questions to a quiz, ' . + 'the question name column is required.', $this->getSession()); + } + if (!array_key_exists('page', $questiondata)) { + throw new ExpectationException('When adding questions to a quiz, ' . + 'the page number column is required.', $this->getSession()); } - list($questionname, $rawpage) = $questiondata; - if (!isset($questiondata[2]) || $questiondata[2] === '') { + // Question id. + $questionid = $DB->get_field('question', 'id', + array('name' => $questiondata['question']), MUST_EXIST); + + // Page number. + $page = clean_param($questiondata['page'], PARAM_INT); + if ($page <= 0 || (string) $page !== $questiondata['page']) { + throw new ExpectationException('The page number for question "' . + $questiondata['question'] . '" must be a positive integer.', + $this->getSession()); + } + if ($page < $lastpage || $page > $lastpage + 1) { + throw new ExpectationException('When adding questions to a quiz, ' . + 'the page number for each question must either be the same, ' . + 'or one more, then the page number for the previous question.', + $this->getSession()); + } + $lastpage = $page; + + // Max mark. + if (!array_key_exists('maxmark', $questiondata) || $questiondata['maxmark'] === '') { $maxmark = null; } else { - $maxmark = clean_param($questiondata[2], PARAM_FLOAT); - if (!is_numeric($questiondata[2]) || $maxmark < 0) { - throw new ExpectationException('When adding questions to a quiz, the max mark must be a positive number.', + $maxmark = clean_param($questiondata['maxmark'], PARAM_FLOAT); + if (!is_numeric($questiondata['maxmark']) || $maxmark < 0) { + throw new ExpectationException('The max mark for question "' . + $questiondata['question'] . '" must be a positive number.', $this->getSession()); } } - $page = clean_param($rawpage, PARAM_INT); - if ($page <= 0 || (string) $page !== $rawpage) { - throw new ExpectationException('When adding questions to a quiz, the page number must be a positive integer.', - $this->getSession()); - } - - $questionid = $DB->get_field('question', 'id', array('name' => $questionname), MUST_EXIST); + // Add the question. quiz_add_quiz_question($questionid, $quiz, $page, $maxmark); } + quiz_update_sumgrades($quiz); } From 867b0430b0e3f793d5a55802ae18cca05763cf7d Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 27 Feb 2015 14:45:17 +0000 Subject: [PATCH 3/3] MDL-49335 quiz behat: new test of attempting a quiz This separates out attempting the quiz into a separate .feature, away from the monolithic add_quiz.feature. At some point we should clean that up, but for now I am just adding this. Really, the main reason for this test is to verify the two Behat enhancememnts I just did. --- mod/quiz/tests/behat/attempt.feature | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 mod/quiz/tests/behat/attempt.feature diff --git a/mod/quiz/tests/behat/attempt.feature b/mod/quiz/tests/behat/attempt.feature new file mode 100644 index 00000000000..77627c45827 --- /dev/null +++ b/mod/quiz/tests/behat/attempt.feature @@ -0,0 +1,43 @@ +@mod @mod_quiz +Feature: Attemp a quiz where some questions require that the previous question has been answered. + As a student + In order to demonstrate what I know + I need to be able to attempt quizzes + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | + | student | Student | One | student@moodle.com | + And the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + And the following "course enrolments" exist: + | user | course | role | + | student | C1 | student | + And the following "question categories" exist: + | contextlevel | reference | name | + | Course | C1 | Test questions | + And the following "questions" exist: + | questioncategory | qtype | name | questiontext | + | Test questions | truefalse | TF1 | First question | + | Test questions | truefalse | TF2 | Second question | + And the following "activities" exist: + | activity | name | intro | course | idnumber | + | quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 | + And quiz "Quiz 1" contains the following questions: + | question | page | maxmark | + | TF1 | 1 | | + | TF2 | 1 | 3.0 | + + @javascript + Scenario: A student can attempt a quiz + When I log in as "student" + And I follow "Course 1" + And I follow "Quiz 1" + And I press "Attempt quiz now" + And I click on "True" "radio" in the "First question" "question" + And I click on "False" "radio" in the "Second question" "question" + And I press "Next" + And I press "Submit all and finish" + And I click on "Submit all and finish" "button" in the "Confirmation" "dialogue" + Then I should see "25.00 out of 100.00"