PageRenderTime 60ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/question/format/xml/tests/xmlformat_test.php

https://bitbucket.org/kudutest1/moodlegit
PHP | 1438 lines | 1253 code | 136 blank | 49 comment | 9 complexity | f75c6e66306d721086d995098216e074 MD5 | raw file
  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. * Unit tests for the Moodle XML format.
  18. *
  19. * @package qformat
  20. * @subpackage xml
  21. * @copyright 2010 The Open University
  22. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23. */
  24. defined('MOODLE_INTERNAL') || die();
  25. global $CFG;
  26. require_once($CFG->libdir . '/questionlib.php');
  27. require_once($CFG->dirroot . '/question/format/xml/format.php');
  28. require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
  29. /**
  30. * Unit tests for the matching question definition class.
  31. *
  32. * @copyright 2009 The Open University
  33. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  34. */
  35. class qformat_xml_test extends question_testcase {
  36. public function assert_same_xml($expectedxml, $xml) {
  37. $this->assertEquals(str_replace("\r\n", "\n", $expectedxml),
  38. str_replace("\r\n", "\n", $xml));
  39. }
  40. public function make_test_question() {
  41. global $USER;
  42. $q = new stdClass();
  43. $q->id = 0;
  44. $q->contextid = 0;
  45. $q->category = 0;
  46. $q->parent = 0;
  47. $q->questiontextformat = FORMAT_HTML;
  48. $q->generalfeedbackformat = FORMAT_HTML;
  49. $q->defaultmark = 1;
  50. $q->penalty = 0.3333333;
  51. $q->length = 1;
  52. $q->stamp = make_unique_id_code();
  53. $q->version = make_unique_id_code();
  54. $q->hidden = 0;
  55. $q->timecreated = time();
  56. $q->timemodified = time();
  57. $q->createdby = $USER->id;
  58. $q->modifiedby = $USER->id;
  59. return $q;
  60. }
  61. /**
  62. * The data the XML import format sends to save_question is not exactly
  63. * the same as the data returned from the editing form, so this method
  64. * makes necessary changes to the return value of
  65. * test_question_maker::get_question_form_data so that the tests can work.
  66. * @param object $expectedq as returned by get_question_form_data.
  67. * @return object one more likely to match the return value of import_...().
  68. */
  69. public function remove_irrelevant_form_data_fields($expectedq) {
  70. return $this->itemid_to_files($expectedq);
  71. }
  72. /**
  73. * Becuase XML import uses a files array instead of an itemid integer to
  74. * handle saving files with a question, we need to covert the output of
  75. * test_question_maker::get_question_form_data to match. This method recursively
  76. * replaces all array elements with key itemid with an array entry with
  77. * key files and value an empty array.
  78. *
  79. * @param mixed $var any data structure.
  80. * @return mixed an equivalent structure with the relacements made.
  81. */
  82. protected function itemid_to_files($var) {
  83. if (is_object($var)) {
  84. $newvar = new stdClass();
  85. foreach(get_object_vars($var) as $field => $value) {
  86. $newvar->$field = $this->itemid_to_files($value);
  87. }
  88. } else if (is_array($var)) {
  89. $newvar = array();
  90. foreach ($var as $index => $value) {
  91. if ($index === 'itemid') {
  92. $newvar['files'] = array();
  93. } else {
  94. $newvar[$index] = $this->itemid_to_files($value);
  95. }
  96. }
  97. } else {
  98. $newvar = $var;
  99. }
  100. return $newvar;
  101. }
  102. public function test_write_hint_basic() {
  103. $q = $this->make_test_question();
  104. $q->name = 'Short answer question';
  105. $q->questiontext = 'Name an amphibian: __________';
  106. $q->generalfeedback = 'Generalfeedback: frog or toad would have been OK.';
  107. if (!isset($q->options)) {
  108. $q->options = new stdClass();
  109. }
  110. $q->options->usecase = false;
  111. $q->options->answers = array(
  112. 13 => new question_answer(13, 'frog', 1.0, 'Frog is a very good answer.', FORMAT_HTML),
  113. 14 => new question_answer(14, 'toad', 0.8, 'Toad is an OK good answer.', FORMAT_HTML),
  114. 15 => new question_answer(15, '*', 0.0, 'That is a bad answer.', FORMAT_HTML),
  115. );
  116. $q->qtype = 'shortanswer';
  117. $q->hints = array(
  118. new question_hint(0, 'This is the first hint.', FORMAT_MOODLE),
  119. );
  120. $exporter = new qformat_xml();
  121. $xml = $exporter->writequestion($q);
  122. $this->assertRegExp('|<hint format=\"moodle_auto_format\">\s*<text>\s*' .
  123. 'This is the first hint\.\s*</text>\s*</hint>|', $xml);
  124. $this->assertNotRegExp('|<shownumcorrect/>|', $xml);
  125. $this->assertNotRegExp('|<clearwrong/>|', $xml);
  126. $this->assertNotRegExp('|<options>|', $xml);
  127. }
  128. public function test_write_hint_with_parts() {
  129. $q = $this->make_test_question();
  130. $q->name = 'Matching question';
  131. $q->questiontext = 'Classify the animals.';
  132. $q->generalfeedback = 'Frogs and toads are amphibians, the others are mammals.';
  133. $q->qtype = 'match';
  134. if (!isset($q->options)) {
  135. $q->options = new stdClass();
  136. }
  137. $q->options->shuffleanswers = 1;
  138. $q->options->correctfeedback = '';
  139. $q->options->correctfeedbackformat = FORMAT_HTML;
  140. $q->options->partiallycorrectfeedback = '';
  141. $q->options->partiallycorrectfeedbackformat = FORMAT_HTML;
  142. $q->options->incorrectfeedback = '';
  143. $q->options->incorrectfeedbackformat = FORMAT_HTML;
  144. $q->options->subquestions = array();
  145. $q->hints = array(
  146. new question_hint_with_parts(0, 'This is the first hint.', FORMAT_HTML, false, true),
  147. new question_hint_with_parts(0, 'This is the second hint.', FORMAT_HTML, true, false),
  148. );
  149. $exporter = new qformat_xml();
  150. $xml = $exporter->writequestion($q);
  151. $this->assertRegExp(
  152. '|<hint format=\"html\">\s*<text>\s*This is the first hint\.\s*</text>|', $xml);
  153. $this->assertRegExp(
  154. '|<hint format=\"html\">\s*<text>\s*This is the second hint\.\s*</text>|', $xml);
  155. list($ignored, $hint1, $hint2) = explode('<hint', $xml);
  156. $this->assertNotRegExp('|<shownumcorrect/>|', $hint1);
  157. $this->assertRegExp('|<clearwrong/>|', $hint1);
  158. $this->assertRegExp('|<shownumcorrect/>|', $hint2);
  159. $this->assertNotRegExp('|<clearwrong/>|', $hint2);
  160. $this->assertNotRegExp('|<options>|', $xml);
  161. }
  162. public function test_import_hints_no_parts() {
  163. $xml = <<<END
  164. <question>
  165. <hint>
  166. <text>This is the first hint</text>
  167. <clearwrong/>
  168. </hint>
  169. <hint>
  170. <text>This is the second hint</text>
  171. <shownumcorrect/>
  172. </hint>
  173. </question>
  174. END;
  175. $questionxml = xmlize($xml);
  176. $qo = new stdClass();
  177. $importer = new qformat_xml();
  178. $importer->import_hints($qo, $questionxml['question'], false, false, 'html');
  179. $this->assertEquals(array(
  180. array('text' => 'This is the first hint',
  181. 'format' => FORMAT_HTML),
  182. array('text' => 'This is the second hint',
  183. 'format' => FORMAT_HTML),
  184. ), $qo->hint);
  185. $this->assertFalse(isset($qo->hintclearwrong));
  186. $this->assertFalse(isset($qo->hintshownumcorrect));
  187. }
  188. public function test_import_hints_with_parts() {
  189. $xml = <<<END
  190. <question>
  191. <hint>
  192. <text>This is the first hint</text>
  193. <clearwrong/>
  194. </hint>
  195. <hint>
  196. <text>This is the second hint</text>
  197. <shownumcorrect/>
  198. </hint>
  199. </question>
  200. END;
  201. $questionxml = xmlize($xml);
  202. $qo = new stdClass();
  203. $importer = new qformat_xml();
  204. $importer->import_hints($qo, $questionxml['question'], true, true, 'html');
  205. $this->assertEquals(array(
  206. array('text' => 'This is the first hint',
  207. 'format' => FORMAT_HTML),
  208. array('text' => 'This is the second hint',
  209. 'format' => FORMAT_HTML),
  210. ), $qo->hint);
  211. $this->assertEquals(array(1, 0), $qo->hintclearwrong);
  212. $this->assertEquals(array(0, 1), $qo->hintshownumcorrect);
  213. }
  214. public function test_import_no_hints_no_error() {
  215. $xml = <<<END
  216. <question>
  217. </question>
  218. END;
  219. $questionxml = xmlize($xml);
  220. $qo = new stdClass();
  221. $importer = new qformat_xml();
  222. $importer->import_hints($qo, $questionxml['question'], 'html');
  223. $this->assertFalse(isset($qo->hint));
  224. }
  225. public function test_import_description() {
  226. $xml = ' <question type="description">
  227. <name>
  228. <text>A description</text>
  229. </name>
  230. <questiontext format="html">
  231. <text>The question text.</text>
  232. </questiontext>
  233. <generalfeedback>
  234. <text>Here is some general feedback.</text>
  235. </generalfeedback>
  236. <defaultgrade>0</defaultgrade>
  237. <penalty>0</penalty>
  238. <hidden>0</hidden>
  239. </question>';
  240. $xmldata = xmlize($xml);
  241. $importer = new qformat_xml();
  242. $q = $importer->import_description($xmldata['question']);
  243. $expectedq = new stdClass();
  244. $expectedq->qtype = 'description';
  245. $expectedq->name = 'A description';
  246. $expectedq->questiontext = 'The question text.';
  247. $expectedq->questiontextformat = FORMAT_HTML;
  248. $expectedq->generalfeedback = 'Here is some general feedback.';
  249. $expectedq->defaultmark = 0;
  250. $expectedq->length = 0;
  251. $expectedq->penalty = 0;
  252. $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
  253. }
  254. public function test_export_description() {
  255. $qdata = new stdClass();
  256. $qdata->id = 123;
  257. $qdata->contextid = 0;
  258. $qdata->qtype = 'description';
  259. $qdata->name = 'A description';
  260. $qdata->questiontext = 'The question text.';
  261. $qdata->questiontextformat = FORMAT_HTML;
  262. $qdata->generalfeedback = 'Here is some general feedback.';
  263. $qdata->generalfeedbackformat = FORMAT_HTML;
  264. $qdata->defaultmark = 0;
  265. $qdata->length = 0;
  266. $qdata->penalty = 0;
  267. $qdata->hidden = 0;
  268. $exporter = new qformat_xml();
  269. $xml = $exporter->writequestion($qdata);
  270. $expectedxml = '<!-- question: 123 -->
  271. <question type="description">
  272. <name>
  273. <text>A description</text>
  274. </name>
  275. <questiontext format="html">
  276. <text>The question text.</text>
  277. </questiontext>
  278. <generalfeedback format="html">
  279. <text>Here is some general feedback.</text>
  280. </generalfeedback>
  281. <defaultgrade>0</defaultgrade>
  282. <penalty>0</penalty>
  283. <hidden>0</hidden>
  284. </question>
  285. ';
  286. $this->assert_same_xml($expectedxml, $xml);
  287. }
  288. public function test_import_essay_20() {
  289. $xml = ' <question type="essay">
  290. <name>
  291. <text>An essay</text>
  292. </name>
  293. <questiontext format="moodle_auto_format">
  294. <text>Write something.</text>
  295. </questiontext>
  296. <generalfeedback>
  297. <text>I hope you wrote something interesting.</text>
  298. </generalfeedback>
  299. <defaultgrade>1</defaultgrade>
  300. <penalty>0</penalty>
  301. <hidden>0</hidden>
  302. </question>';
  303. $xmldata = xmlize($xml);
  304. $importer = new qformat_xml();
  305. $q = $importer->import_essay($xmldata['question']);
  306. $expectedq = new stdClass();
  307. $expectedq->qtype = 'essay';
  308. $expectedq->name = 'An essay';
  309. $expectedq->questiontext = 'Write something.';
  310. $expectedq->questiontextformat = FORMAT_MOODLE;
  311. $expectedq->generalfeedback = 'I hope you wrote something interesting.';
  312. $expectedq->defaultmark = 1;
  313. $expectedq->length = 1;
  314. $expectedq->penalty = 0;
  315. $expectedq->responseformat = 'editor';
  316. $expectedq->responsefieldlines = 15;
  317. $expectedq->attachments = 0;
  318. $expectedq->graderinfo['text'] = '';
  319. $expectedq->graderinfo['format'] = FORMAT_MOODLE;
  320. $expectedq->responsetemplate['text'] = '';
  321. $expectedq->responsetemplate['format'] = FORMAT_MOODLE;
  322. $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
  323. }
  324. public function test_import_essay_21() {
  325. $xml = ' <question type="essay">
  326. <name>
  327. <text>An essay</text>
  328. </name>
  329. <questiontext format="moodle_auto_format">
  330. <text>Write something.</text>
  331. </questiontext>
  332. <generalfeedback>
  333. <text>I hope you wrote something interesting.</text>
  334. </generalfeedback>
  335. <defaultgrade>1</defaultgrade>
  336. <penalty>0</penalty>
  337. <hidden>0</hidden>
  338. <responseformat>monospaced</responseformat>
  339. <responsefieldlines>42</responsefieldlines>
  340. <attachments>-1</attachments>
  341. <graderinfo format="html">
  342. <text><![CDATA[<p>Grade <b>generously</b>!</p>]]></text>
  343. </graderinfo>
  344. <responsetemplate format="html">
  345. <text><![CDATA[<p>Here is something <b>really</b> interesting.</p>]]></text>
  346. </responsetemplate>
  347. </question>';
  348. $xmldata = xmlize($xml);
  349. $importer = new qformat_xml();
  350. $q = $importer->import_essay($xmldata['question']);
  351. $expectedq = new stdClass();
  352. $expectedq->qtype = 'essay';
  353. $expectedq->name = 'An essay';
  354. $expectedq->questiontext = 'Write something.';
  355. $expectedq->questiontextformat = FORMAT_MOODLE;
  356. $expectedq->generalfeedback = 'I hope you wrote something interesting.';
  357. $expectedq->defaultmark = 1;
  358. $expectedq->length = 1;
  359. $expectedq->penalty = 0;
  360. $expectedq->responseformat = 'monospaced';
  361. $expectedq->responsefieldlines = 42;
  362. $expectedq->attachments = -1;
  363. $expectedq->graderinfo['text'] = '<p>Grade <b>generously</b>!</p>';
  364. $expectedq->graderinfo['format'] = FORMAT_HTML;
  365. $expectedq->responsetemplate['text'] = '<p>Here is something <b>really</b> interesting.</p>';
  366. $expectedq->responsetemplate['format'] = FORMAT_HTML;
  367. $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
  368. }
  369. public function test_export_essay() {
  370. $qdata = new stdClass();
  371. $qdata->id = 123;
  372. $qdata->contextid = 0;
  373. $qdata->qtype = 'essay';
  374. $qdata->name = 'An essay';
  375. $qdata->questiontext = 'Write something.';
  376. $qdata->questiontextformat = FORMAT_MOODLE;
  377. $qdata->generalfeedback = 'I hope you wrote something interesting.';
  378. $qdata->generalfeedbackformat = FORMAT_MOODLE;
  379. $qdata->defaultmark = 1;
  380. $qdata->length = 1;
  381. $qdata->penalty = 0;
  382. $qdata->hidden = 0;
  383. $qdata->options = new stdClass();
  384. $qdata->options->id = 456;
  385. $qdata->options->questionid = 123;
  386. $qdata->options->responseformat = 'monospaced';
  387. $qdata->options->responsefieldlines = 42;
  388. $qdata->options->attachments = -1;
  389. $qdata->options->graderinfo = '<p>Grade <b>generously</b>!</p>';
  390. $qdata->options->graderinfoformat = FORMAT_HTML;
  391. $qdata->options->responsetemplate = '<p>Here is something <b>really</b> interesting.</p>';
  392. $qdata->options->responsetemplateformat = FORMAT_HTML;
  393. $exporter = new qformat_xml();
  394. $xml = $exporter->writequestion($qdata);
  395. $expectedxml = '<!-- question: 123 -->
  396. <question type="essay">
  397. <name>
  398. <text>An essay</text>
  399. </name>
  400. <questiontext format="moodle_auto_format">
  401. <text>Write something.</text>
  402. </questiontext>
  403. <generalfeedback format="moodle_auto_format">
  404. <text>I hope you wrote something interesting.</text>
  405. </generalfeedback>
  406. <defaultgrade>1</defaultgrade>
  407. <penalty>0</penalty>
  408. <hidden>0</hidden>
  409. <responseformat>monospaced</responseformat>
  410. <responsefieldlines>42</responsefieldlines>
  411. <attachments>-1</attachments>
  412. <graderinfo format="html">
  413. <text><![CDATA[<p>Grade <b>generously</b>!</p>]]></text>
  414. </graderinfo>
  415. <responsetemplate format="html">
  416. <text><![CDATA[<p>Here is something <b>really</b> interesting.</p>]]></text>
  417. </responsetemplate>
  418. </question>
  419. ';
  420. $this->assert_same_xml($expectedxml, $xml);
  421. }
  422. public function test_import_match_19() {
  423. $xml = ' <question type="matching">
  424. <name>
  425. <text>Matching question</text>
  426. </name>
  427. <questiontext format="html">
  428. <text>Match the upper and lower case letters.</text>
  429. </questiontext>
  430. <generalfeedback>
  431. <text>The answer is A -> a, B -> b and C -> c.</text>
  432. </generalfeedback>
  433. <defaultgrade>1</defaultgrade>
  434. <penalty>0.3333333</penalty>
  435. <hidden>0</hidden>
  436. <shuffleanswers>false</shuffleanswers>
  437. <correctfeedback>
  438. <text>Well done.</text>
  439. </correctfeedback>
  440. <partiallycorrectfeedback>
  441. <text>Not entirely.</text>
  442. </partiallycorrectfeedback>
  443. <incorrectfeedback>
  444. <text>Completely wrong!</text>
  445. </incorrectfeedback>
  446. <subquestion>
  447. <text>A</text>
  448. <answer>
  449. <text>a</text>
  450. </answer>
  451. </subquestion>
  452. <subquestion>
  453. <text>B</text>
  454. <answer>
  455. <text>b</text>
  456. </answer>
  457. </subquestion>
  458. <subquestion>
  459. <text>C</text>
  460. <answer>
  461. <text>c</text>
  462. </answer>
  463. </subquestion>
  464. <subquestion>
  465. <text></text>
  466. <answer>
  467. <text>d</text>
  468. </answer>
  469. </subquestion>
  470. <hint>
  471. <text>Hint 1</text>
  472. <shownumcorrect />
  473. </hint>
  474. <hint>
  475. <text></text>
  476. <shownumcorrect />
  477. <clearwrong />
  478. </hint>
  479. </question>';
  480. $xmldata = xmlize($xml);
  481. $importer = new qformat_xml();
  482. $q = $importer->import_match($xmldata['question']);
  483. $expectedq = new stdClass();
  484. $expectedq->qtype = 'match';
  485. $expectedq->name = 'Matching question';
  486. $expectedq->questiontext = 'Match the upper and lower case letters.';
  487. $expectedq->questiontextformat = FORMAT_HTML;
  488. $expectedq->correctfeedback = array('text' => 'Well done.',
  489. 'format' => FORMAT_HTML);
  490. $expectedq->partiallycorrectfeedback = array('text' => 'Not entirely.',
  491. 'format' => FORMAT_HTML);
  492. $expectedq->shownumcorrect = false;
  493. $expectedq->incorrectfeedback = array('text' => 'Completely wrong!',
  494. 'format' => FORMAT_HTML);
  495. $expectedq->generalfeedback = 'The answer is A -> a, B -> b and C -> c.';
  496. $expectedq->generalfeedbackformat = FORMAT_HTML;
  497. $expectedq->defaultmark = 1;
  498. $expectedq->length = 1;
  499. $expectedq->penalty = 0.3333333;
  500. $expectedq->shuffleanswers = 0;
  501. $expectedq->subquestions = array(
  502. array('text' => 'A', 'format' => FORMAT_HTML),
  503. array('text' => 'B', 'format' => FORMAT_HTML),
  504. array('text' => 'C', 'format' => FORMAT_HTML),
  505. array('text' => '', 'format' => FORMAT_HTML));
  506. $expectedq->subanswers = array('a', 'b', 'c', 'd');
  507. $expectedq->hint = array(
  508. array('text' => 'Hint 1', 'format' => FORMAT_HTML),
  509. array('text' => '', 'format' => FORMAT_HTML),
  510. );
  511. $expectedq->hintshownumcorrect = array(true, true);
  512. $expectedq->hintclearwrong = array(false, true);
  513. $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
  514. }
  515. public function test_export_match() {
  516. $qdata = new stdClass();
  517. $qdata->id = 123;
  518. $qdata->contextid = 0;
  519. $qdata->qtype = 'match';
  520. $qdata->name = 'Matching question';
  521. $qdata->questiontext = 'Match the upper and lower case letters.';
  522. $qdata->questiontextformat = FORMAT_HTML;
  523. $qdata->generalfeedback = 'The answer is A -> a, B -> b and C -> c.';
  524. $qdata->generalfeedbackformat = FORMAT_HTML;
  525. $qdata->defaultmark = 1;
  526. $qdata->length = 1;
  527. $qdata->penalty = 0.3333333;
  528. $qdata->hidden = 0;
  529. $qdata->options = new stdClass();
  530. $qdata->options->shuffleanswers = 1;
  531. $qdata->options->correctfeedback = 'Well done.';
  532. $qdata->options->correctfeedbackformat = FORMAT_HTML;
  533. $qdata->options->partiallycorrectfeedback = 'Not entirely.';
  534. $qdata->options->partiallycorrectfeedbackformat = FORMAT_HTML;
  535. $qdata->options->shownumcorrect = false;
  536. $qdata->options->incorrectfeedback = 'Completely wrong!';
  537. $qdata->options->incorrectfeedbackformat = FORMAT_HTML;
  538. $subq1 = new stdClass();
  539. $subq1->id = -4;
  540. $subq1->questiontext = 'A';
  541. $subq1->questiontextformat = FORMAT_HTML;
  542. $subq1->answertext = 'a';
  543. $subq2 = new stdClass();
  544. $subq2->id = -3;
  545. $subq2->questiontext = 'B';
  546. $subq2->questiontextformat = FORMAT_HTML;
  547. $subq2->answertext = 'b';
  548. $subq3 = new stdClass();
  549. $subq3->id = -2;
  550. $subq3->questiontext = 'C';
  551. $subq3->questiontextformat = FORMAT_HTML;
  552. $subq3->answertext = 'c';
  553. $subq4 = new stdClass();
  554. $subq4->id = -1;
  555. $subq4->questiontext = '';
  556. $subq4->questiontextformat = FORMAT_HTML;
  557. $subq4->answertext = 'd';
  558. $qdata->options->subquestions = array(
  559. $subq1, $subq2, $subq3, $subq4);
  560. $qdata->hints = array(
  561. new question_hint_with_parts(0, 'Hint 1', FORMAT_HTML, true, false),
  562. new question_hint_with_parts(0, '', FORMAT_HTML, true, true),
  563. );
  564. $exporter = new qformat_xml();
  565. $xml = $exporter->writequestion($qdata);
  566. $expectedxml = '<!-- question: 123 -->
  567. <question type="matching">
  568. <name>
  569. <text>Matching question</text>
  570. </name>
  571. <questiontext format="html">
  572. <text>Match the upper and lower case letters.</text>
  573. </questiontext>
  574. <generalfeedback format="html">
  575. <text><![CDATA[The answer is A -> a, B -> b and C -> c.]]></text>
  576. </generalfeedback>
  577. <defaultgrade>1</defaultgrade>
  578. <penalty>0.3333333</penalty>
  579. <hidden>0</hidden>
  580. <shuffleanswers>true</shuffleanswers>
  581. <correctfeedback format="html">
  582. <text>Well done.</text>
  583. </correctfeedback>
  584. <partiallycorrectfeedback format="html">
  585. <text>Not entirely.</text>
  586. </partiallycorrectfeedback>
  587. <incorrectfeedback format="html">
  588. <text>Completely wrong!</text>
  589. </incorrectfeedback>
  590. <subquestion format="html">
  591. <text>A</text>
  592. <answer>
  593. <text>a</text>
  594. </answer>
  595. </subquestion>
  596. <subquestion format="html">
  597. <text>B</text>
  598. <answer>
  599. <text>b</text>
  600. </answer>
  601. </subquestion>
  602. <subquestion format="html">
  603. <text>C</text>
  604. <answer>
  605. <text>c</text>
  606. </answer>
  607. </subquestion>
  608. <subquestion format="html">
  609. <text></text>
  610. <answer>
  611. <text>d</text>
  612. </answer>
  613. </subquestion>
  614. <hint format="html">
  615. <text>Hint 1</text>
  616. <shownumcorrect/>
  617. </hint>
  618. <hint format="html">
  619. <text></text>
  620. <shownumcorrect/>
  621. <clearwrong/>
  622. </hint>
  623. </question>
  624. ';
  625. $this->assert_same_xml($expectedxml, $xml);
  626. }
  627. public function test_import_multichoice_19() {
  628. $xml = ' <question type="multichoice">
  629. <name>
  630. <text>Multiple choice question</text>
  631. </name>
  632. <questiontext format="html">
  633. <text>Which are the even numbers?</text>
  634. </questiontext>
  635. <generalfeedback>
  636. <text>The even numbers are 2 and 4.</text>
  637. </generalfeedback>
  638. <defaultgrade>2</defaultgrade>
  639. <penalty>0.3333333</penalty>
  640. <hidden>0</hidden>
  641. <single>false</single>
  642. <shuffleanswers>false</shuffleanswers>
  643. <answernumbering>abc</answernumbering>
  644. <correctfeedback>
  645. <text><![CDATA[<p>Your answer is correct.</p>]]></text>
  646. </correctfeedback>
  647. <partiallycorrectfeedback>
  648. <text><![CDATA[<p>Your answer is partially correct.</p>]]></text>
  649. </partiallycorrectfeedback>
  650. <incorrectfeedback>
  651. <text><![CDATA[<p>Your answer is incorrect.</p>]]></text>
  652. </incorrectfeedback>
  653. <shownumcorrect/>
  654. <answer fraction="0">
  655. <text>1</text>
  656. <feedback>
  657. <text></text>
  658. </feedback>
  659. </answer>
  660. <answer fraction="100">
  661. <text>2</text>
  662. <feedback>
  663. <text></text>
  664. </feedback>
  665. </answer>
  666. <answer fraction="0">
  667. <text>3</text>
  668. <feedback>
  669. <text></text>
  670. </feedback>
  671. </answer>
  672. <answer fraction="100">
  673. <text>4</text>
  674. <feedback>
  675. <text></text>
  676. </feedback>
  677. </answer>
  678. <hint>
  679. <text>Hint 1.</text>
  680. </hint>
  681. <hint>
  682. <text>Hint 2.</text>
  683. </hint>
  684. </question>';
  685. $xmldata = xmlize($xml);
  686. $importer = new qformat_xml();
  687. $q = $importer->import_multichoice($xmldata['question']);
  688. $expectedq = new stdClass();
  689. $expectedq->qtype = 'multichoice';
  690. $expectedq->name = 'Multiple choice question';
  691. $expectedq->questiontext = 'Which are the even numbers?';
  692. $expectedq->questiontextformat = FORMAT_HTML;
  693. $expectedq->correctfeedback = array(
  694. 'text' => '<p>Your answer is correct.</p>',
  695. 'format' => FORMAT_HTML);
  696. $expectedq->shownumcorrect = false;
  697. $expectedq->partiallycorrectfeedback = array(
  698. 'text' => '<p>Your answer is partially correct.</p>',
  699. 'format' => FORMAT_HTML);
  700. $expectedq->shownumcorrect = true;
  701. $expectedq->incorrectfeedback = array(
  702. 'text' => '<p>Your answer is incorrect.</p>',
  703. 'format' => FORMAT_HTML);
  704. $expectedq->generalfeedback = 'The even numbers are 2 and 4.';
  705. $expectedq->defaultmark = 2;
  706. $expectedq->length = 1;
  707. $expectedq->penalty = 0.3333333;
  708. $expectedq->shuffleanswers = 0;
  709. $expectedq->single = false;
  710. $expectedq->answer = array(
  711. array('text' => '1', 'format' => FORMAT_HTML),
  712. array('text' => '2', 'format' => FORMAT_HTML),
  713. array('text' => '3', 'format' => FORMAT_HTML),
  714. array('text' => '4', 'format' => FORMAT_HTML));
  715. $expectedq->fraction = array(0, 1, 0, 1);
  716. $expectedq->feedback = array(
  717. array('text' => '', 'format' => FORMAT_HTML),
  718. array('text' => '', 'format' => FORMAT_HTML),
  719. array('text' => '', 'format' => FORMAT_HTML),
  720. array('text' => '', 'format' => FORMAT_HTML));
  721. $expectedq->hint = array(
  722. array('text' => 'Hint 1.', 'format' => FORMAT_HTML),
  723. array('text' => 'Hint 2.', 'format' => FORMAT_HTML),
  724. );
  725. $expectedq->hintshownumcorrect = array(false, false);
  726. $expectedq->hintclearwrong = array(false, false);
  727. $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
  728. }
  729. public function test_export_multichoice() {
  730. $qdata = new stdClass();
  731. $qdata->id = 123;
  732. $qdata->contextid = 0;
  733. $qdata->qtype = 'multichoice';
  734. $qdata->name = 'Multiple choice question';
  735. $qdata->questiontext = 'Which are the even numbers?';
  736. $qdata->questiontextformat = FORMAT_HTML;
  737. $qdata->generalfeedback = 'The even numbers are 2 and 4.';
  738. $qdata->generalfeedbackformat = FORMAT_HTML;
  739. $qdata->defaultmark = 2;
  740. $qdata->length = 1;
  741. $qdata->penalty = 0.3333333;
  742. $qdata->hidden = 0;
  743. $qdata->options = new stdClass();
  744. $qdata->options->single = 0;
  745. $qdata->options->shuffleanswers = 0;
  746. $qdata->options->answernumbering = 'abc';
  747. $qdata->options->correctfeedback = '<p>Your answer is correct.</p>';
  748. $qdata->options->correctfeedbackformat = FORMAT_HTML;
  749. $qdata->options->partiallycorrectfeedback = '<p>Your answer is partially correct.</p>';
  750. $qdata->options->partiallycorrectfeedbackformat = FORMAT_HTML;
  751. $qdata->options->shownumcorrect = 1;
  752. $qdata->options->incorrectfeedback = '<p>Your answer is incorrect.</p>';
  753. $qdata->options->incorrectfeedbackformat = FORMAT_HTML;
  754. $qdata->options->answers = array(
  755. 13 => new question_answer(13, '1', 0, '', FORMAT_HTML),
  756. 14 => new question_answer(14, '2', 1, '', FORMAT_HTML),
  757. 15 => new question_answer(15, '3', 0, '', FORMAT_HTML),
  758. 16 => new question_answer(16, '4', 1, '', FORMAT_HTML),
  759. );
  760. $qdata->hints = array(
  761. new question_hint_with_parts(0, 'Hint 1.', FORMAT_HTML, false, false),
  762. new question_hint_with_parts(0, 'Hint 2.', FORMAT_HTML, false, false),
  763. );
  764. $exporter = new qformat_xml();
  765. $xml = $exporter->writequestion($qdata);
  766. $expectedxml = '<!-- question: 123 -->
  767. <question type="multichoice">
  768. <name>
  769. <text>Multiple choice question</text>
  770. </name>
  771. <questiontext format="html">
  772. <text>Which are the even numbers?</text>
  773. </questiontext>
  774. <generalfeedback format="html">
  775. <text>The even numbers are 2 and 4.</text>
  776. </generalfeedback>
  777. <defaultgrade>2</defaultgrade>
  778. <penalty>0.3333333</penalty>
  779. <hidden>0</hidden>
  780. <single>false</single>
  781. <shuffleanswers>false</shuffleanswers>
  782. <answernumbering>abc</answernumbering>
  783. <correctfeedback format="html">
  784. <text><![CDATA[<p>Your answer is correct.</p>]]></text>
  785. </correctfeedback>
  786. <partiallycorrectfeedback format="html">
  787. <text><![CDATA[<p>Your answer is partially correct.</p>]]></text>
  788. </partiallycorrectfeedback>
  789. <incorrectfeedback format="html">
  790. <text><![CDATA[<p>Your answer is incorrect.</p>]]></text>
  791. </incorrectfeedback>
  792. <shownumcorrect/>
  793. <answer fraction="0" format="plain_text">
  794. <text>1</text>
  795. <feedback format="html">
  796. <text></text>
  797. </feedback>
  798. </answer>
  799. <answer fraction="100" format="plain_text">
  800. <text>2</text>
  801. <feedback format="html">
  802. <text></text>
  803. </feedback>
  804. </answer>
  805. <answer fraction="0" format="plain_text">
  806. <text>3</text>
  807. <feedback format="html">
  808. <text></text>
  809. </feedback>
  810. </answer>
  811. <answer fraction="100" format="plain_text">
  812. <text>4</text>
  813. <feedback format="html">
  814. <text></text>
  815. </feedback>
  816. </answer>
  817. <hint format="html">
  818. <text>Hint 1.</text>
  819. </hint>
  820. <hint format="html">
  821. <text>Hint 2.</text>
  822. </hint>
  823. </question>
  824. ';
  825. $this->assert_same_xml($expectedxml, $xml);
  826. }
  827. public function test_import_numerical_19() {
  828. $xml = ' <question type="numerical">
  829. <name>
  830. <text>Numerical question</text>
  831. </name>
  832. <questiontext format="html">
  833. <text>What is the answer?</text>
  834. </questiontext>
  835. <generalfeedback>
  836. <text>General feedback: Think Hitch-hikers guide to the Galaxy.</text>
  837. </generalfeedback>
  838. <defaultgrade>1</defaultgrade>
  839. <penalty>0.1</penalty>
  840. <hidden>0</hidden>
  841. <answer fraction="100">
  842. <text>42</text>
  843. <feedback>
  844. <text>Well done!</text>
  845. </feedback>
  846. <tolerance>0.001</tolerance>
  847. </answer>
  848. <answer fraction="0">
  849. <text>13</text>
  850. <feedback>
  851. <text>What were you thinking?!</text>
  852. </feedback>
  853. <tolerance>1</tolerance>
  854. </answer>
  855. <answer fraction="0">
  856. <text>*</text>
  857. <feedback>
  858. <text>Completely wrong.</text>
  859. </feedback>
  860. <tolerance></tolerance>
  861. </answer>
  862. </question>';
  863. $xmldata = xmlize($xml);
  864. $importer = new qformat_xml();
  865. $q = $importer->import_numerical($xmldata['question']);
  866. $expectedq = new stdClass();
  867. $expectedq->qtype = 'numerical';
  868. $expectedq->name = 'Numerical question';
  869. $expectedq->questiontext = 'What is the answer?';
  870. $expectedq->questiontextformat = FORMAT_HTML;
  871. $expectedq->generalfeedback = 'General feedback: Think Hitch-hikers guide to the Galaxy.';
  872. $expectedq->generalfeedbackformat = FORMAT_HTML;
  873. $expectedq->defaultmark = 1;
  874. $expectedq->length = 1;
  875. $expectedq->penalty = 0.1;
  876. $expectedq->answer = array('42', '13', '*');
  877. $expectedq->fraction = array(1, 0, 0);
  878. $expectedq->feedback = array(
  879. array('text' => 'Well done!',
  880. 'format' => FORMAT_HTML),
  881. array('text' => 'What were you thinking?!',
  882. 'format' => FORMAT_HTML),
  883. array('text' => 'Completely wrong.',
  884. 'format' => FORMAT_HTML));
  885. $expectedq->tolerance = array(0.001, 1, 0);
  886. $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
  887. }
  888. public function test_export_numerical() {
  889. question_bank::load_question_definition_classes('numerical');
  890. $qdata = new stdClass();
  891. $qdata->id = 123;
  892. $qdata->contextid = 0;
  893. $qdata->qtype = 'numerical';
  894. $qdata->name = 'Numerical question';
  895. $qdata->questiontext = 'What is the answer?';
  896. $qdata->questiontextformat = FORMAT_HTML;
  897. $qdata->generalfeedback = 'General feedback: Think Hitch-hikers guide to the Galaxy.';
  898. $qdata->generalfeedbackformat = FORMAT_HTML;
  899. $qdata->defaultmark = 1;
  900. $qdata->length = 1;
  901. $qdata->penalty = 0.1;
  902. $qdata->hidden = 0;
  903. $qdata->options = new stdClass();
  904. $qdata->options->answers = array(
  905. 13 => new qtype_numerical_answer(13, '42', 1, 'Well done!',
  906. FORMAT_HTML, 0.001),
  907. 14 => new qtype_numerical_answer(14, '13', 0, 'What were you thinking?!',
  908. FORMAT_HTML, 1),
  909. 15 => new qtype_numerical_answer(15, '*', 0, 'Completely wrong.',
  910. FORMAT_HTML, ''),
  911. );
  912. $qdata->options->units = array();
  913. $exporter = new qformat_xml();
  914. $xml = $exporter->writequestion($qdata);
  915. $expectedxml = '<!-- question: 123 -->
  916. <question type="numerical">
  917. <name>
  918. <text>Numerical question</text>
  919. </name>
  920. <questiontext format="html">
  921. <text>What is the answer?</text>
  922. </questiontext>
  923. <generalfeedback format="html">
  924. <text>General feedback: Think Hitch-hikers guide to the Galaxy.</text>
  925. </generalfeedback>
  926. <defaultgrade>1</defaultgrade>
  927. <penalty>0.1</penalty>
  928. <hidden>0</hidden>
  929. <answer fraction="100" format="plain_text">
  930. <text>42</text>
  931. <feedback format="html">
  932. <text>Well done!</text>
  933. </feedback>
  934. <tolerance>0.001</tolerance>
  935. </answer>
  936. <answer fraction="0" format="plain_text">
  937. <text>13</text>
  938. <feedback format="html">
  939. <text>What were you thinking?!</text>
  940. </feedback>
  941. <tolerance>1</tolerance>
  942. </answer>
  943. <answer fraction="0" format="plain_text">
  944. <text>*</text>
  945. <feedback format="html">
  946. <text>Completely wrong.</text>
  947. </feedback>
  948. <tolerance>0</tolerance>
  949. </answer>
  950. </question>
  951. ';
  952. $this->assert_same_xml($expectedxml, $xml);
  953. }
  954. public function test_import_shortanswer_19() {
  955. $xml = ' <question type="shortanswer">
  956. <name>
  957. <text>Short answer question</text>
  958. </name>
  959. <questiontext format="html">
  960. <text>Fill in the gap in this sequence: Alpha, ________, Gamma.</text>
  961. </questiontext>
  962. <generalfeedback>
  963. <text>The answer is Beta.</text>
  964. </generalfeedback>
  965. <defaultgrade>1</defaultgrade>
  966. <penalty>0.3333333</penalty>
  967. <hidden>0</hidden>
  968. <usecase>0</usecase>
  969. <answer fraction="100" format="plain_text">
  970. <text>Beta</text>
  971. <feedback>
  972. <text>Well done!</text>
  973. </feedback>
  974. </answer>
  975. <answer fraction="0" format="plain_text">
  976. <text>*</text>
  977. <feedback>
  978. <text>Doh!</text>
  979. </feedback>
  980. </answer>
  981. <hint>
  982. <text>Hint 1</text>
  983. </hint>
  984. <hint>
  985. <text>Hint 2</text>
  986. </hint>
  987. </question>';
  988. $xmldata = xmlize($xml);
  989. $importer = new qformat_xml();
  990. $q = $importer->import_shortanswer($xmldata['question']);
  991. $expectedq = new stdClass();
  992. $expectedq->qtype = 'shortanswer';
  993. $expectedq->name = 'Short answer question';
  994. $expectedq->questiontext = 'Fill in the gap in this sequence: Alpha, ________, Gamma.';
  995. $expectedq->questiontextformat = FORMAT_HTML;
  996. $expectedq->generalfeedback = 'The answer is Beta.';
  997. $expectedq->usecase = false;
  998. $expectedq->defaultmark = 1;
  999. $expectedq->length = 1;
  1000. $expectedq->penalty = 0.3333333;
  1001. $expectedq->answer = array('Beta', '*');
  1002. $expectedq->fraction = array(1, 0);
  1003. $expectedq->feedback = array(
  1004. array('text' => 'Well done!', 'format' => FORMAT_HTML),
  1005. array('text' => 'Doh!', 'format' => FORMAT_HTML));
  1006. $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
  1007. }
  1008. public function test_export_shortanswer() {
  1009. $qdata = new stdClass();
  1010. $qdata->id = 123;
  1011. $qdata->contextid = 0;
  1012. $qdata->qtype = 'shortanswer';
  1013. $qdata->name = 'Short answer question';
  1014. $qdata->questiontext = 'Fill in the gap in this sequence: Alpha, ________, Gamma.';
  1015. $qdata->questiontextformat = FORMAT_HTML;
  1016. $qdata->generalfeedback = 'The answer is Beta.';
  1017. $qdata->generalfeedbackformat = FORMAT_HTML;
  1018. $qdata->defaultmark = 1;
  1019. $qdata->length = 1;
  1020. $qdata->penalty = 0.3333333;
  1021. $qdata->hidden = 0;
  1022. $qdata->options = new stdClass();
  1023. $qdata->options->usecase = 0;
  1024. $qdata->options->answers = array(
  1025. 13 => new question_answer(13, 'Beta', 1, 'Well done!', FORMAT_HTML),
  1026. 14 => new question_answer(14, '*', 0, 'Doh!', FORMAT_HTML),
  1027. );
  1028. $qdata->hints = array(
  1029. new question_hint(0, 'Hint 1', FORMAT_HTML),
  1030. new question_hint(0, 'Hint 2', FORMAT_HTML),
  1031. );
  1032. $exporter = new qformat_xml();
  1033. $xml = $exporter->writequestion($qdata);
  1034. $expectedxml = '<!-- question: 123 -->
  1035. <question type="shortanswer">
  1036. <name>
  1037. <text>Short answer question</text>
  1038. </name>
  1039. <questiontext format="html">
  1040. <text>Fill in the gap in this sequence: Alpha, ________, Gamma.</text>
  1041. </questiontext>
  1042. <generalfeedback format="html">
  1043. <text>The answer is Beta.</text>
  1044. </generalfeedback>
  1045. <defaultgrade>1</defaultgrade>
  1046. <penalty>0.3333333</penalty>
  1047. <hidden>0</hidden>
  1048. <usecase>0</usecase>
  1049. <answer fraction="100" format="plain_text">
  1050. <text>Beta</text>
  1051. <feedback format="html">
  1052. <text>Well done!</text>
  1053. </feedback>
  1054. </answer>
  1055. <answer fraction="0" format="plain_text">
  1056. <text>*</text>
  1057. <feedback format="html">
  1058. <text>Doh!</text>
  1059. </feedback>
  1060. </answer>
  1061. <hint format="html">
  1062. <text>Hint 1</text>
  1063. </hint>
  1064. <hint format="html">
  1065. <text>Hint 2</text>
  1066. </hint>
  1067. </question>
  1068. ';
  1069. $this->assert_same_xml($expectedxml, $xml);
  1070. }
  1071. public function test_import_truefalse_19() {
  1072. $xml = ' <question type="truefalse">
  1073. <name>
  1074. <text>True false question</text>
  1075. </name>
  1076. <questiontext format="html">
  1077. <text>The answer is true.</text>
  1078. </questiontext>
  1079. <generalfeedback>
  1080. <text>General feedback: You should have chosen true.</text>
  1081. </generalfeedback>
  1082. <defaultgrade>1</defaultgrade>
  1083. <penalty>1</penalty>
  1084. <hidden>0</hidden>
  1085. <answer fraction="100">
  1086. <text>true</text>
  1087. <feedback>
  1088. <text>Well done!</text>
  1089. </feedback>
  1090. </answer>
  1091. <answer fraction="0">
  1092. <text>false</text>
  1093. <feedback>
  1094. <text>Doh!</text>
  1095. </feedback>
  1096. </answer>
  1097. </question>';
  1098. $xmldata = xmlize($xml);
  1099. $importer = new qformat_xml();
  1100. $q = $importer->import_truefalse($xmldata['question']);
  1101. $expectedq = new stdClass();
  1102. $expectedq->qtype = 'truefalse';
  1103. $expectedq->name = 'True false question';
  1104. $expectedq->questiontext = 'The answer is true.';
  1105. $expectedq->questiontextformat = FORMAT_HTML;
  1106. $expectedq->generalfeedback = 'General feedback: You should have chosen true.';
  1107. $expectedq->defaultmark = 1;
  1108. $expectedq->length = 1;
  1109. $expectedq->penalty = 1;
  1110. $expectedq->feedbacktrue = array('text' => 'Well done!',
  1111. 'format' => FORMAT_HTML);
  1112. $expectedq->feedbackfalse = array('text' => 'Doh!',
  1113. 'format' => FORMAT_HTML);
  1114. $expectedq->correctanswer = true;
  1115. $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
  1116. }
  1117. public function test_export_truefalse() {
  1118. $qdata = new stdClass();
  1119. $qdata->id = 12;
  1120. $qdata->contextid = 0;
  1121. $qdata->qtype = 'truefalse';
  1122. $qdata->name = 'True false question';
  1123. $qdata->questiontext = 'The answer is true.';
  1124. $qdata->questiontextformat = FORMAT_HTML;
  1125. $qdata->generalfeedback = 'General feedback: You should have chosen true.';
  1126. $qdata->generalfeedbackformat = FORMAT_HTML;
  1127. $qdata->defaultmark = 1;
  1128. $qdata->length = 1;
  1129. $qdata->penalty = 1;
  1130. $qdata->hidden = 0;
  1131. $qdata->options = new stdClass();
  1132. $qdata->options->answers = array(
  1133. 1 => new question_answer(1, 'True', 1, 'Well done!', FORMAT_HTML),
  1134. 2 => new question_answer(2, 'False', 0, 'Doh!', FORMAT_HTML),
  1135. );
  1136. $qdata->options->trueanswer = 1;
  1137. $qdata->options->falseanswer = 2;
  1138. $exporter = new qformat_xml();
  1139. $xml = $exporter->writequestion($qdata);
  1140. $expectedxml = '<!-- question: 12 -->
  1141. <question type="truefalse">
  1142. <name>
  1143. <text>True false question</text>
  1144. </name>
  1145. <questiontext format="html">
  1146. <text>The answer is true.</text>
  1147. </questiontext>
  1148. <generalfeedback format="html">
  1149. <text>General feedback: You should have chosen true.</text>
  1150. </generalfeedback>
  1151. <defaultgrade>1</defaultgrade>
  1152. <penalty>1</penalty>
  1153. <hidden>0</hidden>
  1154. <answer fraction="100" format="plain_text">
  1155. <text>true</text>
  1156. <feedback format="html">
  1157. <text>Well done!</text>
  1158. </feedback>
  1159. </answer>
  1160. <answer fraction="0" format="plain_text">
  1161. <text>false</text>
  1162. <feedback format="html">
  1163. <text>Doh!</text>
  1164. </feedback>
  1165. </answer>
  1166. </question>
  1167. ';
  1168. $this->assert_same_xml($expectedxml, $xml);
  1169. }
  1170. public function test_import_multianswer() {
  1171. $xml = ' <question type="cloze">
  1172. <name>
  1173. <text>Simple multianswer</text>
  1174. </name>
  1175. <questiontext format="html">
  1176. <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>
  1177. </questiontext>
  1178. <generalfeedback format="html">
  1179. <text><![CDATA[General feedback: It\'s from "The Owl and the Pussy-cat" by Lear: "The owl and the pussycat went to sea".]]></text>
  1180. </generalfeedback>
  1181. <penalty>0.5</penalty>
  1182. <hidden>0</hidden>
  1183. <hint format="html">
  1184. <text>Hint 1</text>
  1185. </hint>
  1186. <hint format="html">
  1187. <text>Hint 2</text>
  1188. </hint>
  1189. </question>
  1190. ';
  1191. $xmldata = xmlize($xml);
  1192. $importer = new qformat_xml();
  1193. $q = $importer->import_multianswer($xmldata['question']);
  1194. // Annoyingly, import works in a weird way (it duplicates code, rather
  1195. // than just calling save_question) so we cannot use
  1196. // test_question_maker::get_question_form_data('multianswer', 'twosubq').
  1197. $expectedqa = new stdClass();
  1198. $expectedqa->name = 'Simple multianswer';
  1199. $expectedqa->qtype = 'multianswer';
  1200. $expectedqa->questiontext = 'Complete this opening line of verse: "The {#1} and the {#2} went to sea".';
  1201. $expectedqa->generalfeedback = 'General feedback: It\'s from "The Owl and the Pussy-cat" by Lear: "The owl and the pussycat went to sea".';
  1202. $expectedqa->defaultmark = 2;
  1203. $expectedqa->penalty = 0.5;
  1204. $expectedqa->hint = array(
  1205. array('text' => 'Hint 1', 'format' => FORMAT_HTML),
  1206. array('text' => 'Hint 2', 'format' => FORMAT_HTML),
  1207. );
  1208. $sa = new stdClass();
  1209. $sa->questiontext = array('text' => '{1:SHORTANSWER:Dog#Wrong, silly!~=Owl#Well done!~*#Wrong answer}',
  1210. 'format' => FORMAT_HTML, 'itemid' => null);
  1211. $sa->generalfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);
  1212. $sa->defaultmark = 1.0;
  1213. $sa->qtype = 'shortanswer';
  1214. $sa->usecase = 0;
  1215. $sa->answer = array('Dog', 'Owl', '*');
  1216. $sa->fraction = array(0, 1, 0);
  1217. $sa->feedback = array(
  1218. array('text' => 'Wrong, silly!', 'format' => FORMAT_HTML, 'itemid' => null),
  1219. array('text' => 'Well done!', 'format' => FORMAT_HTML, 'itemid' => null),
  1220. array('text' => 'Wrong answer', 'format' => FORMAT_HTML, 'itemid' => null),
  1221. );
  1222. $mc = new stdClass();
  1223. $mc->generalfeedback = '';
  1224. $mc->questiontext = array('text' => '{1:MULTICHOICE:Bow-wow#You seem to have a dog obsessions!~' .
  1225. 'Wiggly worm#Now you are just being ridiculous!~=Pussy-cat#Well done!}',
  1226. 'format' => FORMAT_HTML, 'itemid' => null);
  1227. $mc->generalfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);
  1228. $mc->defaultmark = 1.0;
  1229. $mc->qtype = 'multichoice';
  1230. $mc->layout = 0;
  1231. $mc->single = 1;
  1232. $mc->shuffleanswers = 1;
  1233. $mc->correctfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);
  1234. $mc->partiallycorrectfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);
  1235. $mc->incorrectfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);
  1236. $mc->answernumbering = 0;
  1237. $mc->answer = array(
  1238. array('text' => 'Bow-wow', 'format' => FORMAT_HTML, 'itemid' => null),
  1239. array('text' => 'Wiggly worm', 'format' => FORMAT_HTML, 'itemid' => null),
  1240. array('text' => 'Pussy-cat', 'format' => FORMAT_HTML, 'itemid' => null),
  1241. );
  1242. $mc->fraction = array(0, 0, 1);
  1243. $mc->feedback = array(
  1244. array('text' => 'You seem to have a dog obsessions!', 'format' => FORMAT_HTML, 'itemid' => null),
  1245. array('text' => 'Now you are just being ridiculous!', 'format' => FORMAT_HTML, 'itemid' => null),
  1246. array('text' => 'Well done!', 'format' => FORMAT_HTML, 'itemid' => null),
  1247. );
  1248. $expectedqa->options = new stdClass();
  1249. $expectedqa->options->questions = array(
  1250. 1 => $sa,
  1251. 2 => $mc,
  1252. );
  1253. $this->assertEquals($expectedqa->hint, $q->hint);
  1254. $this->assertEquals($expectedqa->options->questions[1], $q->options->questions[1]);
  1255. $this->assertEquals($expectedqa->options->questions[2], $q->options->questions[2]);
  1256. $this->assert(new question_check_specified_fields_expectation($expectedqa), $q);
  1257. }
  1258. public function test_export_multianswer() {
  1259. $qdata = test_question_maker::get_question_data('multianswer', 'twosubq');
  1260. $exporter = new qformat_xml();
  1261. $xml = $exporter->writequestion($qdata);
  1262. $expectedxml = '<!-- question: 0 -->
  1263. <question type="cloze">
  1264. <name>
  1265. <text>Simple multianswer</text>
  1266. </name>
  1267. <questiontext format="html">
  1268. <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>
  1269. </questiontext>
  1270. <generalfeedback format="html">
  1271. <text><![CDATA[General feedback: It\'s from "The Owl and the Pussy-cat" by Lear: "The owl and the pussycat went to sea]]></text>
  1272. </generalfeedback>
  1273. <penalty>0.3333333</penalty>
  1274. <hidden>0</hidden>
  1275. <hint format="html">
  1276. <text>Hint 1</text>
  1277. </hint>
  1278. <hint format="html">
  1279. <text>Hint 2</text>
  1280. </hint>
  1281. </question>
  1282. ';
  1283. $this->assert_same_xml($expectedxml, $xml);
  1284. }
  1285. public function test_import_files_as_draft() {
  1286. $this->resetAfterTest();
  1287. $this->setAdminUser();
  1288. $xml = <<<END
  1289. <questiontext format="html">
  1290. <text><![CDATA[<p><a href="@@PLUGINFILE@@/moodle.txt">This text file</a> contains the word 'Moodle'.</p>]]></text>
  1291. <file name="moodle.txt" encoding="base64">TW9vZGxl</file>
  1292. </questiontext>
  1293. END;
  1294. $textxml = xmlize($xml);
  1295. $qo = new stdClass();
  1296. $importer = new qformat_xml();
  1297. $draftitemid = $importer->import_files_as_draft($textxml['questiontext']['#']['file']);
  1298. $files = file_get_drafarea_files($draftitemid);
  1299. $this->assertEquals(1, count($files->list));
  1300. $file = $files->list[0];
  1301. $this->assertEquals('moodle.txt', $file->filename);
  1302. $this->assertEquals('