See Release Notes
Long Term Support Release
<?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Unit tests for the Moodle XML format. * * @package qformat_xml * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */> namespace qformat_xml; > defined('MOODLE_INTERNAL') || die(); > use qformat_xml; > use qtype_numerical_answer; global $CFG; > use question_answer; require_once($CFG->libdir . '/questionlib.php'); > use question_bank; require_once($CFG->dirroot . '/question/format/xml/format.php'); > use question_check_specified_fields_expectation; require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); > use question_hint; > use question_hint_with_parts;</** * Unit tests for the matching question definition class. *> * @package qformat_xml* @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */< class qformat_xml_test extends question_testcase {> class xmlformat_test extends \question_testcase {public function assert_same_xml($expectedxml, $xml) { $this->assertEquals(str_replace("\r\n", "\n", $expectedxml), str_replace("\r\n", "\n", $xml)); } public function make_test_question() { global $USER;< $q = new stdClass();> $q = new \stdClass();$q->id = 0; $q->contextid = 0; $q->idnumber = null; $q->category = 0; $q->parent = 0; $q->questiontextformat = FORMAT_HTML; $q->generalfeedbackformat = FORMAT_HTML; $q->defaultmark = 1; $q->penalty = 0.3333333; $q->length = 1; $q->stamp = make_unique_id_code();< $q->version = make_unique_id_code(); < $q->hidden = 0;> $q->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$q->timecreated = time(); $q->timemodified = time(); $q->createdby = $USER->id; $q->modifiedby = $USER->id; return $q; } /** * The data the XML import format sends to save_question is not exactly * the same as the data returned from the editing form, so this method * makes necessary changes to the return value of< * test_question_maker::get_question_form_data so that the tests can work.> * \test_question_maker::get_question_form_data so that the tests can work.* @param object $expectedq as returned by get_question_form_data. * @return object one more likely to match the return value of import_...(). */ public function remove_irrelevant_form_data_fields($expectedq) { return $this->itemid_to_files($expectedq); } /** * Becuase XML import uses a files array instead of an itemid integer to * handle saving files with a question, we need to covert the output of< * test_question_maker::get_question_form_data to match. This method recursively> * \test_question_maker::get_question_form_data to match. This method recursively* replaces all array elements with key itemid with an array entry with * key files and value an empty array. * * @param mixed $var any data structure. * @return mixed an equivalent structure with the relacements made. */ protected function itemid_to_files($var) { if (is_object($var)) {< $newvar = new stdClass();> $newvar = new \stdClass();foreach (get_object_vars($var) as $field => $value) { $newvar->$field = $this->itemid_to_files($value); } } else if (is_array($var)) { $newvar = array(); foreach ($var as $index => $value) { if ($index === 'itemid') { $newvar['files'] = array(); } else { $newvar[$index] = $this->itemid_to_files($value); } } } else { $newvar = $var; } return $newvar; } public function test_xml_escape_simple_input_not_escaped() { $exporter = new qformat_xml(); $string = 'Nothing funny here. Even if we go to a café or to 日本.'; $this->assertEquals($string, $exporter->xml_escape($string)); } public function test_xml_escape_html_wrapped_in_cdata() { $exporter = new qformat_xml(); $string = '<p>Nothing <b>funny<b> here. Even if we go to a café or to 日本.</p>'; $this->assertEquals('<![CDATA[' . $string . ']]>', $exporter->xml_escape($string)); } public function test_xml_escape_script_tag_handled_ok() { $exporter = new qformat_xml(); $input = '<script><![CDATA[alert(1<2);]]></script>'; $expected = '<![CDATA[<script><![CDATA[alert(1<2);]]]]><![CDATA[></script>]]>'; $this->assertEquals($expected, $exporter->xml_escape($input)); // Check that parsing the expected result does give the input again. $parsed = simplexml_load_string('<div>' . $expected . '</div>'); $this->assertEquals($input, $parsed->xpath('//div')[0]); } public function test_xml_escape_code_that_looks_like_cdata_end_ok() { $exporter = new qformat_xml(); $input = "if (x[[0]]>a) print('hah');"; $expected = "<![CDATA[if (x[[0]]]]><![CDATA[>a) print('hah');]]>"; $this->assertEquals($expected, $exporter->xml_escape($input)); // Check that parsing the expected result does give the input again. $parsed = simplexml_load_string('<div>' . $expected . '</div>'); $this->assertEquals($input, $parsed->xpath('//div')[0]); } public function test_write_hint_basic() { $q = $this->make_test_question(); $q->contextid = \context_system::instance()->id; $q->name = 'Short answer question'; $q->questiontext = 'Name an amphibian: __________'; $q->generalfeedback = 'Generalfeedback: frog or toad would have been OK.'; if (!isset($q->options)) {< $q->options = new stdClass();> $q->options = new \stdClass();} $q->options->usecase = false; $q->options->answers = array( 13 => new question_answer(13, 'frog', 1.0, 'Frog is a very good answer.', FORMAT_HTML), 14 => new question_answer(14, 'toad', 0.8, 'Toad is an OK good answer.', FORMAT_HTML), 15 => new question_answer(15, '*', 0.0, 'That is a bad answer.', FORMAT_HTML), ); $q->qtype = 'shortanswer'; $q->hints = array( new question_hint(0, 'This is the first hint.', FORMAT_MOODLE), ); $exporter = new qformat_xml(); $xml = $exporter->writequestion($q);< $this->assertRegExp('|<hint format=\"moodle_auto_format\">\s*<text>\s*' .> $this->assertMatchesRegularExpression('|<hint format=\"moodle_auto_format\">\s*<text>\s*' .'This is the first hint\.\s*</text>\s*</hint>|', $xml);< $this->assertNotRegExp('|<shownumcorrect/>|', $xml); < $this->assertNotRegExp('|<clearwrong/>|', $xml); < $this->assertNotRegExp('|<options>|', $xml);> $this->assertDoesNotMatchRegularExpression('|<shownumcorrect/>|', $xml); > $this->assertDoesNotMatchRegularExpression('|<clearwrong/>|', $xml); > $this->assertDoesNotMatchRegularExpression('|<options>|', $xml);} public function test_write_hint_with_parts() { $q = $this->make_test_question(); $q->contextid = \context_system::instance()->id; $q->name = 'Matching question'; $q->questiontext = 'Classify the animals.'; $q->generalfeedback = 'Frogs and toads are amphibians, the others are mammals.'; $q->qtype = 'match'; if (!isset($q->options)) {< $q->options = new stdClass();> $q->options = new \stdClass();} $q->options->shuffleanswers = 1; $q->options->correctfeedback = ''; $q->options->correctfeedbackformat = FORMAT_HTML; $q->options->partiallycorrectfeedback = ''; $q->options->partiallycorrectfeedbackformat = FORMAT_HTML; $q->options->incorrectfeedback = ''; $q->options->incorrectfeedbackformat = FORMAT_HTML; $q->options->subquestions = array(); $q->hints = array( new question_hint_with_parts(0, 'This is the first hint.', FORMAT_HTML, false, true), new question_hint_with_parts(0, 'This is the second hint.', FORMAT_HTML, true, false), ); $exporter = new qformat_xml(); $xml = $exporter->writequestion($q);< $this->assertRegExp(> $this->assertMatchesRegularExpression('|<hint format=\"html\">\s*<text>\s*This is the first hint\.\s*</text>|', $xml);< $this->assertRegExp(> $this->assertMatchesRegularExpression('|<hint format=\"html\">\s*<text>\s*This is the second hint\.\s*</text>|', $xml); list($ignored, $hint1, $hint2) = explode('<hint', $xml);< $this->assertNotRegExp('|<shownumcorrect/>|', $hint1); < $this->assertRegExp('|<clearwrong/>|', $hint1); < $this->assertRegExp('|<shownumcorrect/>|', $hint2); < $this->assertNotRegExp('|<clearwrong/>|', $hint2); < $this->assertNotRegExp('|<options>|', $xml);> $this->assertDoesNotMatchRegularExpression('|<shownumcorrect/>|', $hint1); > $this->assertMatchesRegularExpression('|<clearwrong/>|', $hint1); > $this->assertMatchesRegularExpression('|<shownumcorrect/>|', $hint2); > $this->assertDoesNotMatchRegularExpression('|<clearwrong/>|', $hint2); > $this->assertDoesNotMatchRegularExpression('|<options>|', $xml);} public function test_import_hints_no_parts() { $xml = <<<END <question> <hint> <text>This is the first hint</text> <clearwrong/> </hint> <hint> <text>This is the second hint</text> <shownumcorrect/> </hint> </question> END; $questionxml = xmlize($xml);< $qo = new stdClass();> $qo = new \stdClass();$importer = new qformat_xml(); $importer->import_hints($qo, $questionxml['question'], false, false, 'html'); $this->assertEquals(array( array('text' => 'This is the first hint', 'format' => FORMAT_HTML), array('text' => 'This is the second hint', 'format' => FORMAT_HTML), ), $qo->hint); $this->assertFalse(isset($qo->hintclearwrong)); $this->assertFalse(isset($qo->hintshownumcorrect)); } public function test_import_hints_with_parts() { $xml = <<<END <question> <hint> <text>This is the first hint</text> <clearwrong/> </hint> <hint> <text>This is the second hint</text> <shownumcorrect/> </hint> </question> END; $questionxml = xmlize($xml);< $qo = new stdClass();> $qo = new \stdClass();$importer = new qformat_xml(); $importer->import_hints($qo, $questionxml['question'], true, true, 'html'); $this->assertEquals(array( array('text' => 'This is the first hint', 'format' => FORMAT_HTML), array('text' => 'This is the second hint', 'format' => FORMAT_HTML), ), $qo->hint); $this->assertEquals(array(1, 0), $qo->hintclearwrong); $this->assertEquals(array(0, 1), $qo->hintshownumcorrect); } public function test_import_no_hints_no_error() { $xml = <<<END <question> </question> END; $questionxml = xmlize($xml);< $qo = new stdClass();> $qo = new \stdClass();$importer = new qformat_xml(); $importer->import_hints($qo, $questionxml['question'], 'html'); $this->assertFalse(isset($qo->hint)); } public function test_import_description() { $xml = ' <question type="description"> <name> <text>A description</text> </name> <questiontext format="html"> <text>The question text.</text> </questiontext> <generalfeedback> <text>Here is some general feedback.</text> </generalfeedback> <defaultgrade>0</defaultgrade> <penalty>0</penalty> <hidden>0</hidden> <tags> <tag><text>tagDescription</text></tag> <tag><text>tagTest</text></tag> </tags> </question>'; $xmldata = xmlize($xml); $importer = new qformat_xml(); $q = $importer->import_description($xmldata['question']);< $expectedq = new stdClass();> $expectedq = new \stdClass();$expectedq->qtype = 'description'; $expectedq->name = 'A description'; $expectedq->questiontext = 'The question text.'; $expectedq->questiontextformat = FORMAT_HTML; $expectedq->generalfeedback = 'Here is some general feedback.'; $expectedq->defaultmark = 0; $expectedq->length = 0; $expectedq->penalty = 0; $expectedq->tags = array('tagDescription', 'tagTest'); $this->assert(new question_check_specified_fields_expectation($expectedq), $q); } public function test_export_description() {< $qdata = new stdClass();> $qdata = new \stdClass();$qdata->id = 123; $qdata->contextid = \context_system::instance()->id; $qdata->qtype = 'description'; $qdata->name = 'A description'; $qdata->questiontext = 'The question text.'; $qdata->questiontextformat = FORMAT_HTML; $qdata->generalfeedback = 'Here is some general feedback.'; $qdata->generalfeedbackformat = FORMAT_HTML; $qdata->defaultmark = 0; $qdata->length = 0; $qdata->penalty = 0;< $qdata->hidden = 0;> $qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$qdata->idnumber = null; $exporter = new qformat_xml(); $xml = $exporter->writequestion($qdata); $expectedxml = '<!-- question: 123 --> <question type="description"> <name> <text>A description</text> </name> <questiontext format="html"> <text>The question text.</text> </questiontext> <generalfeedback format="html"> <text>Here is some general feedback.</text> </generalfeedback> <defaultgrade>0</defaultgrade> <penalty>0</penalty> <hidden>0</hidden> <idnumber></idnumber> </question> '; $this->assert_same_xml($expectedxml, $xml); } public function test_import_essay_20() { $xml = ' <question type="essay"> <name> <text>An essay</text> </name> <questiontext format="moodle_auto_format"> <text>Write something.</text> </questiontext> <generalfeedback> <text>I hope you wrote something interesting.</text> </generalfeedback> <defaultgrade>1</defaultgrade> <penalty>0</penalty> <hidden>0</hidden> <tags> <tag><text>tagEssay</text></tag> <tag><text>tagEssay20</text></tag> <tag><text>tagTest</text></tag> </tags> </question>'; $xmldata = xmlize($xml); $importer = new qformat_xml(); $q = $importer->import_essay($xmldata['question']);< $expectedq = new stdClass();> $expectedq = new \stdClass();$expectedq->qtype = 'essay'; $expectedq->name = 'An essay'; $expectedq->questiontext = 'Write something.'; $expectedq->questiontextformat = FORMAT_MOODLE; $expectedq->generalfeedback = 'I hope you wrote something interesting.'; $expectedq->defaultmark = 1; $expectedq->length = 1; $expectedq->penalty = 0; $expectedq->responseformat = 'editor'; $expectedq->responserequired = 1; $expectedq->responsefieldlines = 15;> $expectedq->minwordlimit = null; $expectedq->attachments = 0; > $expectedq->minwordenabled = false; $expectedq->attachmentsrequired = 0; > $expectedq->maxwordlimit = null; $expectedq->filetypeslist = null; > $expectedq->maxwordenabled = false;$expectedq->graderinfo['text'] = '';> $expectedq->maxbytes = 0;$expectedq->graderinfo['format'] = FORMAT_MOODLE; $expectedq->responsetemplate['text'] = ''; $expectedq->responsetemplate['format'] = FORMAT_MOODLE; $expectedq->tags = array('tagEssay', 'tagEssay20', 'tagTest'); $this->assert(new question_check_specified_fields_expectation($expectedq), $q); } public function test_import_essay_21() { $xml = ' <question type="essay"> <name> <text>An essay</text> </name> <questiontext format="moodle_auto_format"> <text>Write something.</text> </questiontext> <generalfeedback> <text>I hope you wrote something interesting.</text> </generalfeedback> <defaultgrade>1</defaultgrade> <penalty>0</penalty> <hidden>0</hidden> <responseformat>monospaced</responseformat> <responserequired>0</responserequired> <responsefieldlines>42</responsefieldlines> <attachments>-1</attachments> <attachmentsrequired>1</attachmentsrequired> <graderinfo format="html"> <text><![CDATA[<p>Grade <b>generously</b>!</p>]]></text> </graderinfo> <responsetemplate format="html"> <text><![CDATA[<p>Here is something <b>really</b> interesting.</p>]]></text> </responsetemplate> <tags> <tag><text>tagEssay</text></tag> <tag><text>tagEssay21</text></tag> <tag><text>tagTest</text></tag> </tags> </question>'; $xmldata = xmlize($xml); $importer = new qformat_xml(); $q = $importer->import_essay($xmldata['question']);< $expectedq = new stdClass();> $expectedq = new \stdClass();$expectedq->qtype = 'essay'; $expectedq->name = 'An essay'; $expectedq->questiontext = 'Write something.'; $expectedq->questiontextformat = FORMAT_MOODLE; $expectedq->generalfeedback = 'I hope you wrote something interesting.'; $expectedq->defaultmark = 1; $expectedq->length = 1; $expectedq->penalty = 0; $expectedq->responseformat = 'monospaced'; $expectedq->responserequired = 0; $expectedq->responsefieldlines = 42;> $expectedq->minwordlimit = null; $expectedq->attachments = -1; > $expectedq->minwordenabled = false; $expectedq->attachmentsrequired = 1; > $expectedq->maxwordlimit = null; $expectedq->filetypeslist = null; > $expectedq->maxwordenabled = false;$expectedq->graderinfo['text'] = '<p>Grade <b>generously</b>!</p>';> $expectedq->maxbytes = 0;$expectedq->graderinfo['format'] = FORMAT_HTML; $expectedq->responsetemplate['text'] = '<p>Here is something <b>really</b> interesting.</p>'; $expectedq->responsetemplate['format'] = FORMAT_HTML; $expectedq->tags = array('tagEssay', 'tagEssay21', 'tagTest'); $this->assert(new question_check_specified_fields_expectation($expectedq), $q); }> public function test_import_essay_311() { public function test_export_essay() { > $xml = ' <question type="essay"> $qdata = new stdClass(); > <name> $qdata->id = 123; > <text>An essay</text> $qdata->contextid = \context_system::instance()->id; > </name> $qdata->qtype = 'essay'; > <questiontext format="moodle_auto_format"> $qdata->name = 'An essay'; > <text>Write something.</text> $qdata->questiontext = 'Write something.'; > </questiontext> $qdata->questiontextformat = FORMAT_MOODLE; > <generalfeedback> $qdata->generalfeedback = 'I hope you wrote something interesting.'; > <text>I hope you wrote something interesting.</text> $qdata->generalfeedbackformat = FORMAT_MOODLE; > </generalfeedback> $qdata->defaultmark = 1; > <defaultgrade>1</defaultgrade> $qdata->length = 1; > <penalty>0</penalty> $qdata->penalty = 0; > <hidden>0</hidden> $qdata->hidden = 0; > <responseformat>monospaced</responseformat> $qdata->idnumber = null; > <responserequired>0</responserequired> $qdata->options = new stdClass(); > <responsefieldlines>42</responsefieldlines> $qdata->options->id = 456; > <minwordlimit>10</minwordlimit> $qdata->options->questionid = 123; > <maxwordlimit>20</maxwordlimit> $qdata->options->responseformat = 'monospaced'; > <attachments>-1</attachments> $qdata->options->responserequired = 0; > <attachmentsrequired>1</attachmentsrequired> $qdata->options->responsefieldlines = 42; > <maxbytes>52428800</maxbytes> $qdata->options->attachments = -1; > <filetypeslist>.pdf,.zip.,.docx</filetypeslist> $qdata->options->attachmentsrequired = 1; > <graderinfo format="html"> $qdata->options->graderinfo = '<p>Grade <b>generously</b>!</p>'; > <text><![CDATA[<p>Grade <b>generously</b>!</p>]]></text> $qdata->options->graderinfoformat = FORMAT_HTML; > </graderinfo> $qdata->options->responsetemplate = '<p>Here is something <b>really</b> interesting.</p>'; > <responsetemplate format="html"> $qdata->options->responsetemplateformat = FORMAT_HTML; > <text><![CDATA[<p>Here is something <b>really</b> interesting.</p>]]></text> $qdata->options->filetypeslist = '.pdf,.zip.,.docx'; > </responsetemplate> $exporter = new qformat_xml(); > <tags> $xml = $exporter->writequestion($qdata); > <tag><text>tagEssay</text></tag> > <tag><text>tagEssay21</text></tag> $expectedxml = '<!-- question: 123 --> > <tag><text>tagTest</text></tag> <question type="essay"> > </tags> <name> > </question>'; <text>An essay</text> > $xmldata = xmlize($xml); </name> > <questiontext format="moodle_auto_format"> > $importer = new qformat_xml(); <text>Write something.</text> > $q = $importer->import_essay($xmldata['question']); </questiontext> > <generalfeedback format="moodle_auto_format"> > $expectedq = new \stdClass(); <text>I hope you wrote something interesting.</text> > $expectedq->qtype = 'essay'; </generalfeedback> > $expectedq->name = 'An essay'; <defaultgrade>1</defaultgrade> > $expectedq->questiontext = 'Write something.'; <penalty>0</penalty> > $expectedq->questiontextformat = FORMAT_MOODLE; <hidden>0</hidden> > $expectedq->generalfeedback = 'I hope you wrote something interesting.'; <idnumber></idnumber> > $expectedq->defaultmark = 1; <responseformat>monospaced</responseformat> > $expectedq->length = 1; <responserequired>0</responserequired> > $expectedq->penalty = 0; <responsefieldlines>42</responsefieldlines> > $expectedq->responseformat = 'monospaced'; <attachments>-1</attachments> > $expectedq->responserequired = 0; <attachmentsrequired>1</attachmentsrequired> > $expectedq->responsefieldlines = 42; <filetypeslist>.pdf,.zip.,.docx</filetypeslist> > $expectedq->minwordlimit = 10; <graderinfo format="html"> > $expectedq->minwordenabled = true; <text><![CDATA[<p>Grade <b>generously</b>!</p>]]></text> > $expectedq->maxwordlimit = 20; </graderinfo> > $expectedq->maxwordenabled = true; <responsetemplate format="html"> > $expectedq->attachments = -1; <text><![CDATA[<p>Here is something <b>really</b> interesting.</p>]]></text> > $expectedq->attachmentsrequired = 1; </responsetemplate> > $expectedq->maxbytes = 52428800; // 50MB. </question> > $expectedq->filetypeslist = '.pdf,.zip.,.docx'; '; > $expectedq->graderinfo['text'] = '<p>Grade <b>generously</b>!</p>'; > $expectedq->graderinfo['format'] = FORMAT_HTML; $this->assert_same_xml($expectedxml, $xml); > $expectedq->responsetemplate['text'] = '<p>Here is something <b>really</b> interesting.</p>'; } > $expectedq->responsetemplate['format'] = FORMAT_HTML; > $expectedq->tags = array('tagEssay', 'tagEssay21', 'tagTest'); public function test_import_match_19() { > $xml = ' <question type="matching"> > $this->assert(new question_check_specified_fields_expectation($expectedq), $q); <name> > } <text>Matching question</text> >< $qdata = new stdClass();> $qdata = new \stdClass();< $qdata->hidden = 0;> $qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;< $qdata->options = new stdClass();> $qdata->options = new \stdClass();</questiontext>> $qdata->options->minwordlimit = 10; <generalfeedback> > $qdata->options->maxwordlimit = 20;<text>The answer is A -> a, B -> b and C -> c.</text>> $qdata->options->maxbytes = 52428800; // 50MB.</generalfeedback>> <minwordlimit>10</minwordlimit> <defaultgrade>1</defaultgrade> > <maxwordlimit>20</maxwordlimit><penalty>0.3333333</penalty>> <maxbytes>52428800</maxbytes><hidden>0</hidden> <shuffleanswers>false</shuffleanswers> <correctfeedback> <text>Well done.</text> </correctfeedback> <partiallycorrectfeedback> <text>Not entirely.</text> </partiallycorrectfeedback> <incorrectfeedback> <text>Completely wrong!</text> </incorrectfeedback> <subquestion> <text>A</text> <answer> <text>a</text> </answer> </subquestion> <subquestion> <text>B</text> <answer> <text>b</text> </answer> </subquestion> <subquestion> <text>C</text> <answer> <text>c</text> </answer> </subquestion> <subquestion> <text></text> <answer> <text>d</text> </answer> </subquestion> <hint> <text>Hint 1</text> <shownumcorrect /> </hint> <hint> <text></text> <shownumcorrect /> <clearwrong /> </hint> <tags> <tag><text>tagMatching</text></tag> <tag><text>tagTest</text></tag> </tags> </question>'; $xmldata = xmlize($xml); $importer = new qformat_xml(); $q = $importer->import_match($xmldata['question']);< $expectedq = new stdClass();> $expectedq = new \stdClass();$expectedq->qtype = 'match'; $expectedq->name = 'Matching question'; $expectedq->questiontext = 'Match the upper and lower case letters.'; $expectedq->questiontextformat = FORMAT_HTML; $expectedq->correctfeedback = array('text' => 'Well done.', 'format' => FORMAT_HTML); $expectedq->partiallycorrectfeedback = array('text' => 'Not entirely.', 'format' => FORMAT_HTML); $expectedq->shownumcorrect = false; $expectedq->incorrectfeedback = array('text' => 'Completely wrong!', 'format' => FORMAT_HTML); $expectedq->generalfeedback = 'The answer is A -> a, B -> b and C -> c.'; $expectedq->generalfeedbackformat = FORMAT_HTML; $expectedq->defaultmark = 1; $expectedq->length = 1; $expectedq->penalty = 0.3333333; $expectedq->shuffleanswers = 0; $expectedq->subquestions = array( array('text' => 'A', 'format' => FORMAT_HTML), array('text' => 'B', 'format' => FORMAT_HTML), array('text' => 'C', 'format' => FORMAT_HTML), array('text' => '', 'format' => FORMAT_HTML)); $expectedq->subanswers = array('a', 'b', 'c', 'd'); $expectedq->hint = array( array('text' => 'Hint 1', 'format' => FORMAT_HTML), array('text' => '', 'format' => FORMAT_HTML), ); $expectedq->hintshownumcorrect = array(true, true); $expectedq->hintclearwrong = array(false, true); $expectedq->tags = array('tagMatching', 'tagTest'); $this->assert(new question_check_specified_fields_expectation($expectedq), $q); } public function test_export_match() {< $qdata = new stdClass();> $qdata = new \stdClass();$qdata->id = 123; $qdata->contextid = \context_system::instance()->id; $qdata->qtype = 'match'; $qdata->name = 'Matching question'; $qdata->questiontext = 'Match the upper and lower case letters.'; $qdata->questiontextformat = FORMAT_HTML; $qdata->generalfeedback = 'The answer is A -> a, B -> b and C -> c.'; $qdata->generalfeedbackformat = FORMAT_HTML; $qdata->defaultmark = 1; $qdata->length = 1; $qdata->penalty = 0.3333333;< $qdata->hidden = 0;> $qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$qdata->idnumber = null;< $qdata->options = new stdClass();> $qdata->options = new \stdClass();$qdata->options->shuffleanswers = 1; $qdata->options->correctfeedback = 'Well done.'; $qdata->options->correctfeedbackformat = FORMAT_HTML; $qdata->options->partiallycorrectfeedback = 'Not entirely.'; $qdata->options->partiallycorrectfeedbackformat = FORMAT_HTML; $qdata->options->shownumcorrect = false; $qdata->options->incorrectfeedback = 'Completely wrong!'; $qdata->options->incorrectfeedbackformat = FORMAT_HTML;< $subq1 = new stdClass();> $subq1 = new \stdClass();$subq1->id = -4; $subq1->questiontext = 'A'; $subq1->questiontextformat = FORMAT_HTML; $subq1->answertext = 'a';< $subq2 = new stdClass();> $subq2 = new \stdClass();$subq2->id = -3; $subq2->questiontext = 'B'; $subq2->questiontextformat = FORMAT_HTML; $subq2->answertext = 'b';< $subq3 = new stdClass();> $subq3 = new \stdClass();$subq3->id = -2; $subq3->questiontext = 'C'; $subq3->questiontextformat = FORMAT_HTML; $subq3->answertext = 'c';< $subq4 = new stdClass();> $subq4 = new \stdClass();$subq4->id = -1; $subq4->questiontext = ''; $subq4->questiontextformat = FORMAT_HTML; $subq4->answertext = 'd'; $qdata->options->subquestions = array( $subq1, $subq2, $subq3, $subq4); $qdata->hints = array( new question_hint_with_parts(0, 'Hint 1', FORMAT_HTML, true, false), new question_hint_with_parts(0, '', FORMAT_HTML, true, true), ); $exporter = new qformat_xml(); $xml = $exporter->writequestion($qdata); $expectedxml = '<!-- question: 123 --> <question type="matching"> <name> <text>Matching question</text> </name> <questiontext format="html"> <text>Match the upper and lower case letters.</text> </questiontext> <generalfeedback format="html"> <text><![CDATA[The answer is A -> a, B -> b and C -> c.]]></text> </generalfeedback> <defaultgrade>1</defaultgrade> <penalty>0.3333333</penalty> <hidden>0</hidden> <idnumber></idnumber> <shuffleanswers>true</shuffleanswers> <correctfeedback format="html"> <text>Well done.</text> </correctfeedback> <partiallycorrectfeedback format="html"> <text>Not entirely.</text> </partiallycorrectfeedback> <incorrectfeedback format="html"> <text>Completely wrong!</text> </incorrectfeedback> <subquestion format="html"> <text>A</text> <answer> <text>a</text> </answer> </subquestion> <subquestion format="html"> <text>B</text> <answer> <text>b</text> </answer> </subquestion> <subquestion format="html"> <text>C</text> <answer> <text>c</text> </answer> </subquestion> <subquestion format="html"> <text></text> <answer> <text>d</text> </answer> </subquestion> <hint format="html"> <text>Hint 1</text> <shownumcorrect/> </hint> <hint format="html"> <text></text> <shownumcorrect/> <clearwrong/> </hint> </question> '; $this->assert_same_xml($expectedxml, $xml); } public function test_import_multichoice_19() { $xml = ' <question type="multichoice"> <name> <text>Multiple choice question</text> </name> <questiontext format="html"> <text>Which are the even numbers?</text> </questiontext> <generalfeedback> <text>The even numbers are 2 and 4.</text> </generalfeedback> <defaultgrade>2</defaultgrade> <penalty>0.3333333</penalty> <hidden>0</hidden> <single>false</single> <shuffleanswers>false</shuffleanswers> <answernumbering>abc</answernumbering> <correctfeedback> <text><![CDATA[<p>Your answer is correct.</p>]]></text> </correctfeedback> <partiallycorrectfeedback> <text><![CDATA[<p>Your answer is partially correct.</p>]]></text> </partiallycorrectfeedback> <incorrectfeedback> <text><![CDATA[<p>Your answer is incorrect.</p>]]></text> </incorrectfeedback> <shownumcorrect/> <answer fraction="0"> <text>1</text> <feedback> <text></text> </feedback> </answer> <answer fraction="100"> <text>2</text> <feedback> <text></text> </feedback> </answer> <answer fraction="0"> <text>3</text> <feedback> <text></text> </feedback> </answer> <answer fraction="100"> <text>4</text> <feedback> <text></text> </feedback> </answer> <hint> <text>Hint 1.</text> </hint> <hint> <text>Hint 2.</text> </hint> </question>'; $xmldata = xmlize($xml); $importer = new qformat_xml(); $q = $importer->import_multichoice($xmldata['question']);< $expectedq = new stdClass();> $expectedq = new \stdClass();$expectedq->qtype = 'multichoice'; $expectedq->name = 'Multiple choice question'; $expectedq->questiontext = 'Which are the even numbers?'; $expectedq->questiontextformat = FORMAT_HTML; $expectedq->correctfeedback = array( 'text' => '<p>Your answer is correct.</p>', 'format' => FORMAT_HTML); $expectedq->shownumcorrect = false; $expectedq->partiallycorrectfeedback = array( 'text' => '<p>Your answer is partially correct.</p>', 'format' => FORMAT_HTML); $expectedq->shownumcorrect = true; $expectedq->incorrectfeedback = array( 'text' => '<p>Your answer is incorrect.</p>', 'format' => FORMAT_HTML); $expectedq->generalfeedback = 'The even numbers are 2 and 4.'; $expectedq->defaultmark = 2; $expectedq->length = 1; $expectedq->penalty = 0.3333333; $expectedq->shuffleanswers = 0; $expectedq->single = false; $expectedq->answer = array( array('text' => '1', 'format' => FORMAT_HTML), array('text' => '2', 'format' => FORMAT_HTML), array('text' => '3', 'format' => FORMAT_HTML), array('text' => '4', 'format' => FORMAT_HTML)); $expectedq->fraction = array(0, 1, 0, 1); $expectedq->feedback = array( array('text' => '', 'format' => FORMAT_HTML), array('text' => '', 'format' => FORMAT_HTML), array('text' => '', 'format' => FORMAT_HTML), array('text' => '', 'format' => FORMAT_HTML)); $expectedq->hint = array( array('text' => 'Hint 1.', 'format' => FORMAT_HTML), array('text' => 'Hint 2.', 'format' => FORMAT_HTML), ); $expectedq->hintshownumcorrect = array(false, false); $expectedq->hintclearwrong = array(false, false); $this->assert(new question_check_specified_fields_expectation($expectedq), $q); } public function test_export_multichoice() {< $qdata = new stdClass();> $qdata = new \stdClass();$qdata->id = 123; $qdata->contextid = \context_system::instance()->id; $qdata->qtype = 'multichoice'; $qdata->name = 'Multiple choice question'; $qdata->questiontext = 'Which are the even numbers?'; $qdata->questiontextformat = FORMAT_HTML; $qdata->generalfeedback = 'The even numbers are 2 and 4.'; $qdata->generalfeedbackformat = FORMAT_HTML; $qdata->defaultmark = 2; $qdata->length = 1; $qdata->penalty = 0.3333333;< $qdata->hidden = 0;> $qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$qdata->idnumber = null;< $qdata->options = new stdClass();> $qdata->options = new \stdClass();$qdata->options->single = 0; $qdata->options->shuffleanswers = 0; $qdata->options->answernumbering = 'abc'; $qdata->options->showstandardinstruction = 0; $qdata->options->correctfeedback = '<p>Your answer is correct.</p>'; $qdata->options->correctfeedbackformat = FORMAT_HTML; $qdata->options->partiallycorrectfeedback = '<p>Your answer is partially correct.</p>'; $qdata->options->partiallycorrectfeedbackformat = FORMAT_HTML; $qdata->options->shownumcorrect = 1; $qdata->options->incorrectfeedback = '<p>Your answer is incorrect.</p>'; $qdata->options->incorrectfeedbackformat = FORMAT_HTML; $qdata->options->answers = array( 13 => new question_answer(13, '1', 0, '', FORMAT_HTML), 14 => new question_answer(14, '2', 1, '', FORMAT_HTML), 15 => new question_answer(15, '3', 0, '', FORMAT_HTML), 16 => new question_answer(16, '4', 1, '', FORMAT_HTML), ); $qdata->hints = array( new question_hint_with_parts(0, 'Hint 1.', FORMAT_HTML, false, false), new question_hint_with_parts(0, 'Hint 2.', FORMAT_HTML, false, false), ); $exporter = new qformat_xml(); $xml = $exporter->writequestion($qdata); $expectedxml = '<!-- question: 123 --> <question type="multichoice"> <name> <text>Multiple choice question</text> </name> <questiontext format="html"> <text>Which are the even numbers?</text> </questiontext> <generalfeedback format="html"> <text>The even numbers are 2 and 4.</text> </generalfeedback> <defaultgrade>2</defaultgrade> <penalty>0.3333333</penalty> <hidden>0</hidden> <idnumber></idnumber> <single>false</single> <shuffleanswers>false</shuffleanswers> <answernumbering>abc</answernumbering> <showstandardinstruction>0</showstandardinstruction> <correctfeedback format="html"> <text><![CDATA[<p>Your answer is correct.</p>]]></text> </correctfeedback> <partiallycorrectfeedback format="html"> <text><![CDATA[<p>Your answer is partially correct.</p>]]></text> </partiallycorrectfeedback> <incorrectfeedback format="html"> <text><![CDATA[<p>Your answer is incorrect.</p>]]></text> </incorrectfeedback> <shownumcorrect/> <answer fraction="0" format="plain_text"> <text>1</text> <feedback format="html"> <text></text> </feedback> </answer> <answer fraction="100" format="plain_text"> <text>2</text> <feedback format="html"> <text></text> </feedback> </answer> <answer fraction="0" format="plain_text"> <text>3</text> <feedback format="html"> <text></text> </feedback> </answer> <answer fraction="100" format="plain_text"> <text>4</text> <feedback format="html"> <text></text> </feedback> </answer> <hint format="html"> <text>Hint 1.</text> </hint> <hint format="html"> <text>Hint 2.</text> </hint> </question> '; $this->assert_same_xml($expectedxml, $xml); } public function test_import_numerical_19() { $xml = ' <question type="numerical"> <name> <text>Numerical question</text> </name> <questiontext format="html"> <text>What is the answer?</text> </questiontext> <generalfeedback> <text>General feedback: Think Hitch-hikers guide to the Galaxy.</text> </generalfeedback> <defaultgrade>1</defaultgrade> <penalty>0.1</penalty> <hidden>0</hidden> <answer fraction="100"> <text>42</text> <feedback> <text>Well done!</text> </feedback> <tolerance>0.001</tolerance> </answer> <answer fraction="0"> <text>13</text> <feedback> <text>What were you thinking?!</text> </feedback> <tolerance>1</tolerance> </answer> <answer fraction="0"> <text>*</text> <feedback> <text>Completely wrong.</text> </feedback> <tolerance></tolerance> </answer> </question>'; $xmldata = xmlize($xml); $importer = new qformat_xml(); $q = $importer->import_numerical($xmldata['question']);< $expectedq = new stdClass();> $expectedq = new \stdClass();$expectedq->qtype = 'numerical'; $expectedq->name = 'Numerical question'; $expectedq->questiontext = 'What is the answer?'; $expectedq->questiontextformat = FORMAT_HTML; $expectedq->generalfeedback = 'General feedback: Think Hitch-hikers guide to the Galaxy.'; $expectedq->generalfeedbackformat = FORMAT_HTML; $expectedq->defaultmark = 1; $expectedq->length = 1; $expectedq->penalty = 0.1; $expectedq->answer = array('42', '13', '*'); $expectedq->fraction = array(1, 0, 0); $expectedq->feedback = array( array('text' => 'Well done!', 'format' => FORMAT_HTML), array('text' => 'What were you thinking?!', 'format' => FORMAT_HTML), array('text' => 'Completely wrong.', 'format' => FORMAT_HTML));< $expectedq->tolerance = array(0.001, 1, 0);> $expectedq->tolerance = array(0.001, 1, '');$this->assert(new question_check_specified_fields_expectation($expectedq), $q); } public function test_export_numerical() { question_bank::load_question_definition_classes('numerical');< $qdata = new stdClass();> $qdata = new \stdClass();$qdata->id = 123; $qdata->contextid = \context_system::instance()->id; $qdata->qtype = 'numerical'; $qdata->name = 'Numerical question'; $qdata->questiontext = 'What is the answer?'; $qdata->questiontextformat = FORMAT_HTML; $qdata->generalfeedback = 'General feedback: Think Hitch-hikers guide to the Galaxy.'; $qdata->generalfeedbackformat = FORMAT_HTML; $qdata->defaultmark = 1; $qdata->length = 1; $qdata->penalty = 0.1;< $qdata->hidden = 0;> $qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$qdata->idnumber = null;< $qdata->options = new stdClass();> $qdata->options = new \stdClass();$qdata->options->answers = array( 13 => new qtype_numerical_answer(13, '42', 1, 'Well done!', FORMAT_HTML, 0.001), 14 => new qtype_numerical_answer(14, '13', 0, 'What were you thinking?!', FORMAT_HTML, 1), 15 => new qtype_numerical_answer(15, '*', 0, 'Completely wrong.', FORMAT_HTML, ''), ); $qdata->options->units = array(); $exporter = new qformat_xml(); $xml = $exporter->writequestion($qdata); $expectedxml = '<!-- question: 123 --> <question type="numerical"> <name> <text>Numerical question</text> </name> <questiontext format="html"> <text>What is the answer?</text> </questiontext> <generalfeedback format="html"> <text>General feedback: Think Hitch-hikers guide to the Galaxy.</text> </generalfeedback> <defaultgrade>1</defaultgrade> <penalty>0.1</penalty> <hidden>0</hidden> <idnumber></idnumber> <answer fraction="100" format="plain_text"> <text>42</text> <feedback format="html"> <text>Well done!</text> </feedback> <tolerance>0.001</tolerance> </answer> <answer fraction="0" format="plain_text"> <text>13</text> <feedback format="html"> <text>What were you thinking?!</text> </feedback> <tolerance>1</tolerance> </answer> <answer fraction="0" format="plain_text"> <text>*</text> <feedback format="html"> <text>Completely wrong.</text> </feedback> <tolerance>0</tolerance> </answer> </question> '; $this->assert_same_xml($expectedxml, $xml); } public function test_import_shortanswer_19() { $xml = ' <question type="shortanswer"> <name> <text>Short answer question</text> </name> <questiontext format="html"> <text>Fill in the gap in this sequence: Alpha, ________, Gamma.</text> </questiontext> <generalfeedback> <text>The answer is Beta.</text> </generalfeedback> <defaultgrade>1</defaultgrade> <penalty>0.3333333</penalty> <hidden>0</hidden> <usecase>0</usecase> <answer fraction="100" format="plain_text"> <text>Beta</text> <feedback> <text>Well done!</text> </feedback> </answer> <answer fraction="0" format="plain_text"> <text>*</text> <feedback> <text>Doh!</text> </feedback> </answer> <hint> <text>Hint 1</text> </hint> <hint> <text>Hint 2</text> </hint> </question>'; $xmldata = xmlize($xml); $importer = new qformat_xml(); $q = $importer->import_shortanswer($xmldata['question']);< $expectedq = new stdClass();> $expectedq = new \stdClass();$expectedq->qtype = 'shortanswer'; $expectedq->name = 'Short answer question'; $expectedq->questiontext = 'Fill in the gap in this sequence: Alpha, ________, Gamma.'; $expectedq->questiontextformat = FORMAT_HTML; $expectedq->generalfeedback = 'The answer is Beta.'; $expectedq->usecase = false; $expectedq->defaultmark = 1; $expectedq->length = 1; $expectedq->penalty = 0.3333333; $expectedq->answer = array('Beta', '*'); $expectedq->fraction = array(1, 0); $expectedq->feedback = array( array('text' => 'Well done!', 'format' => FORMAT_HTML), array('text' => 'Doh!', 'format' => FORMAT_HTML)); $this->assert(new question_check_specified_fields_expectation($expectedq), $q); } public function test_export_shortanswer() {< $qdata = new stdClass();> $qdata = new \stdClass();$qdata->id = 123; $qdata->contextid = \context_system::instance()->id; $qdata->qtype = 'shortanswer'; $qdata->name = 'Short answer question'; $qdata->questiontext = 'Fill in the gap in this sequence: Alpha, ________, Gamma.'; $qdata->questiontextformat = FORMAT_HTML; $qdata->generalfeedback = 'The answer is Beta.'; $qdata->generalfeedbackformat = FORMAT_HTML; $qdata->defaultmark = 1; $qdata->length = 1; $qdata->penalty = 0.3333333;< $qdata->hidden = 0;> $qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$qdata->idnumber = null;< $qdata->options = new stdClass();> $qdata->options = new \stdClass();$qdata->options->usecase = 0; $qdata->options->answers = array( 13 => new question_answer(13, 'Beta', 1, 'Well done!', FORMAT_HTML), 14 => new question_answer(14, '*', 0, 'Doh!', FORMAT_HTML), ); $qdata->hints = array( new question_hint(0, 'Hint 1', FORMAT_HTML), new question_hint(0, 'Hint 2', FORMAT_HTML), ); $exporter = new qformat_xml(); $xml = $exporter->writequestion($qdata); $expectedxml = '<!-- question: 123 --> <question type="shortanswer"> <name> <text>Short answer question</text> </name> <questiontext format="html"> <text>Fill in the gap in this sequence: Alpha, ________, Gamma.</text> </questiontext> <generalfeedback format="html"> <text>The answer is Beta.</text> </generalfeedback> <defaultgrade>1</defaultgrade> <penalty>0.3333333</penalty> <hidden>0</hidden> <idnumber></idnumber> <usecase>0</usecase> <answer fraction="100" format="plain_text"> <text>Beta</text> <feedback format="html"> <text>Well done!</text> </feedback> </answer> <answer fraction="0" format="plain_text"> <text>*</text> <feedback format="html"> <text>Doh!</text> </feedback> </answer> <hint format="html"> <text>Hint 1</text> </hint> <hint format="html"> <text>Hint 2</text> </hint> </question> '; $this->assert_same_xml($expectedxml, $xml); } public function test_import_truefalse_19() { $xml = ' <question type="truefalse"> <name> <text>True false question</text> </name> <questiontext format="html"> <text>The answer is true.</text> </questiontext> <generalfeedback> <text>General feedback: You should have chosen true.</text> </generalfeedback> <defaultgrade>1</defaultgrade> <penalty>1</penalty> <hidden>0</hidden> <answer fraction="100"> <text>true</text> <feedback> <text>Well done!</text> </feedback> </answer> <answer fraction="0"> <text>false</text> <feedback> <text>Doh!</text> </feedback> </answer> </question>'; $xmldata = xmlize($xml); $importer = new qformat_xml(); $q = $importer->import_truefalse($xmldata['question']);< $expectedq = new stdClass();> $expectedq = new \stdClass();$expectedq->qtype = 'truefalse'; $expectedq->name = 'True false question'; $expectedq->questiontext = 'The answer is true.'; $expectedq->questiontextformat = FORMAT_HTML; $expectedq->generalfeedback = 'General feedback: You should have chosen true.'; $expectedq->defaultmark = 1; $expectedq->length = 1; $expectedq->penalty = 1; $expectedq->feedbacktrue = array('text' => 'Well done!', 'format' => FORMAT_HTML); $expectedq->feedbackfalse = array('text' => 'Doh!', 'format' => FORMAT_HTML); $expectedq->correctanswer = true; $this->assert(new question_check_specified_fields_expectation($expectedq), $q); } public function test_import_truefalse_with_idnumber() { $xml = ' <question type="truefalse"> <name> <text>True false question</text> </name> <questiontext format="html"> <text>The answer is true.</text> </questiontext> <generalfeedback> <text>General feedback: You should have chosen true.</text> </generalfeedback> <defaultgrade>1</defaultgrade> <penalty>1</penalty> <hidden>0</hidden> <idnumber>TestIdNum1</idnumber> <answer fraction="100"> <text>true</text> <feedback> <text>Well done!</text> </feedback> </answer> <answer fraction="0"> <text>false</text> <feedback> <text>Doh!</text> </feedback> </answer> </question>'; $xmldata = xmlize($xml); $importer = new qformat_xml(); $q = $importer->import_truefalse($xmldata['question']);< $expectedq = new stdClass();> $expectedq = new \stdClass();$expectedq->qtype = 'truefalse'; $expectedq->name = 'True false question'; $expectedq->questiontext = 'The answer is true.'; $expectedq->questiontextformat = FORMAT_HTML; $expectedq->generalfeedback = 'General feedback: You should have chosen true.'; $expectedq->defaultmark = 1; $expectedq->length = 1; $expectedq->penalty = 1; $expectedq->idnumber = 'TestIdNum1'; $expectedq->feedbacktrue = array('text' => 'Well done!', 'format' => FORMAT_HTML); $expectedq->feedbackfalse = array('text' => 'Doh!', 'format' => FORMAT_HTML); $expectedq->correctanswer = true; $this->assert(new question_check_specified_fields_expectation($expectedq), $q); } public function test_export_truefalse() {< $qdata = new stdClass();> $qdata = new \stdClass();$qdata->id = 12; $qdata->contextid = \context_system::instance()->id; $qdata->qtype = 'truefalse'; $qdata->name = 'True false question'; $qdata->questiontext = 'The answer is true.'; $qdata->questiontextformat = FORMAT_HTML; $qdata->generalfeedback = 'General feedback: You should have chosen true.'; $qdata->generalfeedbackformat = FORMAT_HTML; $qdata->defaultmark = 1; $qdata->length = 1; $qdata->penalty = 1;< $qdata->hidden = 0;> $qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$qdata->idnumber = null;< $qdata->options = new stdClass();> $qdata->options = new \stdClass();$qdata->options->answers = array( 1 => new question_answer(1, 'True', 1, 'Well done!', FORMAT_HTML), 2 => new question_answer(2, 'False', 0, 'Doh!', FORMAT_HTML), ); $qdata->options->trueanswer = 1; $qdata->options->falseanswer = 2; $exporter = new qformat_xml(); $xml = $exporter->writequestion($qdata); $expectedxml = '<!-- question: 12 --> <question type="truefalse"> <name> <text>True false question</text> </name> <questiontext format="html"> <text>The answer is true.</text> </questiontext> <generalfeedback format="html"> <text>General feedback: You should have chosen true.</text> </generalfeedback> <defaultgrade>1</defaultgrade> <penalty>1</penalty> <hidden>0</hidden> <idnumber></idnumber> <answer fraction="100" format="plain_text"> <text>true</text> <feedback format="html"> <text>Well done!</text> </feedback> </answer> <answer fraction="0" format="plain_text"> <text>false</text> <feedback format="html"> <text>Doh!</text> </feedback> </answer> </question> '; $this->assert_same_xml($expectedxml, $xml); } public function test_export_truefalse_with_idnumber() {< $qdata = new stdClass();> $qdata = new \stdClass();$qdata->id = 12; $qdata->contextid = \context_system::instance()->id; $qdata->qtype = 'truefalse'; $qdata->name = 'True false question'; $qdata->questiontext = 'The answer is true.'; $qdata->questiontextformat = FORMAT_HTML; $qdata->generalfeedback = 'General feedback: You should have chosen true.'; $qdata->generalfeedbackformat = FORMAT_HTML; $qdata->defaultmark = 1; $qdata->length = 1; $qdata->penalty = 1;< $qdata->hidden = 0;> $qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$qdata->idnumber = 'TestIDNum2';< $qdata->options = new stdClass();> $qdata->options = new \stdClass();$qdata->options->answers = array( 1 => new question_answer(1, 'True', 1, 'Well done!', FORMAT_HTML), 2 => new question_answer(2, 'False', 0, 'Doh!', FORMAT_HTML), ); $qdata->options->trueanswer = 1; $qdata->options->falseanswer = 2; $exporter = new qformat_xml(); $xml = $exporter->writequestion($qdata); $expectedxml = '<!-- question: 12 --> <question type="truefalse"> <name> <text>True false question</text> </name> <questiontext format="html"> <text>The answer is true.</text> </questiontext> <generalfeedback format="html"> <text>General feedback: You should have chosen true.</text> </generalfeedback> <defaultgrade>1</defaultgrade> <penalty>1</penalty> <hidden>0</hidden> <idnumber>TestIDNum2</idnumber> <answer fraction="100" format="plain_text"> <text>true</text> <feedback format="html"> <text>Well done!</text> </feedback> </answer> <answer fraction="0" format="plain_text"> <text>false</text> <feedback format="html"> <text>Doh!</text> </feedback> </answer> </question> '; $this->assert_same_xml($expectedxml, $xml); } public function test_import_multianswer() { $xml = ' <question type="cloze"> <name> <text>Simple multianswer</text> </name> <questiontext format="html"> <text><![CDATA[Complete this opening line of verse: "The {1:SHORTANSWER:Dog#Wrong, silly!~=Owl#Well done!~*#Wrong answer} and the {1:MULTICHOICE:Bow-wow#You seem to have a dog obsessions!~Wiggly worm#Now you are just being ridiculous!~=Pussy-cat#Well done!} went to sea".]]></text> </questiontext> <generalfeedback format="html"> <text><![CDATA[General feedback: It\'s from "The Owl and the Pussy-cat" by Lear: "The owl and the pussycat went to sea".]]></text> </generalfeedback> <penalty>0.5</penalty> <hidden>0</hidden>> <idnumber>id-101</idnumber><hint format="html"> <text>Hint 1</text> </hint> <hint format="html"> <text>Hint 2</text> </hint> <tags> <tag><text>tagCloze</text></tag> <tag><text>tagTest</text></tag> </tags> </question> '; $xmldata = xmlize($xml); $importer = new qformat_xml(); $q = $importer->import_multianswer($xmldata['question']); // Annoyingly, import works in a weird way (it duplicates code, rather // than just calling save_question) so we cannot use< // test_question_maker::get_question_form_data('multianswer', 'twosubq'). < $expectedqa = new stdClass();> // \test_question_maker::get_question_form_data('multianswer', 'twosubq'). > $expectedqa = new \stdClass();$expectedqa->name = 'Simple multianswer'; $expectedqa->qtype = 'multianswer'; $expectedqa->questiontext = 'Complete this opening line of verse: "The {#1} and the {#2} went to sea".';> $expectedqa->idnumber = 'id-101';$expectedqa->generalfeedback = 'General feedback: It\'s from "The Owl and the Pussy-cat" by Lear: "The owl and the pussycat went to sea".'; $expectedqa->defaultmark = 2; $expectedqa->penalty = 0.5; $expectedqa->hint = array( array('text' => 'Hint 1', 'format' => FORMAT_HTML), array('text' => 'Hint 2', 'format' => FORMAT_HTML), );< $sa = new stdClass();> $sa = new \stdClass();$sa->questiontext = array('text' => '{1:SHORTANSWER:Dog#Wrong, silly!~=Owl#Well done!~*#Wrong answer}', 'format' => FORMAT_HTML, 'itemid' => null); $sa->generalfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null); $sa->defaultmark = 1.0; $sa->qtype = 'shortanswer'; $sa->usecase = 0; $sa->answer = array('Dog', 'Owl', '*'); $sa->fraction = array(0, 1, 0); $sa->feedback = array( array('text' => 'Wrong, silly!', 'format' => FORMAT_HTML, 'itemid' => null), array('text' => 'Well done!', 'format' => FORMAT_HTML, 'itemid' => null), array('text' => 'Wrong answer', 'format' => FORMAT_HTML, 'itemid' => null), );< $mc = new stdClass();> $mc = new \stdClass();$mc->generalfeedback = ''; $mc->questiontext = array('text' => '{1:MULTICHOICE:Bow-wow#You seem to have a dog obsessions!~' . 'Wiggly worm#Now you are just being ridiculous!~=Pussy-cat#Well done!}', 'format' => FORMAT_HTML, 'itemid' => null); $mc->generalfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null); $mc->defaultmark = 1.0; $mc->qtype = 'multichoice'; $mc->layout = 0; $mc->single = 1; $mc->shuffleanswers = 0; $mc->correctfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null); $mc->partiallycorrectfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null); $mc->incorrectfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null); $mc->answernumbering = 0; $mc->answer = array( array('text' => 'Bow-wow', 'format' => FORMAT_HTML, 'itemid' => null), array('text' => 'Wiggly worm', 'format' => FORMAT_HTML, 'itemid' => null), array('text' => 'Pussy-cat', 'format' => FORMAT_HTML, 'itemid' => null), ); $mc->fraction = array(0, 0, 1); $mc->feedback = array( array('text' => 'You seem to have a dog obsessions!', 'format' => FORMAT_HTML, 'itemid' => null), array('text' => 'Now you are just being ridiculous!', 'format' => FORMAT_HTML, 'itemid' => null), array('text' => 'Well done!', 'format' => FORMAT_HTML, 'itemid' => null), );< $expectedqa->options = new stdClass();> $expectedqa->options = new \stdClass();$expectedqa->options->questions = array( 1 => $sa, 2 => $mc, ); $expectedqa->tags = array('tagCloze', 'tagTest'); $this->assertEquals($expectedqa->hint, $q->hint); $this->assertEquals($expectedqa->options->questions[1], $q->options->questions[1]); $this->assertEquals($expectedqa->options->questions[2], $q->options->questions[2]); $this->assert(new question_check_specified_fields_expectation($expectedqa), $q); } public function test_export_multianswer() {< $qdata = test_question_maker::get_question_data('multianswer', 'twosubq');> $qdata = \test_question_maker::get_question_data('multianswer', 'twosubq');$qdata->contextid = \context_system::instance()->id; $exporter = new qformat_xml(); $xml = $exporter->writequestion($qdata); $expectedxml = '<!-- question: 0 --> <question type="cloze"> <name> <text>Simple multianswer</text> </name> <questiontext format="html"> <text><![CDATA[Complete this opening line of verse: "The {1:SHORTANSWER:Dog#Wrong, silly!~=Owl#Well done!~*#Wrong answer} and the {1:MULTICHOICE:Bow-wow#You seem to have a dog obsessions!~Wiggly worm#Now you are just being ridiculous!~=Pussy-cat#Well done!} went to sea".]]></text> </questiontext> <generalfeedback format="html"> <text><![CDATA[General feedback: It\'s from "The Owl and the Pussy-cat" by Lear: "The owl and the pussycat went to sea]]></text> </generalfeedback> <penalty>0.3333333</penalty> <hidden>0</hidden> <idnumber></idnumber> <hint format="html"> <text>Hint 1</text> </hint> <hint format="html"> <text>Hint 2</text> </hint> </question> '; $this->assert_same_xml($expectedxml, $xml); } public function test_export_multianswer_withdollars() {< $qdata = test_question_maker::get_question_data('multianswer', 'dollarsigns');> $qdata = \test_question_maker::get_question_data('multianswer', 'dollarsigns');$qdata->contextid = \context_system::instance()->id; $exporter = new qformat_xml(); $xml = $exporter->writequestion($qdata); $expectedxml = '<!-- question: 0 --> <question type="cloze"> <name> <text>Multianswer with $s</text> </name> <questiontext format="html"> <text>Which is the right order? {1:MULTICHOICE:=y,y,$3~$3,y,y}</text> </questiontext> <generalfeedback format="html"> <text></text> </generalfeedback> <penalty>0.3333333</penalty> <hidden>0</hidden> <idnumber></idnumber> </question> '; $this->assert_same_xml($expectedxml, $xml); } public function test_import_files_as_draft() { $this->resetAfterTest(); $this->setAdminUser(); $xml = <<<END <questiontext format="html"> <text><![CDATA[<p><a href="@@PLUGINFILE@@/moodle.txt">This text file</a> contains the word 'Moodle'.</p>]]></text> <file name="moodle.txt" encoding="base64">TW9vZGxl</file> </questiontext> END; $textxml = xmlize($xml);< $qo = new stdClass();> $qo = new \stdClass();$importer = new qformat_xml(); $draftitemid = $importer->import_files_as_draft($textxml['questiontext']['#']['file']); $files = file_get_drafarea_files($draftitemid); $this->assertEquals(1, count($files->list)); $file = $files->list[0]; $this->assertEquals('moodle.txt', $file->filename); $this->assertEquals('/', $file->filepath); $this->assertEquals(6, $file->size); } public function test_import_truefalse_wih_files() { $this->resetAfterTest(); $this->setAdminUser(); $xml = '<question type="truefalse"> <name> <text>truefalse</text> </name> <questiontext format="html"> <text><![CDATA[<p><a href="@@PLUGINFILE@@/myfolder/moodle.txt">This text file</a> contains the word Moodle.</p>]]></text> <file name="moodle.txt" path="/myfolder/" encoding="base64">TW9vZGxl</file> </questiontext> <generalfeedback format="html"> <text><![CDATA[<p>For further information, see the documentation about Moodle.</p>]]></text> </generalfeedback> <defaultgrade>1.0000000</defaultgrade> <penalty>1.0000000</penalty> <hidden>0</hidden> <answer fraction="100" format="moodle_auto_format"> <text>true</text> <feedback format="html"> <text></text> </feedback> </answer> <answer fraction="0" format="moodle_auto_format"> <text>false</text> <feedback format="html"> <text></text> </feedback> </answer> </question>'; $xmldata = xmlize($xml); $importer = new qformat_xml(); $q = $importer->import_truefalse($xmldata['question']); $draftitemid = $q->questiontextitemid; $files = file_get_drafarea_files($draftitemid, '/myfolder/'); $this->assertEquals(1, count($files->list)); $file = $files->list[0]; $this->assertEquals('moodle.txt', $file->filename); $this->assertEquals('/myfolder/', $file->filepath); $this->assertEquals(6, $file->size); } public function test_create_dummy_question() { $testobject = new mock_qformat_xml(); $categoryname = 'name1';< $categoryinfo = new stdClass();> $categoryinfo = new \stdClass();$categoryinfo->info = 'info1'; $categoryinfo->infoformat = 'infoformat1'; $categoryinfo->idnumber = null; $dummyquestion = $testobject->mock_create_dummy_question_representing_category($categoryname, $categoryinfo); $this->assertEquals('category', $dummyquestion->qtype); $this->assertEquals($categoryname, $dummyquestion->category); $this->assertEquals($categoryinfo->info, $dummyquestion->info); $this->assertEquals($categoryinfo->infoformat, $dummyquestion->infoformat); $this->assertEquals('Switch category to ' . $categoryname, $dummyquestion->name); $this->assertEquals(0, $dummyquestion->id); $this->assertEquals('', $dummyquestion->questiontextformat); $this->assertEquals(0, $dummyquestion->contextid); } } /** * Class mock_qformat_xml exists only to enable testing of the create dummy question category. * @package qformat_xml * @copyright 2018 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class mock_qformat_xml extends qformat_xml { /** * Make public an otherwise protected function. * @param string $categoryname the name of the category * @param object $categoryinfo description of the category */ public function mock_create_dummy_question_representing_category(string $categoryname, $categoryinfo) { return $this->create_dummy_question_representing_category($categoryname, $categoryinfo); } }