MDL-34306 gift question format: allow import of general feedback
[moodle.git] / question / format / gift / tests / giftformat_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 GIFT format.
19  *
20  * @package    qformat
21  * @subpackage gift
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.php');
32 require_once($CFG->dirroot . '/question/format/gift/format.php');
33 require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
36 /**
37  * Unit tests for the GIFT import/export format.
38  *
39  * @copyright 2010 The Open University
40  * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41  */
42 class qformat_gift_test extends question_testcase {
43     public function assert_same_gift($expectedtext, $text) {
44         $this->assertEquals(str_replace("\r\n", "\n", $expectedtext),
45                 str_replace("\r\n", "\n", $text));
46     }
48     public function test_import_essay() {
49         $gift = '
50 // essay
51 ::Q8:: How are you? {}';
52         $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
54         $importer = new qformat_gift();
55         $q = $importer->readquestion($lines);
57         $expectedq = (object) array(
58             'name' => 'Q8',
59             'questiontext' => 'How are you?',
60             'questiontextformat' => FORMAT_MOODLE,
61             'generalfeedback' => '',
62             'generalfeedbackformat' => FORMAT_MOODLE,
63             'qtype' => 'essay',
64             'defaultmark' => 1,
65             'penalty' => 0.3333333,
66             'length' => 1,
67             'responseformat' => 'editor',
68             'responsefieldlines' => 15,
69             'attachments' => 0,
70             'graderinfo' => array(
71                 'text' => '',
72                 'format' => FORMAT_HTML,
73                 'files' => array()),
74         );
76         $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
77     }
79     public function test_export_essay() {
80         $qdata = (object) array(
81             'id' => 666 ,
82             'name' => 'Q8',
83             'questiontext' => 'How are you?',
84             'questiontextformat' => FORMAT_MOODLE,
85             'generalfeedback' => '',
86             'generalfeedbackformat' => FORMAT_MOODLE,
87             'defaultmark' => 1,
88             'penalty' => 0.3333333,
89             'length' => 1,
90             'qtype' => 'essay',
91             'options' => (object) array(
92                 'responseformat' => 'editor',
93                 'responsefieldlines' => 15,
94                 'attachments' => 0,
95                 'graderinfo' => '',
96                 'graderinfoformat' => FORMAT_HTML,
97             ),
98         );
100         $exporter = new qformat_gift();
101         $gift = $exporter->writequestion($qdata);
103         $expectedgift = "// question: 666  name: Q8
104 ::Q8::How are you?{}
106 ";
108         $this->assert_same_gift($expectedgift, $gift);
109     }
111     public function test_import_match() {
112         $gift = '
113 // question: 2  name: Moodle activities
114 ::Moodle activities::[html]Match the <b>activity</b> to the description.{
115     =[html]An activity supporting asynchronous discussions. -> Forum
116     =[moodle]A teacher asks a question and specifies a choice of multiple responses. -> Choice
117     =[plain]A bank of record entries which participants can add to. -> Database
118     =[markdown]A collection of web pages that anyone can add to or edit. -> Wiki
119     = -> Chat
120 }';
121         $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
123         $importer = new qformat_gift();
124         $q = $importer->readquestion($lines);
126         $expectedq = (object) array(
127             'name' => 'Moodle activities',
128             'questiontext' => 'Match the <b>activity</b> to the description.',
129             'questiontextformat' => FORMAT_HTML,
130             'generalfeedback' => '',
131             'generalfeedbackformat' => FORMAT_HTML,
132             'qtype' => 'match',
133             'defaultmark' => 1,
134             'penalty' => 0.3333333,
135             'length' => 1,
136             'shuffleanswers' => '1',
137             'correctfeedback' => array(
138                 'text' => '',
139                 'format' => FORMAT_HTML,
140                 'files' => array(),
141             ),
142             'partiallycorrectfeedback' => array(
143                 'text' => '',
144                 'format' => FORMAT_HTML,
145                 'files' => array(),
146             ),
147             'incorrectfeedback' => array(
148                 'text' => '',
149                 'format' => FORMAT_HTML,
150                 'files' => array(),
151             ),
152             'subquestions' => array(
153                 0 => array(
154                     'text' => 'An activity supporting asynchronous discussions.',
155                     'format' => FORMAT_HTML,
156                     'files' => array(),
157                 ),
158                 1 => array(
159                     'text' => 'A teacher asks a question and specifies a choice of multiple responses.',
160                     'format' => FORMAT_MOODLE,
161                     'files' => array(),
162                 ),
163                 2 => array(
164                     'text' => 'A bank of record entries which participants can add to.',
165                     'format' => FORMAT_PLAIN,
166                     'files' => array(),
167                 ),
168                 3 => array(
169                     'text' => 'A collection of web pages that anyone can add to or edit.',
170                     'format' => FORMAT_MARKDOWN,
171                     'files' => array(),
172                 ),
173                 4 => array(
174                     'text' => '',
175                     'format' => FORMAT_HTML,
176                     'files' => array(),
177                 ),
178             ),
179             'subanswers' => array(
180                 0 => 'Forum',
181                 1 => 'Choice',
182                 2 => 'Database',
183                 3 => 'Wiki',
184                 4 => 'Chat',
185             ),
186         );
188         // Repeated test for better failure messages.
189         $this->assertEquals($expectedq->subquestions, $q->subquestions);
190         $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
191     }
193     public function test_export_match() {
194         $qdata = (object) array(
195             'id' => 666 ,
196             'name' => 'Moodle activities',
197             'questiontext' => 'Match the <b>activity</b> to the description.',
198             'questiontextformat' => FORMAT_HTML,
199             'generalfeedback' => '',
200             'generalfeedbackformat' => FORMAT_HTML,
201             'defaultmark' => 1,
202             'penalty' => 0.3333333,
203             'length' => 1,
204             'qtype' => 'match',
205             'options' => (object) array(
206                 'id' => 123,
207                 'question' => 666,
208                 'shuffleanswers' => 1,
209                 'subquestions' => array(
210                     42 => (object) array(
211                         'id' => 1234,
212                         'code' => 12341234,
213                         'question' => 666,
214                         'questiontext' => '<div class="frog">An activity supporting asynchronous discussions.</div>',
215                         'questiontextformat' => FORMAT_HTML,
216                         'answertext' => 'Forum',
217                     ),
218                     43 => (object) array(
219                         'id' => 1234,
220                         'code' => 12341234,
221                         'question' => 666,
222                         'questiontext' => 'A teacher asks a question and specifies a choice of multiple responses.',
223                         'questiontextformat' => FORMAT_MOODLE,
224                         'answertext' => 'Choice',
225                     ),
226                     44 => (object) array(
227                         'id' => 1234,
228                         'code' => 12341234,
229                         'question' => 666,
230                         'questiontext' => 'A bank of record entries which participants can add to.',
231                         'questiontextformat' => FORMAT_PLAIN,
232                         'answertext' => 'Database',
233                     ),
234                     45 => (object) array(
235                         'id' => 1234,
236                         'code' => 12341234,
237                         'question' => 666,
238                         'questiontext' => 'A collection of web pages that anyone can add to or edit.',
239                         'questiontextformat' => FORMAT_MARKDOWN,
240                         'answertext' => 'Wiki',
241                     ),
242                     46 => (object) array(
243                         'id' => 1234,
244                         'code' => 12341234,
245                         'question' => 666,
246                         'questiontext' => '',
247                         'questiontextformat' => FORMAT_MARKDOWN,
248                         'answertext' => 'Chat',
249                     ),
250                 ),
251             ),
252         );
254         $exporter = new qformat_gift();
255         $gift = $exporter->writequestion($qdata);
257         $expectedgift = "// question: 666  name: Moodle activities
258 ::Moodle activities::[html]Match the <b>activity</b> to the description.{
259 \t=<div class\\=\"frog\">An activity supporting asynchronous discussions.</div> -> Forum
260 \t=[moodle]A teacher asks a question and specifies a choice of multiple responses. -> Choice
261 \t=[plain]A bank of record entries which participants can add to. -> Database
262 \t=[markdown]A collection of web pages that anyone can add to or edit. -> Wiki
263 \t= -> Chat
266 ";
268         $this->assert_same_gift($expectedgift, $gift);
269     }
271     public function test_import_multichoice() {
272         $gift = "
273 // multiple choice with specified feedback for right and wrong answers
274 ::Q2:: What's between orange and green in the spectrum?
276     =yellow # right; good!
277     ~red # [html]wrong, it's yellow
278     ~[plain]blue # wrong, it's yellow
279 }";
280         $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
282         $importer = new qformat_gift();
283         $q = $importer->readquestion($lines);
285         $expectedq = (object) array(
286             'name' => 'Q2',
287             'questiontext' => "What's between orange and green in the spectrum?",
288             'questiontextformat' => FORMAT_MOODLE,
289             'generalfeedback' => '',
290             'generalfeedbackformat' => FORMAT_MOODLE,
291             'qtype' => 'multichoice',
292             'defaultmark' => 1,
293             'penalty' => 0.3333333,
294             'length' => 1,
295             'single' => 1,
296             'shuffleanswers' => '1',
297             'answernumbering' => 'abc',
298             'correctfeedback' => array(
299                 'text' => '',
300                 'format' => FORMAT_MOODLE,
301                 'files' => array(),
302             ),
303             'partiallycorrectfeedback' => array(
304                 'text' => '',
305                 'format' => FORMAT_MOODLE,
306                 'files' => array(),
307             ),
308             'incorrectfeedback' => array(
309                 'text' => '',
310                 'format' => FORMAT_MOODLE,
311                 'files' => array(),
312             ),
313             'answer' => array(
314                 0 => array(
315                     'text' => 'yellow',
316                     'format' => FORMAT_MOODLE,
317                     'files' => array(),
318                 ),
319                 1 => array(
320                     'text' => 'red',
321                     'format' => FORMAT_MOODLE,
322                     'files' => array(),
323                 ),
324                 2 => array(
325                     'text' => 'blue',
326                     'format' => FORMAT_PLAIN,
327                     'files' => array(),
328                 ),
329             ),
330             'fraction' => array(1, 0, 0),
331             'feedback' => array(
332                 0 => array(
333                     'text' => 'right; good!',
334                     'format' => FORMAT_MOODLE,
335                     'files' => array(),
336                 ),
337                 1 => array(
338                     'text' => "wrong, it's yellow",
339                     'format' => FORMAT_HTML,
340                     'files' => array(),
341                 ),
342                 2 => array(
343                     'text' => "wrong, it's yellow",
344                     'format' => FORMAT_MOODLE,
345                     'files' => array(),
346                 ),
347             ),
348         );
350         // Repeated test for better failure messages.
351         $this->assertEquals($expectedq->answer, $q->answer);
352         $this->assertEquals($expectedq->feedback, $q->feedback);
353         $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
354     }
356     public function test_import_multichoice_multi() {
357         $gift = "
358 // multiple choice, multiple response with specified feedback for right and wrong answers
359 ::colours:: What's between orange and green in the spectrum?
361     ~%50%yellow # right; good!
362     ~%-100%red # [html]wrong
363     ~%50%off-beige # right; good!
364     ~%-100%[plain]blue # wrong
365 }";
366         $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
368         $importer = new qformat_gift();
369         $q = $importer->readquestion($lines);
371         $expectedq = (object) array(
372             'name' => 'colours',
373             'questiontext' => "What's between orange and green in the spectrum?",
374             'questiontextformat' => FORMAT_MOODLE,
375             'generalfeedback' => '',
376             'generalfeedbackformat' => FORMAT_MOODLE,
377             'qtype' => 'multichoice',
378             'defaultmark' => 1,
379             'penalty' => 0.3333333,
380             'length' => 1,
381             'single' => 0,
382             'shuffleanswers' => '1',
383             'answernumbering' => 'abc',
384             'correctfeedback' => array(
385                 'text' => '',
386                 'format' => FORMAT_MOODLE,
387                 'files' => array(),
388             ),
389             'partiallycorrectfeedback' => array(
390                 'text' => '',
391                 'format' => FORMAT_MOODLE,
392                 'files' => array(),
393             ),
394             'incorrectfeedback' => array(
395                 'text' => '',
396                 'format' => FORMAT_MOODLE,
397                 'files' => array(),
398             ),
399             'answer' => array(
400                 0 => array(
401                     'text' => 'yellow',
402                     'format' => FORMAT_MOODLE,
403                     'files' => array(),
404                 ),
405                 1 => array(
406                     'text' => 'red',
407                     'format' => FORMAT_MOODLE,
408                     'files' => array(),
409                 ),
410                 2 => array(
411                     'text' => 'off-beige',
412                     'format' => FORMAT_MOODLE,
413                     'files' => array(),
414                 ),
415                 3 => array(
416                     'text' => 'blue',
417                     'format' => FORMAT_PLAIN,
418                     'files' => array(),
419                 ),
420             ),
421             'fraction' => array(0.5, -1, 0.5, -1),
422             'feedback' => array(
423                 0 => array(
424                     'text' => 'right; good!',
425                     'format' => FORMAT_MOODLE,
426                     'files' => array(),
427                 ),
428                 1 => array(
429                     'text' => "wrong",
430                     'format' => FORMAT_HTML,
431                     'files' => array(),
432                 ),
433                 2 => array(
434                     'text' => "right; good!",
435                     'format' => FORMAT_MOODLE,
436                     'files' => array(),
437                 ),
438                 3 => array(
439                     'text' => "wrong",
440                     'format' => FORMAT_MOODLE,
441                     'files' => array(),
442                 ),
443             ),
444         );
446         // Repeated test for better failure messages.
447         $this->assertEquals($expectedq->answer, $q->answer);
448         $this->assertEquals($expectedq->feedback, $q->feedback);
449         $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
450     }
452     public function test_export_multichoice() {
453         $qdata = (object) array(
454             'id' => 666 ,
455             'name' => 'Q8',
456             'questiontext' => "What's between orange and green in the spectrum?",
457             'questiontextformat' => FORMAT_MOODLE,
458             'generalfeedback' => '',
459             'generalfeedbackformat' => FORMAT_MOODLE,
460             'defaultmark' => 1,
461             'penalty' => 0.3333333,
462             'length' => 1,
463             'qtype' => 'multichoice',
464             'options' => (object) array(
465                 'single' => 1,
466                 'shuffleanswers' => '1',
467                 'answernumbering' => 'abc',
468                 'correctfeedback' => '',
469                 'correctfeedbackformat' => FORMAT_MOODLE,
470                 'partiallycorrectfeedback' => '',
471                 'partiallycorrectfeedbackformat' => FORMAT_MOODLE,
472                 'incorrectfeedback' => '',
473                 'incorrectfeedbackformat' => FORMAT_MOODLE,
474                 'answers' => array(
475                     123 => (object) array(
476                         'id' => 123,
477                         'answer' => 'yellow',
478                         'answerformat' => FORMAT_MOODLE,
479                         'fraction' => 1,
480                         'feedback' => 'right; good!',
481                         'feedbackformat' => FORMAT_MOODLE,
482                     ),
483                     124 => (object) array(
484                         'id' => 124,
485                         'answer' => 'red',
486                         'answerformat' => FORMAT_MOODLE,
487                         'fraction' => 0,
488                         'feedback' => "wrong, it's yellow",
489                         'feedbackformat' => FORMAT_HTML,
490                     ),
491                     125 => (object) array(
492                         'id' => 125,
493                         'answer' => 'blue',
494                         'answerformat' => FORMAT_PLAIN,
495                         'fraction' => 0,
496                         'feedback' => "wrong, it's yellow",
497                         'feedbackformat' => FORMAT_MOODLE,
498                     ),
499                 ),
500             ),
501         );
503         $exporter = new qformat_gift();
504         $gift = $exporter->writequestion($qdata);
506         $expectedgift = "// question: 666  name: Q8
507 ::Q8::What's between orange and green in the spectrum?{
508 \t=yellow#right; good!
509 \t~red#[html]wrong, it's yellow
510 \t~[plain]blue#wrong, it's yellow
513 ";
515         $this->assert_same_gift($expectedgift, $gift);
516     }
518     public function test_import_numerical() {
519         $gift = "
520 // math range question
521 ::Q5:: What is a number from 1 to 5? {#3:2~#Completely wrong}";
522         $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
524         $importer = new qformat_gift();
525         $q = $importer->readquestion($lines);
527         $expectedq = (object) array(
528             'name' => 'Q5',
529             'questiontext' => "What is a number from 1 to 5?",
530             'questiontextformat' => FORMAT_MOODLE,
531             'generalfeedback' => '',
532             'generalfeedbackformat' => FORMAT_MOODLE,
533             'qtype' => 'numerical',
534             'defaultmark' => 1,
535             'penalty' => 0.3333333,
536             'length' => 1,
537             'answer' => array(
538                 '3',
539                 '*',
540             ),
541             'fraction' => array(1, 0),
542             'feedback' => array(
543                 0 => array(
544                     'text' => '',
545                     'format' => FORMAT_MOODLE,
546                     'files' => array(),
547                 ),
548                 1 => array(
549                     'text' => "Completely wrong",
550                     'format' => FORMAT_MOODLE,
551                     'files' => array(),
552                 ),
553             ),
554             'tolerance' => array(2, 0),
555         );
557         // Repeated test for better failure messages.
558         $this->assertEquals($expectedq->answer, $q->answer);
559         $this->assertEquals($expectedq->fraction, $q->fraction);
560         $this->assertEquals($expectedq->feedback, $q->feedback);
561         $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
562     }
564     public function test_export_numerical() {
565         $qdata = (object) array(
566             'id' => 666 ,
567             'name' => 'Q5',
568             'questiontext' => "What is a number from 1 to 5?",
569             'questiontextformat' => FORMAT_MOODLE,
570             'generalfeedback' => '',
571             'generalfeedbackformat' => FORMAT_MOODLE,
572             'defaultmark' => 1,
573             'penalty' => 1,
574             'length' => 1,
575             'qtype' => 'numerical',
576             'options' => (object) array(
577                 'id' => 123,
578                 'question' => 666,
579                 'showunits' => 0,
580                 'unitsleft' => 0,
581                 'showunits' => 2,
582                 'unitgradingtype' => 0,
583                 'unitpenalty' => 0,
584                 'answers' => array(
585                     1 => (object) array(
586                         'id' => 123,
587                         'answer' => '3',
588                         'answerformat' => 0,
589                         'fraction' => 1,
590                         'tolerance' => 2,
591                         'feedback' => '',
592                         'feedbackformat' => FORMAT_MOODLE,
593                     ),
594                     2 => (object) array(
595                         'id' => 124,
596                         'answer' => '*',
597                         'answerformat' => 0,
598                         'fraction' => 0,
599                         'tolerance' => 0,
600                         'feedback' => "Completely wrong",
601                         'feedbackformat' => FORMAT_MOODLE,
602                     ),
603                 ),
604             ),
605         );
607         $exporter = new qformat_gift();
608         $gift = $exporter->writequestion($qdata);
610         $expectedgift = "// question: 666  name: Q5
611 ::Q5::What is a number from 1 to 5?{#
612 \t=%100%3:2#
613 \t~#Completely wrong
616 ";
618         $this->assert_same_gift($expectedgift, $gift);
619     }
621     public function test_import_shortanswer() {
622         $gift = "
623 // question: 666  name: Shortanswer
624 ::Shortanswer::Which is the best animal?{
625     =Frog#Good!
626     =%50%Cat#What is it with Moodlers and cats?
627     =%0%*#Completely wrong
628 }";
629         $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
631         $importer = new qformat_gift();
632         $q = $importer->readquestion($lines);
634         $expectedq = (object) array(
635             'name' => 'Shortanswer',
636             'questiontext' => "Which is the best animal?",
637             'questiontextformat' => FORMAT_MOODLE,
638             'generalfeedback' => '',
639             'generalfeedbackformat' => FORMAT_MOODLE,
640             'qtype' => 'shortanswer',
641             'defaultmark' => 1,
642             'penalty' => 0.3333333,
643             'length' => 1,
644             'answer' => array(
645                 'Frog',
646                 'Cat',
647                 '*',
648             ),
649             'fraction' => array(1, 0.5, 0),
650             'feedback' => array(
651                 0 => array(
652                     'text' => 'Good!',
653                     'format' => FORMAT_MOODLE,
654                     'files' => array(),
655                 ),
656                 1 => array(
657                     'text' => "What is it with Moodlers and cats?",
658                     'format' => FORMAT_MOODLE,
659                     'files' => array(),
660                 ),
661                 2 => array(
662                     'text' => "Completely wrong",
663                     'format' => FORMAT_MOODLE,
664                     'files' => array(),
665                 ),
666             ),
667         );
669         // Repeated test for better failure messages.
670         $this->assertEquals($expectedq->answer, $q->answer);
671         $this->assertEquals($expectedq->fraction, $q->fraction);
672         $this->assertEquals($expectedq->feedback, $q->feedback);
673         $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
674     }
676     public function test_import_shortanswer_with_general_feedback() {
677         $gift = "
678 // question: 666  name: Shortanswer
679 ::Shortanswer::Which is the best animal?{
680     =Frog#Good!
681     =%50%Cat#What is it with Moodlers and cats?
682     =%0%*#Completely wrong
683     ####[html]Here is some general feedback!
684 }";
685         $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
687         $importer = new qformat_gift();
688         $q = $importer->readquestion($lines);
690         $expectedq = (object) array(
691             'name' => 'Shortanswer',
692             'questiontext' => "Which is the best animal?",
693             'questiontextformat' => FORMAT_MOODLE,
694             'generalfeedback' => 'Here is some general feedback!',
695             'generalfeedbackformat' => FORMAT_HTML,
696             'qtype' => 'shortanswer',
697             'defaultmark' => 1,
698             'penalty' => 0.3333333,
699             'length' => 1,
700             'answer' => array(
701                 'Frog',
702                 'Cat',
703                 '*',
704             ),
705             'fraction' => array(1, 0.5, 0),
706             'feedback' => array(
707                 0 => array(
708                     'text' => 'Good!',
709                     'format' => FORMAT_MOODLE,
710                     'files' => array(),
711                 ),
712                 1 => array(
713                     'text' => "What is it with Moodlers and cats?",
714                     'format' => FORMAT_MOODLE,
715                     'files' => array(),
716                 ),
717                 2 => array(
718                     'text' => "Completely wrong",
719                     'format' => FORMAT_MOODLE,
720                     'files' => array(),
721                 ),
722             ),
723         );
725         // Repeated test for better failure messages.
726         $this->assertEquals($expectedq->answer, $q->answer);
727         $this->assertEquals($expectedq->fraction, $q->fraction);
728         $this->assertEquals($expectedq->feedback, $q->feedback);
729         $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
730     }
732     public function test_export_shortanswer() {
733         $qdata = (object) array(
734             'id' => 666 ,
735             'name' => 'Shortanswer',
736             'questiontext' => "Which is the best animal?",
737             'questiontextformat' => FORMAT_MOODLE,
738             'generalfeedback' => '',
739             'generalfeedbackformat' => FORMAT_MOODLE,
740             'defaultmark' => 1,
741             'penalty' => 1,
742             'length' => 1,
743             'qtype' => 'shortanswer',
744             'options' => (object) array(
745                 'id' => 123,
746                 'question' => 666,
747                 'usecase' => 1,
748                 'answers' => array(
749                     1 => (object) array(
750                         'id' => 1,
751                         'answer' => 'Frog',
752                         'answerformat' => 0,
753                         'fraction' => 1,
754                         'feedback' => 'Good!',
755                         'feedbackformat' => FORMAT_MOODLE,
756                     ),
757                     2 => (object) array(
758                         'id' => 2,
759                         'answer' => 'Cat',
760                         'answerformat' => 0,
761                         'fraction' => 0.5,
762                         'feedback' => "What is it with Moodlers and cats?",
763                         'feedbackformat' => FORMAT_MOODLE,
764                     ),
765                     3 => (object) array(
766                         'id' => 3,
767                         'answer' => '*',
768                         'answerformat' => 0,
769                         'fraction' => 0,
770                         'feedback' => "Completely wrong",
771                         'feedbackformat' => FORMAT_MOODLE,
772                     ),
773                 ),
774             ),
775         );
777         $exporter = new qformat_gift();
778         $gift = $exporter->writequestion($qdata);
780         $expectedgift = "// question: 666  name: Shortanswer
781 ::Shortanswer::Which is the best animal?{
782 \t=%100%Frog#Good!
783 \t=%50%Cat#What is it with Moodlers and cats?
784 \t=%0%*#Completely wrong
787 ";
789         $this->assert_same_gift($expectedgift, $gift);
790     }
792     public function test_export_shortanswer_with_general_feedback() {
793         $qdata = (object) array(
794             'id' => 666 ,
795             'name' => 'Shortanswer',
796             'questiontext' => "Which is the best animal?",
797             'questiontextformat' => FORMAT_MOODLE,
798             'generalfeedback' => 'Here is some general feedback!',
799             'generalfeedbackformat' => FORMAT_HTML,
800             'defaultmark' => 1,
801             'penalty' => 1,
802             'length' => 1,
803             'qtype' => 'shortanswer',
804             'options' => (object) array(
805                 'id' => 123,
806                 'question' => 666,
807                 'usecase' => 1,
808                 'answers' => array(
809                     1 => (object) array(
810                         'id' => 1,
811                         'answer' => 'Frog',
812                         'answerformat' => 0,
813                         'fraction' => 1,
814                         'feedback' => 'Good!',
815                         'feedbackformat' => FORMAT_MOODLE,
816                     ),
817                     2 => (object) array(
818                         'id' => 2,
819                         'answer' => 'Cat',
820                         'answerformat' => 0,
821                         'fraction' => 0.5,
822                         'feedback' => "What is it with Moodlers and cats?",
823                         'feedbackformat' => FORMAT_MOODLE,
824                     ),
825                     3 => (object) array(
826                         'id' => 3,
827                         'answer' => '*',
828                         'answerformat' => 0,
829                         'fraction' => 0,
830                         'feedback' => "Completely wrong",
831                         'feedbackformat' => FORMAT_MOODLE,
832                     ),
833                 ),
834             ),
835         );
837         $exporter = new qformat_gift();
838         $gift = $exporter->writequestion($qdata);
840         $expectedgift = "// question: 666  name: Shortanswer
841 ::Shortanswer::Which is the best animal?{
842 \t=%100%Frog#Good!
843 \t=%50%Cat#What is it with Moodlers and cats?
844 \t=%0%*#Completely wrong
845 \t####[html]Here is some general feedback!
848 ";
850         $this->assert_same_gift($expectedgift, $gift);
851     }
853     public function test_import_truefalse() {
854         $gift = "
855 // true/false
856 ::Q1:: 42 is the Absolute Answer to everything.{
857 FALSE#42 is the Ultimate Answer.#You gave the right answer.}";
858         $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
860         $importer = new qformat_gift();
861         $q = $importer->readquestion($lines);
863         $expectedq = (object) array(
864             'name' => 'Q1',
865             'questiontext' => "42 is the Absolute Answer to everything.",
866             'questiontextformat' => FORMAT_MOODLE,
867             'generalfeedback' => '',
868             'generalfeedbackformat' => FORMAT_MOODLE,
869             'qtype' => 'truefalse',
870             'defaultmark' => 1,
871             'penalty' => 1,
872             'length' => 1,
873             'correctanswer' => 0,
874             'feedbacktrue' => array(
875                 'text' => '42 is the Ultimate Answer.',
876                 'format' => FORMAT_MOODLE,
877                 'files' => array(),
878             ),
879             'feedbackfalse' => array(
880                 'text' => 'You gave the right answer.',
881                 'format' => FORMAT_MOODLE,
882                 'files' => array(),
883             ),
884         );
886         $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
887     }
889     public function test_import_truefalse_true_answer1() {
890         $gift = "// name 0-11
891 ::2-08 TSL::TSL is blablabla.{T}";
892         $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
894         $importer = new qformat_gift();
895         $q = $importer->readquestion($lines);
897         $expectedq = (object) array(
898             'name' => '2-08 TSL',
899             'questiontext' => "TSL is blablabla.",
900             'questiontextformat' => FORMAT_MOODLE,
901             'generalfeedback' => '',
902             'generalfeedbackformat' => FORMAT_MOODLE,
903             'qtype' => 'truefalse',
904             'defaultmark' => 1,
905             'penalty' => 1,
906             'length' => 1,
907             'correctanswer' => 1,
908             'feedbacktrue' => array(
909                 'text' => '',
910                 'format' => FORMAT_MOODLE,
911                 'files' => array(),
912             ),
913             'feedbackfalse' => array(
914                 'text' => '',
915                 'format' => FORMAT_MOODLE,
916                 'files' => array(),
917             ),
918         );
920         $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
921     }
923     public function test_import_truefalse_true_answer2() {
924         $gift = "// name 0-11
925 ::2-08 TSL::TSL is blablabla.{TRUE}";
926         $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
928         $importer = new qformat_gift();
929         $q = $importer->readquestion($lines);
931         $expectedq = (object) array(
932             'name' => '2-08 TSL',
933             'questiontext' => "TSL is blablabla.",
934             'questiontextformat' => FORMAT_MOODLE,
935             'generalfeedback' => '',
936             'generalfeedbackformat' => FORMAT_MOODLE,
937             'qtype' => 'truefalse',
938             'defaultmark' => 1,
939             'penalty' => 1,
940             'length' => 1,
941             'correctanswer' => 1,
942             'feedbacktrue' => array(
943                 'text' => '',
944                 'format' => FORMAT_MOODLE,
945                 'files' => array(),
946             ),
947             'feedbackfalse' => array(
948                 'text' => '',
949                 'format' => FORMAT_MOODLE,
950                 'files' => array(),
951             ),
952         );
954         $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
955     }
957     public function test_export_truefalse() {
958         $qdata = (object) array(
959             'id' => 666 ,
960             'name' => 'Q1',
961             'questiontext' => "42 is the Absolute Answer to everything.",
962             'questiontextformat' => FORMAT_MOODLE,
963             'generalfeedback' => '',
964             'generalfeedbackformat' => FORMAT_MOODLE,
965             'defaultmark' => 1,
966             'penalty' => 1,
967             'length' => 1,
968             'qtype' => 'truefalse',
969             'options' => (object) array(
970                 'id' => 123,
971                 'question' => 666,
972                 'trueanswer' => 1,
973                 'falseanswer' => 2,
974                 'answers' => array(
975                     1 => (object) array(
976                         'id' => 123,
977                         'answer' => 'True',
978                         'answerformat' => 0,
979                         'fraction' => 1,
980                         'feedback' => 'You gave the right answer.',
981                         'feedbackformat' => FORMAT_MOODLE,
982                     ),
983                     2 => (object) array(
984                         'id' => 124,
985                         'answer' => 'False',
986                         'answerformat' => 0,
987                         'fraction' => 0,
988                         'feedback' => "42 is the Ultimate Answer.",
989                         'feedbackformat' => FORMAT_HTML,
990                     ),
991                 ),
992             ),
993         );
995         $exporter = new qformat_gift();
996         $gift = $exporter->writequestion($qdata);
998         $expectedgift = "// question: 666  name: Q1
999 ::Q1::42 is the Absolute Answer to everything.{TRUE#[html]42 is the Ultimate Answer.#You gave the right answer.}
1001 ";
1003         $this->assert_same_gift($expectedgift, $gift);
1004     }
1006     public function test_export_backslash() {
1007         // There was a bug (MDL-34171) where \\ was getting exported as \\, not
1008         // \\\\, and on import, \\ in converted to \.
1009         // We need \\\\ in the test code, because of PHPs string escaping rules.
1010         $qdata = (object) array(
1011             'id' => 666 ,
1012             'name' => 'backslash',
1013             'questiontext' => 'A \\ B \\\\ C',
1014             'questiontextformat' => FORMAT_MOODLE,
1015             'generalfeedback' => '',
1016             'generalfeedbackformat' => FORMAT_MOODLE,
1017             'defaultmark' => 1,
1018             'penalty' => 0.3333333,
1019             'length' => 1,
1020             'qtype' => 'essay',
1021             'options' => (object) array(
1022                 'responseformat' => 'editor',
1023                 'responsefieldlines' => 15,
1024                 'attachments' => 0,
1025                 'graderinfo' => '',
1026                 'graderinfoformat' => FORMAT_HTML,
1027             ),
1028         );
1030         $exporter = new qformat_gift();
1031         $gift = $exporter->writequestion($qdata);
1033         $expectedgift = "// question: 666  name: backslash
1034 ::backslash::A \\\\ B \\\\\\\\ C{}
1036 ";
1038         $this->assert_same_gift($expectedgift, $gift);
1039     }
1041     public function test_import_backslash() {
1042         // There was a bug (MDL-34171) where \\ in the import was getting changed
1043         // to \. This test checks for that.
1044         // We need \\\\ in the test code, because of PHPs string escaping rules.
1045         $gift = '
1046 // essay
1047 ::double backslash:: A \\\\ B \\\\\\\\ C{}';
1048         $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
1050         $importer = new qformat_gift();
1051         $q = $importer->readquestion($lines);
1053         $expectedq = (object) array(
1054             'name' => 'double backslash',
1055             'questiontext' => 'A \\ B \\\\ C',
1056             'questiontextformat' => FORMAT_MOODLE,
1057             'generalfeedback' => '',
1058             'generalfeedbackformat' => FORMAT_MOODLE,
1059             'qtype' => 'essay',
1060             'defaultmark' => 1,
1061             'penalty' => 0.3333333,
1062             'length' => 1,
1063             'responseformat' => 'editor',
1064             'responsefieldlines' => 15,
1065             'attachments' => 0,
1066             'graderinfo' => array(
1067                 'text' => '',
1068                 'format' => FORMAT_HTML,
1069                 'files' => array()),
1070         );
1072         $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
1073     }