3 // This file is part of Moodle - http://moodle.org/
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
20 * Unit tests for the Moodle GIFT format.
22 * @package qformat_xml
23 * @copyright 2010 The Open University
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 require_once($CFG->libdir . '/questionlib.php');
28 require_once($CFG->dirroot . '/question/format.php');
29 require_once($CFG->dirroot . '/question/format/gift/format.php');
33 * Unit tests for the GIFT import/export format.
35 * @copyright 2010 The Open University
36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38 class qformat_gift_test extends UnitTestCase {
39 public function assert_same_gift($expectedtext, $text) {
40 $this->assertEqual(str_replace("\r\n", "\n", $expectedtext),
41 str_replace("\r\n", "\n", $text));
44 public function test_import_essay() {
47 ::Q8:: How are you? {}';
48 $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
50 $importer = new qformat_gift();
51 $q = $importer->readquestion($lines);
53 $expectedq = (object) array(
55 'questiontext' => 'How are you?',
56 'questiontextformat' => FORMAT_MOODLE,
57 'generalfeedback' => '',
58 'generalfeedbackformat' => FORMAT_MOODLE,
65 'format' => FORMAT_MOODLE,
70 $this->assert(new CheckSpecifiedFieldsExpectation($expectedq), $q);
73 public function test_export_essay() {
74 $qdata = (object) array(
77 'questiontext' => 'How are you?',
78 'questiontextformat' => FORMAT_MOODLE,
79 'generalfeedback' => '',
80 'generalfeedbackformat' => FORMAT_MOODLE,
85 'options' => (object) array(
87 123 => (object) array(
90 'answerformat' => FORMAT_MOODLE,
93 'feedbackformat' => FORMAT_MOODLE,
99 $exporter = new qformat_gift();
100 $gift = $exporter->writequestion($qdata);
102 $expectedgift = "// question: 666 name: Q8
107 $this->assert_same_gift($expectedgift, $gift);
110 public function test_import_match() {
112 // question: 2 name: Moodle activities
113 ::Moodle activities::[html]Match the <b>activity</b> to the description.{
114 =[html]An activity supporting asynchronous discussions. -> Forum
115 =[moodle]A teacher asks a question and specifies a choice of multiple responses. -> Choice
116 =[plain]A bank of record entries which participants can add to. -> Database
117 =[markdown]A collection of web pages that anyone can add to or edit. -> Wiki
120 $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
122 $importer = new qformat_gift();
123 $q = $importer->readquestion($lines);
125 $expectedq = (object) array(
126 'name' => 'Moodle activities',
127 'questiontext' => 'Match the <b>activity</b> to the description.',
128 'questiontextformat' => FORMAT_HTML,
129 'generalfeedback' => '',
130 'generalfeedbackformat' => FORMAT_HTML,
135 'shuffleanswers' => '1',
136 'subquestions' => array(
138 'text' => 'An activity supporting asynchronous discussions.',
139 'format' => FORMAT_HTML,
143 'text' => 'A teacher asks a question and specifies a choice of multiple responses.',
144 'format' => FORMAT_MOODLE,
148 'text' => 'A bank of record entries which participants can add to.',
149 'format' => FORMAT_PLAIN,
153 'text' => 'A collection of web pages that anyone can add to or edit.',
154 'format' => FORMAT_MARKDOWN,
159 'format' => FORMAT_HTML,
163 'subanswers' => array(
172 // Repeated test for better failure messages.
173 $this->assertEqual($expectedq->subquestions, $q->subquestions);
174 $this->assert(new CheckSpecifiedFieldsExpectation($expectedq), $q);
177 public function test_export_match() {
178 $qdata = (object) array(
180 'name' => 'Moodle activities',
181 'questiontext' => 'Match the <b>activity</b> to the description.',
182 'questiontextformat' => FORMAT_HTML,
183 'generalfeedback' => '',
184 'generalfeedbackformat' => FORMAT_HTML,
189 'options' => (object) array(
192 'shuffleanswers' => 1,
193 'subquestions' => array(
194 42 => (object) array(
198 'questiontext' => 'An activity supporting asynchronous discussions.',
199 'questiontextformat' => FORMAT_HTML,
200 'answertext' => 'Forum',
202 43 => (object) array(
206 'questiontext' => 'A teacher asks a question and specifies a choice of multiple responses.',
207 'questiontextformat' => FORMAT_MOODLE,
208 'answertext' => 'Choice',
210 44 => (object) array(
214 'questiontext' => 'A bank of record entries which participants can add to.',
215 'questiontextformat' => FORMAT_PLAIN,
216 'answertext' => 'Database',
218 45 => (object) array(
222 'questiontext' => 'A collection of web pages that anyone can add to or edit.',
223 'questiontextformat' => FORMAT_MARKDOWN,
224 'answertext' => 'Wiki',
226 46 => (object) array(
230 'questiontext' => '',
231 'questiontextformat' => FORMAT_MARKDOWN,
232 'answertext' => 'Chat',
238 $exporter = new qformat_gift();
239 $gift = $exporter->writequestion($qdata);
241 $expectedgift = "// question: 666 name: Moodle activities
242 ::Moodle activities::[html]Match the <b>activity</b> to the description.{
243 \t=An activity supporting asynchronous discussions. -> Forum
244 \t=[moodle]A teacher asks a question and specifies a choice of multiple responses. -> Choice
245 \t=[plain]A bank of record entries which participants can add to. -> Database
246 \t=[markdown]A collection of web pages that anyone can add to or edit. -> Wiki
252 $this->assert_same_gift($expectedgift, $gift);
255 public function test_import_multichoice() {
257 // multiple choice with specified feedback for right and wrong answers
258 ::Q2:: What's between orange and green in the spectrum?
260 =yellow # right; good!
261 ~red # [html]wrong, it's yellow
262 ~[plain]blue # wrong, it's yellow
264 $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
266 $importer = new qformat_gift();
267 $q = $importer->readquestion($lines);
269 $expectedq = (object) array(
271 'questiontext' => "What's between orange and green in the spectrum?",
272 'questiontextformat' => FORMAT_MOODLE,
273 'generalfeedback' => '',
274 'generalfeedbackformat' => FORMAT_MOODLE,
275 'qtype' => 'multichoice',
280 'shuffleanswers' => '1',
281 'answernumbering' => 'abc',
282 'correctfeedback' => array(
284 'format' => FORMAT_MOODLE,
287 'partiallycorrectfeedback' => array(
289 'format' => FORMAT_MOODLE,
292 'incorrectfeedback' => array(
294 'format' => FORMAT_MOODLE,
300 'format' => FORMAT_MOODLE,
305 'format' => FORMAT_MOODLE,
310 'format' => FORMAT_PLAIN,
314 'fraction' => array(1, 0, 0),
317 'text' => 'right; good!',
318 'format' => FORMAT_MOODLE,
322 'text' => "wrong, it's yellow",
323 'format' => FORMAT_HTML,
327 'text' => "wrong, it's yellow",
328 'format' => FORMAT_MOODLE,
334 // Repeated test for better failure messages.
335 $this->assertEqual($expectedq->answer, $q->answer);
336 $this->assertEqual($expectedq->feedback, $q->feedback);
337 $this->assert(new CheckSpecifiedFieldsExpectation($expectedq), $q);
340 public function test_export_multichoice() {
341 $qdata = (object) array(
344 'questiontext' => "What's between orange and green in the spectrum?",
345 'questiontextformat' => FORMAT_MOODLE,
346 'generalfeedback' => '',
347 'generalfeedbackformat' => FORMAT_MOODLE,
351 'qtype' => 'multichoice',
352 'options' => (object) array(
354 'shuffleanswers' => '1',
355 'answernumbering' => 'abc',
356 'correctfeedback' => '',
357 'correctfeedbackformat' => FORMAT_MOODLE,
358 'partiallycorrectfeedback' => '',
359 'partiallycorrectfeedbackformat' => FORMAT_MOODLE,
360 'incorrectfeedback' => '',
361 'incorrectfeedbackformat' => FORMAT_MOODLE,
363 123 => (object) array(
365 'answer' => 'yellow',
366 'answerformat' => FORMAT_MOODLE,
368 'feedback' => 'right; good!',
369 'feedbackformat' => FORMAT_MOODLE,
371 124 => (object) array(
374 'answerformat' => FORMAT_MOODLE,
376 'feedback' => "wrong, it's yellow",
377 'feedbackformat' => FORMAT_HTML,
379 125 => (object) array(
382 'answerformat' => FORMAT_PLAIN,
384 'feedback' => "wrong, it's yellow",
385 'feedbackformat' => FORMAT_MOODLE,
391 $exporter = new qformat_gift();
392 $gift = $exporter->writequestion($qdata);
394 $expectedgift = "// question: 666 name: Q8
395 ::Q8::What's between orange and green in the spectrum?{
396 \t=yellow#right; good!
397 \t~red#[html]wrong, it's yellow
398 \t~[plain]blue#wrong, it's yellow
403 $this->assert_same_gift($expectedgift, $gift);
406 public function test_import_numerical() {
408 // math range question
409 ::Q5:: What is a number from 1 to 5? {#3:2~#Completely wrong}";
410 $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
412 $importer = new qformat_gift();
413 $q = $importer->readquestion($lines);
415 $expectedq = (object) array(
417 'questiontext' => "What is a number from 1 to 5?",
418 'questiontextformat' => FORMAT_MOODLE,
419 'generalfeedback' => '',
420 'generalfeedbackformat' => FORMAT_MOODLE,
421 'qtype' => 'numerical',
429 'fraction' => array(1, 0),
433 'format' => FORMAT_MOODLE,
437 'text' => "Completely wrong",
438 'format' => FORMAT_MOODLE,
442 'tolerance' => array(2, 0),
445 // Repeated test for better failure messages.
446 $this->assertEqual($expectedq->answer, $q->answer);
447 $this->assertEqual($expectedq->fraction, $q->fraction);
448 $this->assertEqual($expectedq->feedback, $q->feedback);
449 $this->assert(new CheckSpecifiedFieldsExpectation($expectedq), $q);
452 public function test_export_numerical() {
453 $qdata = (object) array(
456 'questiontext' => "What is a number from 1 to 5?",
457 'questiontextformat' => FORMAT_MOODLE,
458 'generalfeedback' => '',
459 'generalfeedbackformat' => FORMAT_MOODLE,
463 'qtype' => 'numerical',
464 'options' => (object) array(
467 'instructions' => '',
468 'instructionsformat' => FORMAT_MOODLE,
472 'unitgradingtype' => 0,
482 'feedbackformat' => FORMAT_MOODLE,
490 'feedback' => "Completely wrong",
491 'feedbackformat' => FORMAT_MOODLE,
497 $exporter = new qformat_gift();
498 $gift = $exporter->writequestion($qdata);
500 $expectedgift = "// question: 666 name: Q5
501 ::Q5::What is a number from 1 to 5?{#
508 $this->assert_same_gift($expectedgift, $gift);
511 public function test_import_shortanswer() {
513 // question: 666 name: Shortanswer
514 ::Shortanswer::Which is the best animal?{
516 =%50%Cat#What is it with Moodlers and cats?
517 =%0%*#Completely wrong
519 $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
521 $importer = new qformat_gift();
522 $q = $importer->readquestion($lines);
524 $expectedq = (object) array(
525 'name' => 'Shortanswer',
526 'questiontext' => "Which is the best animal?",
527 'questiontextformat' => FORMAT_MOODLE,
528 'generalfeedback' => '',
529 'generalfeedbackformat' => FORMAT_MOODLE,
530 'qtype' => 'shortanswer',
539 'fraction' => array(1, 0.5, 0),
543 'format' => FORMAT_MOODLE,
547 'text' => "What is it with Moodlers and cats?",
548 'format' => FORMAT_MOODLE,
552 'text' => "Completely wrong",
553 'format' => FORMAT_MOODLE,
559 // Repeated test for better failure messages.
560 $this->assertEqual($expectedq->answer, $q->answer);
561 $this->assertEqual($expectedq->fraction, $q->fraction);
562 $this->assertEqual($expectedq->feedback, $q->feedback);
563 $this->assert(new CheckSpecifiedFieldsExpectation($expectedq), $q);
566 public function test_export_shortanswer() {
567 $qdata = (object) array(
569 'name' => 'Shortanswer',
570 'questiontext' => "Which is the best animal?",
571 'questiontextformat' => FORMAT_MOODLE,
572 'generalfeedback' => '',
573 'generalfeedbackformat' => FORMAT_MOODLE,
577 'qtype' => 'shortanswer',
578 'options' => (object) array(
588 'feedback' => 'Good!',
589 'feedbackformat' => FORMAT_MOODLE,
596 'feedback' => "What is it with Moodlers and cats?",
597 'feedbackformat' => FORMAT_MOODLE,
604 'feedback' => "Completely wrong",
605 'feedbackformat' => FORMAT_MOODLE,
611 $exporter = new qformat_gift();
612 $gift = $exporter->writequestion($qdata);
614 $expectedgift = "// question: 666 name: Shortanswer
615 ::Shortanswer::Which is the best animal?{
617 \t=%50%Cat#What is it with Moodlers and cats?
618 \t=%0%*#Completely wrong
623 $this->assert_same_gift($expectedgift, $gift);
626 public function test_import_truefalse() {
629 ::Q1:: 42 is the Absolute Answer to everything.{
630 FALSE#42 is the Ultimate Answer.#You gave the right answer.}";
631 $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
633 $importer = new qformat_gift();
634 $q = $importer->readquestion($lines);
636 $expectedq = (object) array(
638 'questiontext' => "42 is the Absolute Answer to everything.",
639 'questiontextformat' => FORMAT_MOODLE,
640 'generalfeedback' => '',
641 'generalfeedbackformat' => FORMAT_MOODLE,
642 'qtype' => 'truefalse',
646 'correctanswer' => 0,
647 'feedbacktrue' => array(
648 'text' => '42 is the Ultimate Answer.',
649 'format' => FORMAT_MOODLE,
652 'feedbackfalse' => array(
653 'text' => 'You gave the right answer.',
654 'format' => FORMAT_MOODLE,
659 $this->assert(new CheckSpecifiedFieldsExpectation($expectedq), $q);
662 public function test_import_truefalse_true_answer1() {
663 $gift = "// name 0-11
664 ::2-08 TSL::TSL is blablabla.{T}";
665 $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
667 $importer = new qformat_gift();
668 $q = $importer->readquestion($lines);
670 $expectedq = (object) array(
671 'name' => '2-08 TSL',
672 'questiontext' => "TSL is blablabla.",
673 'questiontextformat' => FORMAT_MOODLE,
674 'generalfeedback' => '',
675 'generalfeedbackformat' => FORMAT_MOODLE,
676 'qtype' => 'truefalse',
680 'correctanswer' => 1,
681 'feedbacktrue' => array(
683 'format' => FORMAT_MOODLE,
686 'feedbackfalse' => array(
688 'format' => FORMAT_MOODLE,
693 $this->assert(new CheckSpecifiedFieldsExpectation($expectedq), $q);
696 public function test_import_truefalse_true_answer2() {
697 $gift = "// name 0-11
698 ::2-08 TSL::TSL is blablabla.{TRUE}";
699 $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
701 $importer = new qformat_gift();
702 $q = $importer->readquestion($lines);
704 $expectedq = (object) array(
705 'name' => '2-08 TSL',
706 'questiontext' => "TSL is blablabla.",
707 'questiontextformat' => FORMAT_MOODLE,
708 'generalfeedback' => '',
709 'generalfeedbackformat' => FORMAT_MOODLE,
710 'qtype' => 'truefalse',
714 'correctanswer' => 1,
715 'feedbacktrue' => array(
717 'format' => FORMAT_MOODLE,
720 'feedbackfalse' => array(
722 'format' => FORMAT_MOODLE,
727 $this->assert(new CheckSpecifiedFieldsExpectation($expectedq), $q);
730 public function test_export_truefalse() {
731 $qdata = (object) array(
734 'questiontext' => "42 is the Absolute Answer to everything.",
735 'questiontextformat' => FORMAT_MOODLE,
736 'generalfeedback' => '',
737 'generalfeedbackformat' => FORMAT_MOODLE,
741 'qtype' => 'truefalse',
742 'options' => (object) array(
753 'feedback' => 'You gave the right answer.',
754 'feedbackformat' => FORMAT_MOODLE,
761 'feedback' => "42 is the Ultimate Answer.",
762 'feedbackformat' => FORMAT_HTML,
768 $exporter = new qformat_gift();
769 $gift = $exporter->writequestion($qdata);
771 $expectedgift = "// question: 666 name: Q1
772 ::Q1::42 is the Absolute Answer to everything.{TRUE#[html]42 is the Ultimate Answer.#You gave the right answer.}
776 $this->assert_same_gift($expectedgift, $gift);