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