MDL-20636 Question XML export unit tests now all pass.

This commit is contained in:
Tim Hunt
2011-01-18 14:36:40 +00:00
parent 49e2bba7cc
commit 5f7cfba7fa
7 changed files with 105 additions and 97 deletions
+10 -10
View File
@@ -135,9 +135,9 @@ class test_question_maker {
$mc->answernumbering = 'abc';
$mc->answers = array(
13 => new question_answer('A', 1, 'A is right'),
14 => new question_answer('B', -0.3333333, 'B is wrong'),
15 => new question_answer('C', -0.3333333, 'C is wrong'),
13 => new question_answer(13, 'A', 1, 'A is right', FORMAT_HTML),
14 => new question_answer(14, 'B', -0.3333333, 'B is wrong', FORMAT_HTML),
15 => new question_answer(15, 'C', -0.3333333, 'C is wrong', FORMAT_HTML),
);
return $mc;
@@ -163,10 +163,10 @@ class test_question_maker {
self::set_standard_combined_feedback_fields($mc);
$mc->answers = array(
13 => new question_answer('A', 0.5, 'A is part of the right answer'),
14 => new question_answer('B', -1, 'B is wrong'),
15 => new question_answer('C', 0.5, 'C is part of the right answer'),
16 => new question_answer('D', -1, 'D is wrong'),
13 => new question_answer(13, 'A', 0.5, 'A is part of the right answer', FORMAT_HTML),
14 => new question_answer(14, 'B', -1, 'B is wrong', FORMAT_HTML),
15 => new question_answer(15, 'C', 0.5, 'C is part of the right answer', FORMAT_HTML),
16 => new question_answer(16, 'D', -1, 'D is wrong', FORMAT_HTML),
);
return $mc;
@@ -215,9 +215,9 @@ class test_question_maker {
$sa->generalfeedback = 'Generalfeedback: frog or toad would have been OK.';
$sa->usecase = false;
$sa->answers = array(
new question_answer('frog', 1.0, 'Frog is a very good answer.'),
new question_answer('toad', 0.8, 'Toad is an OK good answer.'),
new question_answer('*', 0.0, 'That is a bad answer.'),
13 => new question_answer(13, 'frog', 1.0, 'Frog is a very good answer.', FORMAT_HTML),
14 => new question_answer(14, 'toad', 0.8, 'Toad is an OK good answer.', FORMAT_HTML),
15 => new question_answer(15, '*', 0.0, 'That is a bad answer.', FORMAT_HTML),
);
$sa->qtype = question_bank::get_qtype('shortanswer');
+24 -33
View File
@@ -1160,8 +1160,6 @@ class qformat_xml extends qformat_default {
} else if ($question->qtype != MULTIANSWER) {
// for all question types except Close
$name_text = $this->writetext($question->name, 3);
$qtformat = $this->get_format($question->questiontextformat);
$generalfeedbackformat = $this->get_format($question->generalfeedbackformat);
$question_text = $this->writetext($question->questiontext, 3);
$question_text_files = $this->writefiles($question->questiontextfiles);
@@ -1173,11 +1171,11 @@ class qformat_xml extends qformat_default {
$expout .= " <name>\n";
$expout .= $name_text;
$expout .= " </name>\n";
$expout .= " <questiontext format=\"$qtformat\">\n";
$expout .= " <questiontext {$this->format($question->questiontextformat)}>\n";
$expout .= $question_text;
$expout .= $question_text_files;
$expout .= " </questiontext>\n";
$expout .= " <generalfeedback format=\"$generalfeedbackformat\">\n";
$expout .= " <generalfeedback {$this->format($question->generalfeedbackformat)}>\n";
$expout .= $generalfeedback;
$expout .= $generalfeedback_files;
$expout .= " </generalfeedback>\n";
@@ -1208,12 +1206,12 @@ class qformat_xml extends qformat_default {
case TRUEFALSE:
$trueanswer = $question->options->answers[$question->options->trueanswer];
$expout .= $this->write_answer(new question_answer(
'true', $trueanswer->fraction, $trueanswer->feedback));
$trueanswer->answer = 'true';
$expout .= $this->write_answer($trueanswer);
$falseanswer = $question->options->answers[$question->options->falseanswer];
$expout .= $this->write_answer(new question_answer(
'false', $falseanswer->fraction, $falseanswer->feedback));
$falseanswer->answer = 'false';
$expout .= $this->write_answer($falseanswer);
break;
case MULTICHOICE:
@@ -1222,18 +1220,6 @@ class qformat_xml extends qformat_default {
$expout .= " <answernumbering>{$question->options->answernumbering}</answernumbering>\n";
$expout .= $this->write_combined_feedback($question->options);
$expout .= $this->write_answers($question->options->answers);
// TODO move the following to writeanswers.
foreach($question->options->answers as $answer) {
$percent = $answer->fraction * 100;
$expout .= " <answer fraction=\"$percent\">\n";
$expout .= $this->writetext($answer->answer,4,false);
$feedbackformat = $this->get_format($answer->feedbackformat);
$expout .= " <feedback format=\"$feedbackformat\">\n";
$expout .= $this->writetext($answer->feedback,5,false);
$expout .= $this->writefiles($answer->feedbackfiles);
$expout .= " </feedback>\n";
$expout .= " </answer>\n";
}
break;
case SHORTANSWER:
@@ -1271,9 +1257,8 @@ class qformat_xml extends qformat_default {
$expout .= " <unitsleft>{$question->options->unitsleft}</unitsleft>\n";
}
if (!empty($question->options->instructionsformat)) {
$textformat = $this->get_format($question->options->instructionsformat);
$files = $fs->get_area_files($contextid, 'qtype_numerical', 'instruction', $question->id);
$expout .= " <instructions format=\"$textformat\">\n";
$expout .= " <instructions {$this->format($question->options->instructionsformat)}>\n";
$expout .= $this->writetext($question->options->instructions, 3);
$expout .= $this->writefiles($files);
$expout .= " </instructions>\n";
@@ -1285,8 +1270,7 @@ class qformat_xml extends qformat_default {
$expout .= $this->write_combined_feedback($question->options);
foreach ($question->options->subquestions as $subquestion) {
$files = $fs->get_area_files($contextid, 'qtype_match', 'subquestion', $subquestion->id);
$textformat = $this->get_format($subquestion->questiontextformat);
$expout .= " <subquestion format=\"$textformat\">\n";
$expout .= " <subquestion {$this->format($subquestion->questiontextformat)}>\n";
$expout .= $this->writetext($subquestion->questiontext, 3);
$expout .= $this->writefiles($files);
$expout .= " <answer>\n";
@@ -1345,7 +1329,6 @@ class qformat_xml extends qformat_default {
$tolerance = $answer->tolerance;
$tolerancetype = $answer->tolerancetype;
$correctanswerlength= $answer->correctanswerlength ;
$correctanswerformat= $answer->correctanswerformat;
$percent = 100 * $answer->fraction;
$expout .= "<answer fraction=\"$percent\">\n";
// "<text/>" tags are an added feature, old files won't have them
@@ -1355,7 +1338,7 @@ class qformat_xml extends qformat_default {
$expout .= " <correctanswerformat>$correctanswerformat</correctanswerformat>\n";
$expout .= " <correctanswerlength>$correctanswerlength</correctanswerlength>\n";
$feedbackformat = $this->get_format($answer->feedbackformat);
$expout .= " <feedback format=\"$feedbackformat\">\n";
$expout .= " <feedback {$this->format($answer->correctanswerformat)}>\n";
$expout .= $this->writetext($answer->feedback);
$expout .= $this->writefiles($answer->feedbackfiles);
$expout .= " </feedback>\n";
@@ -1375,9 +1358,8 @@ class qformat_xml extends qformat_default {
}
if (isset($question->options->instructionsformat)) {
$textformat = $this->get_format($question->options->instructionsformat);
$files = $fs->get_area_files($contextid, $component, 'instruction', $question->id);
$expout .= " <instructions format=\"$textformat\">\n";
$expout .= " <instructions {$this->format($question->options->instructionsformat)}>\n";
$expout .= $this->writetext($question->options->instructions, 3);
$expout .= $this->writefiles($files);
$expout .= " </instructions>\n";
@@ -1478,8 +1460,9 @@ class qformat_xml extends qformat_default {
$output = '';
$output .= " <answer fraction=\"$percent\">\n";
$output .= $this->writetext($answer->answer, 3);
$output .= " <feedback>\n";
$output .= " <feedback {$this->format($answer->feedbackformat)}>\n";
$output .= $this->writetext($answer->feedback, 4);
$output .= $this->writefiles($answer->feedbackfiles);
$output .= " </feedback>\n";
$output .= $extra;
$output .= " </answer>\n";
@@ -1498,9 +1481,17 @@ class qformat_xml extends qformat_default {
return $output;
}
/**
* @param unknown_type $format a FORMAT_... constant.
* @return string the attribute to add to an XML tag.
*/
protected function format($format) {
return 'format="' . $this->get_format($format) . '"';
}
public function write_hint($hint) {
$output = '';
$output .= " <hint>\n";
$output .= " <hint {$this->format($hint->hintformat)}>\n";
$output .= ' ' . $this->writetext($hint->hint);
if (!empty($hint->shownumcorrect)) {
$output .= " <shownumcorrect/>\n";
@@ -1516,11 +1507,11 @@ class qformat_xml extends qformat_default {
}
public function write_combined_feedback($questionoptions) {
$output = " <correctfeedback>
$output = " <correctfeedback {$this->format($questionoptions->correctfeedbackformat)}>
{$this->writetext($questionoptions->correctfeedback)} </correctfeedback>
<partiallycorrectfeedback>
<partiallycorrectfeedback {$this->format($questionoptions->partiallycorrectfeedbackformat)}>
{$this->writetext($questionoptions->partiallycorrectfeedback)} </partiallycorrectfeedback>
<incorrectfeedback>
<incorrectfeedback {$this->format($questionoptions->incorrectfeedbackformat)}>
{$this->writetext($questionoptions->incorrectfeedback)} </incorrectfeedback>\n";
if (!empty($questionoptions->shownumcorrect)) {
$output .= " <shownumcorrect/>\n";
@@ -69,9 +69,9 @@ class qformat_xml_test extends UnitTestCase {
$q->generalfeedback = 'Generalfeedback: frog or toad would have been OK.';
$q->options->usecase = false;
$q->options->answers = array(
new question_answer('frog', 1.0, 'Frog is a very good answer.'),
new question_answer('toad', 0.8, 'Toad is an OK good answer.'),
new question_answer('*', 0.0, 'That is a bad answer.'),
13 => new question_answer(13, 'frog', 1.0, 'Frog is a very good answer.', FORMAT_HTML),
14 => new question_answer(14, 'toad', 0.8, 'Toad is an OK good answer.', FORMAT_HTML),
15 => new question_answer(15, '*', 0.0, 'That is a bad answer.', FORMAT_HTML),
);
$q->qtype = 'shortanswer';
$q->hints = array(
@@ -81,13 +81,12 @@ class qformat_xml_test extends UnitTestCase {
$exporter = new qformat_xml();
$xml = $exporter->writequestion($q);
$this->assertPattern('|<hint>\s*<text>\s*This is the first hint\.\s*</text>\s*</hint>|', $xml);
$this->assertPattern('|<hint format=\"moodle_auto_format\">\s*<text>\s*This is the first hint\.\s*</text>\s*</hint>|', $xml);
$this->assertNoPattern('|<shownumcorrect/>|', $xml);
$this->assertNoPattern('|<clearwrong/>|', $xml);
$this->assertNoPattern('|<options>|', $xml);
}
public function test_write_hint_with_parts() {
$q = $this->make_test_question();
$q->name = 'Matching question';
@@ -97,8 +96,11 @@ class qformat_xml_test extends UnitTestCase {
$q->options->shuffleanswers = 1;
$q->options->correctfeedback = '';
$q->options->correctfeedbackformat = FORMAT_HTML;
$q->options->partiallycorrectfeedback = '';
$q->options->partiallycorrectfeedbackformat = FORMAT_HTML;
$q->options->incorrectfeedback = '';
$q->options->incorrectfeedbackformat = FORMAT_HTML;
$q->options->subquestions = array();
$q->hints = array(
@@ -109,9 +111,9 @@ class qformat_xml_test extends UnitTestCase {
$exporter = new qformat_xml();
$xml = $exporter->writequestion($q);
$this->assertPattern('|<hint>\s*<text>\s*This is the first hint\.\s*</text>|', $xml);
$this->assertPattern('|<hint>\s*<text>\s*This is the second hint\.\s*</text>|', $xml);
list($ignored, $hint1, $hint2) = explode('<hint>', $xml);
$this->assertPattern('|<hint format=\"html\">\s*<text>\s*This is the first hint\.\s*</text>|', $xml);
$this->assertPattern('|<hint format=\"html\">\s*<text>\s*This is the second hint\.\s*</text>|', $xml);
list($ignored, $hint1, $hint2) = explode('<hint', $xml);
$this->assertNoPattern('|<shownumcorrect/>|', $hint1);
$this->assertPattern('|<clearwrong/>|', $hint1);
$this->assertPattern('|<shownumcorrect/>|', $hint2);
@@ -245,7 +247,7 @@ END;
<questiontext format="html">
<text>The question text.</text>
</questiontext>
<generalfeedback>
<generalfeedback format="html">
<text>Here is some general feedback.</text>
</generalfeedback>
<defaultgrade>0</defaultgrade>
@@ -316,7 +318,7 @@ END;
<questiontext format="moodle_auto_format">
<text>Write something.</text>
</questiontext>
<generalfeedback>
<generalfeedback format="moodle_auto_format">
<text>I hope you wrote something interesting.</text>
</generalfeedback>
<defaultgrade>1</defaultgrade>
@@ -432,9 +434,12 @@ END;
$qdata->options = new stdClass;
$qdata->options->shuffleanswers = 1;
$qdata->options->correctfeedback = 'Well done.';
$qdata->options->correctfeedbackformat = FORMAT_HTML;
$qdata->options->partiallycorrectfeedback = 'Not entirely.';
$qdata->options->partiallycorrectfeedbackformat = FORMAT_HTML;
$qdata->options->shownumcorrect = false;
$qdata->options->incorrectfeedback = 'Completely wrong!';
$qdata->options->incorrectfeedbackformat = FORMAT_HTML;
$subq1 = new stdClass();
$subq1->id = -4;
@@ -479,51 +484,51 @@ END;
<questiontext format="html">
<text>Match the upper and lower case letters.</text>
</questiontext>
<generalfeedback>
<generalfeedback format="html">
<text><![CDATA[The answer is A -> a, B -> b and C -> c.]]></text>
</generalfeedback>
<defaultgrade>1</defaultgrade>
<penalty>0.3333333</penalty>
<hidden>0</hidden>
<shuffleanswers>true</shuffleanswers>
<correctfeedback>
<correctfeedback format="html">
<text>Well done.</text>
</correctfeedback>
<partiallycorrectfeedback>
<partiallycorrectfeedback format="html">
<text>Not entirely.</text>
</partiallycorrectfeedback>
<incorrectfeedback>
<incorrectfeedback format="html">
<text>Completely wrong!</text>
</incorrectfeedback>
<subquestion>
<subquestion format="html">
<text>A</text>
<answer>
<text>a</text>
</answer>
</subquestion>
<subquestion>
<subquestion format="html">
<text>B</text>
<answer>
<text>b</text>
</answer>
</subquestion>
<subquestion>
<subquestion format="html">
<text>C</text>
<answer>
<text>c</text>
</answer>
</subquestion>
<subquestion>
<subquestion format="html">
<text></text>
<answer>
<text>d</text>
</answer>
</subquestion>
<hint>
<hint format="html">
<text>Hint 1</text>
<shownumcorrect/>
</hint>
<hint>
<hint format="html">
<text></text>
<shownumcorrect/>
<clearwrong/>
@@ -644,15 +649,18 @@ END;
$qdata->options->shuffleanswers = 0;
$qdata->options->answernumbering = 'abc';
$qdata->options->correctfeedback = '<p>Your answer is correct.</p>';
$qdata->options->correctfeedbackformat = FORMAT_HTML;
$qdata->options->partiallycorrectfeedback = '<p>Your answer is partially correct.</p>';
$qdata->options->partiallycorrectfeedbackformat = FORMAT_HTML;
$qdata->options->shownumcorrect = 1;
$qdata->options->incorrectfeedback = '<p>Your answer is incorrect.</p>';
$qdata->options->incorrectfeedbackformat = FORMAT_HTML;
$qdata->options->answers = array(
new question_answer('1', 0, ''),
new question_answer('2', 1, ''),
new question_answer('3', 0, ''),
new question_answer('4', 1, ''),
13 => new question_answer(13, '1', 0, '', FORMAT_HTML),
14 => new question_answer(14, '2', 1, '', FORMAT_HTML),
15 => new question_answer(15, '3', 0, '', FORMAT_HTML),
16 => new question_answer(16, '4', 1, '', FORMAT_HTML),
);
$qdata->hints = array(
@@ -671,7 +679,7 @@ END;
<questiontext format="html">
<text>Which are the even numbers?</text>
</questiontext>
<generalfeedback>
<generalfeedback format="html">
<text>The even numbers are 2 and 4.</text>
</generalfeedback>
<defaultgrade>2</defaultgrade>
@@ -680,44 +688,44 @@ END;
<single>false</single>
<shuffleanswers>false</shuffleanswers>
<answernumbering>abc</answernumbering>
<correctfeedback>
<correctfeedback format="html">
<text><![CDATA[<p>Your answer is correct.</p>]]></text>
</correctfeedback>
<partiallycorrectfeedback>
<partiallycorrectfeedback format="html">
<text><![CDATA[<p>Your answer is partially correct.</p>]]></text>
</partiallycorrectfeedback>
<incorrectfeedback>
<incorrectfeedback format="html">
<text><![CDATA[<p>Your answer is incorrect.</p>]]></text>
</incorrectfeedback>
<shownumcorrect/>
<answer fraction="0">
<text>1</text>
<feedback>
<feedback format="html">
<text></text>
</feedback>
</answer>
<answer fraction="100">
<text>2</text>
<feedback>
<feedback format="html">
<text></text>
</feedback>
</answer>
<answer fraction="0">
<text>3</text>
<feedback>
<feedback format="html">
<text></text>
</feedback>
</answer>
<answer fraction="100">
<text>4</text>
<feedback>
<feedback format="html">
<text></text>
</feedback>
</answer>
<hint>
<hint format="html">
<text>Hint 1.</text>
</hint>
<hint>
<hint format="html">
<text>Hint 2.</text>
</hint>
</question>
@@ -927,8 +935,8 @@ END;
$qdata->options->usecase = 0;
$qdata->options->answers = array(
new question_answer('Beta', 1, 'Well done!'),
new question_answer('*', 0, 'Doh!'),
13 => new question_answer(13, 'Beta', 1, 'Well done!', FORMAT_HTML),
14 => new question_answer(14, '*', 0, 'Doh!', FORMAT_HTML),
);
$qdata->hints = array(
@@ -1043,8 +1051,8 @@ END;
$qdata->hidden = 0;
$qdata->options->answers = array(
1 => new question_answer('True', 1, 'Well done!'),
2 => new question_answer('False', 0, 'Doh!'),
1 => new question_answer(1, 'True', 1, 'Well done!', FORMAT_HTML),
2 => new question_answer(2, 'False', 0, 'Doh!', FORMAT_HTML),
);
$qdata->options->trueanswer = 1;
$qdata->options->falseanswer = 2;
@@ -1060,7 +1068,7 @@ END;
<questiontext format="html">
<text>The answer is true.</text>
</questiontext>
<generalfeedback>
<generalfeedback format="html">
<text>General feedback: You should have chosen true.</text>
</generalfeedback>
<defaultgrade>1</defaultgrade>
@@ -1068,13 +1076,13 @@ END;
<hidden>0</hidden>
<answer fraction="100">
<text>true</text>
<feedback>
<feedback format="html">
<text>Well done!</text>
</feedback>
</answer>
<answer fraction="0">
<text>false</text>
<feedback>
<feedback format="html">
<text>Doh!</text>
</feedback>
</answer>
@@ -84,12 +84,12 @@ class qtype_multichoice_single_question_test extends UnitTestCase {
test_question_maker::set_standard_combined_feedback_fields($mc);
$mc->answers = array(
11 => new question_answer('1', 0.3333333, ''),
12 => new question_answer('2', -1, ''),
13 => new question_answer('3', 0.3333333, ''),
14 => new question_answer('4', -1, ''),
15 => new question_answer('5', 0.3333333, ''),
16 => new question_answer('6', -1, ''),
11 => new question_answer(11, '1', 0.3333333, '', FORMAT_HTML),
12 => new question_answer(12, '2', -1, '', FORMAT_HTML),
13 => new question_answer(13, '3', 0.3333333, '', FORMAT_HTML),
14 => new question_answer(14, '4', -1, '', FORMAT_HTML),
15 => new question_answer(15, '5', 0.3333333, '', FORMAT_HTML),
16 => new question_answer(16, '6', -1, '', FORMAT_HTML),
);
$mc->init_first_step(new question_attempt_step());
+9 -1
View File
@@ -673,6 +673,9 @@ abstract class question_graded_by_strategy extends question_graded_automatically
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class question_answer {
/** @var integer the answer id. */
public $id;
/** @var string the answer. */
public $answer;
@@ -682,16 +685,21 @@ class question_answer {
/** @var string the feedback for this answer. */
public $feedback;
/** @var integer one of the FORMAT_... constans. */
public $feedbackformat;
/**
* Constructor.
* @param string $answer the answer.
* @param number $fraction the fraction this answer is worth.
* @param string $feedback the feedback for this answer.
*/
public function __construct($answer, $fraction, $feedback) {
public function __construct($id, $answer, $fraction, $feedback, $feedbackformat) {
$this->id = $id;
$this->answer = $answer;
$this->fraction = $fraction;
$this->feedback = $feedback;
$this->feedbackformat = $feedbackformat;
}
}
+2 -1
View File
@@ -672,7 +672,8 @@ class question_type {
return;
}
foreach ($questiondata->options->answers as $a) {
$question->answers[$a->id] = new question_answer($a->answer, $a->fraction, $a->feedback);
$question->answers[$a->id] = new question_answer($a->id, $a->answer,
$a->fraction, $a->feedback, $a->feedbackformat);
}
}
@@ -64,23 +64,23 @@ class question_first_matching_answer_grading_strategy_test extends UnitTestCase
}
public function test_matching_answer_returned1() {
$answer = new question_answer('frog', 1, '');
$answer = new question_answer(0, 'frog', 1, '', FORMAT_HTML);
$question = new test_response_answer_comparer(array($answer));
$strategy = new question_first_matching_answer_grading_strategy($question);
$this->assertIdentical($answer, $strategy->grade(array('answer' => 'frog')));
}
public function test_matching_answer_returned2() {
$answer = new question_answer('frog', 1, '');
$answer2 = new question_answer('frog', 0.5, '');
$answer = new question_answer(0, 'frog', 1, '', FORMAT_HTML);
$answer2 = new question_answer(0, 'frog', 0.5, '');
$question = new test_response_answer_comparer(array($answer, $answer2));
$strategy = new question_first_matching_answer_grading_strategy($question);
$this->assertIdentical($answer, $strategy->grade(array('answer' => 'frog')));
}
public function test_no_matching_answer_gives_null() {
$answer = new question_answer('frog', 1, '');
$answer2 = new question_answer('frog', 0.5, '');
$answer = new question_answer(0, 'frog', 1, '', FORMAT_HTML);
$answer2 = new question_answer(0, 'frog', 0.5, '', FORMAT_HTML);
$question = new test_response_answer_comparer(array($answer, $answer2));
$strategy = new question_first_matching_answer_grading_strategy($question);
$this->assertNull($strategy->grade(array('answer' => 'toad')));