diff --git a/question/engine/tests/helpers.php b/question/engine/tests/helpers.php index ece0ed7da0d..a55c6c8fb8a 100644 --- a/question/engine/tests/helpers.php +++ b/question/engine/tests/helpers.php @@ -96,6 +96,29 @@ abstract class question_test_helper { * this question type. */ abstract public function get_test_questions(); + + /** + * Set up a form to create a question in $cat. This method also sets cat and contextid on $questiondata object. + * @param object $cat the category + * @param object $questiondata form initialisation requires question data. + * @return moodleform + */ + public static function get_question_editing_form($cat, $questiondata) { + $catcontext = context::instance_by_id($cat->contextid, MUST_EXIST); + $contexts = new question_edit_contexts($catcontext); + $dataforformconstructor = new stdClass(); + $dataforformconstructor->qtype = $questiondata->qtype; + $dataforformconstructor->contextid = $questiondata->contextid = $catcontext->id; + $dataforformconstructor->category = $questiondata->category = $cat->id; + $dataforformconstructor->formoptions = new stdClass(); + $dataforformconstructor->formoptions->canmove = true; + $dataforformconstructor->formoptions->cansaveasnew = true; + $dataforformconstructor->formoptions->movecontext = false; + $dataforformconstructor->formoptions->canedit = true; + $dataforformconstructor->formoptions->repeatelements = true; + $qtype = question_bank::get_qtype($questiondata->qtype); + return $qtype->create_editing_form('question.php', $dataforformconstructor, $cat, $contexts, true); + } } @@ -172,18 +195,6 @@ class test_question_maker { $qdata->hints = array(); } - public static function initialise_question_form_data($qdata) { - $formdata = new stdClass(); - $formdata->id = 0; - $formdata->category = '0,0'; - $formdata->usecurrentcat = 1; - $formdata->categorymoveto = '0,0'; - $formdata->tags = array(); - $formdata->penalty = 0.3333333; - $formdata->questiontextformat = FORMAT_HTML; - $formdata->generalfeedbackformat = FORMAT_HTML; - } - /** * Get the test helper class for a particular question type. * @param $qtype the question type name, e.g. 'multichoice'. @@ -413,6 +424,19 @@ class test_question_maker { $q->incorrectfeedback = self::STANDARD_OVERALL_INCORRECT_FEEDBACK; $q->incorrectfeedbackformat = FORMAT_HTML; } + + /** + * Add some standard overall feedback to a question's form data. + */ + public static function set_standard_combined_feedback_form_data($form) { + $form->correctfeedback = array('text' => self::STANDARD_OVERALL_CORRECT_FEEDBACK, + 'format' => FORMAT_HTML); + $form->partiallycorrectfeedback = array('text' => self::STANDARD_OVERALL_PARTIALLYCORRECT_FEEDBACK, + 'format' => FORMAT_HTML); + $form->shownumcorrect = true; + $form->incorrectfeedback = array('text' => self::STANDARD_OVERALL_INCORRECT_FEEDBACK, + 'format' => FORMAT_HTML); + } } diff --git a/question/type/calculatedsimple/tests/helper.php b/question/type/calculatedsimple/tests/helper.php index 4cd72a32c8c..53cb8e4282d 100644 --- a/question/type/calculatedsimple/tests/helper.php +++ b/question/type/calculatedsimple/tests/helper.php @@ -38,7 +38,7 @@ require_once($CFG->dirroot . '/question/type/calculated/tests/helper.php'); */ class qtype_calculatedsimple_test_helper extends question_test_helper { public function get_test_questions() { - return array('sum'); + return array('sum', 'sumwithvariants'); } /** @@ -77,4 +77,184 @@ class qtype_calculatedsimple_test_helper extends question_test_helper { return $q; } + + + public function get_calculatedsimple_question_form_data_sumwithvariants() { + $form = new stdClass(); + + $form->name = 'Calculated simple'; + + $form->qtype = 'calculatedsimple'; + + $form->questiontext = array(); + $form->questiontext['text'] = '
This is a simple sum of two variables.
'; + $form->questiontext['format'] = '1'; + + $form->defaultmark = 1; + $form->generalfeedback = array(); + $form->generalfeedback['text'] = 'The answer is {a} + {b}
'; + $form->generalfeedback['format'] = '1'; + + $form->synchronize = 0; + $form->initialcategory = 1; + $form->reload = 1; + $form->mform_isexpanded_id_answerhdr = 1; + $form->noanswers = 1; + $form->answer = array('{a} + {b}'); + + $form->fraction = array('1.0'); + + $form->tolerance = array(0.01); + $form->tolerancetype = array('1'); + + $form->correctanswerlength = array('2'); + $form->correctanswerformat = array('1'); + + $form->feedback = array(); + $form->feedback[0] = array(); + $form->feedback[0]['text'] = ''; + $form->feedback[0]['format'] = '1'; + + $form->unitrole = '3'; + $form->unitpenalty = 0.1; + $form->unitgradingtypes = '1'; + $form->unitsleft = '0'; + $form->nounits = 1; + $form->multiplier = array('1.0'); + + $form->penalty = '0.3333333'; + $form->numhints = 2; + $form->hint = array(); + $form->hint[0] = array(); + $form->hint[0]['text'] = ''; + $form->hint[0]['format'] = '1'; + + $form->hint[1] = array(); + $form->hint[1]['text'] = ''; + $form->hint[1]['format'] = '1'; + + $form->calcmin = array(); + $form->calcmin[1] = 1; + $form->calcmin[2] = 1; + + $form->calcmax = array(); + $form->calcmax[1] = 10; + $form->calcmax[2] = 10; + + $form->calclength = array(); + $form->calclength[1] = '1'; + $form->calclength[2] = '1'; + + $form->calcdistribution = array(); + $form->calcdistribution[1] = 0; + $form->calcdistribution[2] = 0; + + $form->datasetdef = array(); + $form->datasetdef[1] = '1-0-a'; + $form->datasetdef[2] = '1-0-b'; + + $form->defoptions = array(); + $form->defoptions[1] = ''; + $form->defoptions[2] = ''; + + $form->selectadd = '10'; + $form->selectshow = '10'; + $form->number = array(); + $form->number[1] = '2.3'; + $form->number[2] = '7.6'; + $form->number[3] = '2.1'; + $form->number[4] = '6.4'; + $form->number[5] = '1.4'; + $form->number[6] = '1.9'; + $form->number[7] = '9.9'; + $form->number[8] = '9.5'; + $form->number[9] = '9.0'; + $form->number[10] = '5.2'; + $form->number[11] = '2.1'; + $form->number[12] = '7.3'; + $form->number[13] = '7.9'; + $form->number[14] = '1.2'; + $form->number[15] = '2.3'; + $form->number[16] = '3.4'; + $form->number[17] = '1.9'; + $form->number[18] = '5.2'; + $form->number[19] = '3.4'; + $form->number[20] = '3.4'; + + $form->itemid = array_fill(1, 20, 0); + + $form->definition = array(); + $form->definition[1] = '1-0-b'; + $form->definition[2] = '1-0-a'; + $form->definition[3] = '1-0-b'; + $form->definition[4] = '1-0-a'; + $form->definition[5] = '1-0-b'; + $form->definition[6] = '1-0-a'; + $form->definition[7] = '1-0-b'; + $form->definition[8] = '1-0-a'; + $form->definition[9] = '1-0-b'; + $form->definition[10] = '1-0-a'; + $form->definition[11] = '1-0-b'; + $form->definition[12] = '1-0-a'; + $form->definition[13] = '1-0-b'; + $form->definition[14] = '1-0-a'; + $form->definition[15] = '1-0-b'; + $form->definition[16] = '1-0-a'; + $form->definition[17] = '1-0-b'; + $form->definition[18] = '1-0-a'; + $form->definition[19] = '1-0-b'; + $form->definition[20] = '1-0-a'; + + return $form; + } + + public function get_calculatedsimple_question_data_sumwithvariants() { + $q = new stdClass(); + + $q->name = 'Calculated simple'; + $q->questiontext = 'This is a simple sum of two variables.
'; + $q->questiontextformat = '1'; + $q->generalfeedback = 'The answer is {a} + {b}
'; + $q->generalfeedbackformat = '1'; + $q->defaultmark = 1; + $q->penalty = 0.3333333; + $q->qtype = 'calculatedsimple'; + $q->length = '1'; + $q->hidden = '0'; + $q->options = new stdClass(); + $q->options->synchronize = 0; + $q->options->single = 0; + $q->options->answernumbering = 'abc'; + $q->options->shuffleanswers = 0; + $q->options->correctfeedback = ''; + $q->options->partiallycorrectfeedback = ''; + $q->options->incorrectfeedback = ''; + $q->options->correctfeedbackformat = 0; + $q->options->partiallycorrectfeedbackformat = 0; + $q->options->incorrectfeedbackformat = 0; + $q->options->answers = array(); + $q->options->answers[0] = new stdClass(); + $q->options->answers[0]->id = '6977'; + $q->options->answers[0]->question = '3379'; + $q->options->answers[0]->answer = '{a} + {b}'; + $q->options->answers[0]->answerformat = '0'; + $q->options->answers[0]->fraction = '1.0000000'; + $q->options->answers[0]->feedback = ''; + $q->options->answers[0]->feedbackformat = '1'; + $q->options->answers[0]->tolerance = '0.01'; + $q->options->answers[0]->tolerancetype = '1'; + $q->options->answers[0]->correctanswerlength = '2'; + $q->options->answers[0]->correctanswerformat = '1'; + + $q->options->units = array(); + + $q->options->unitgradingtype = '0'; + $q->options->unitpenalty = '0.1000000'; + $q->options->showunits = '3'; + $q->options->unitsleft = '0'; + + $q->hints = array(); + + return $q; + } } diff --git a/question/type/calculatedsimple/tests/questiontype_test.php b/question/type/calculatedsimple/tests/questiontype_test.php new file mode 100644 index 00000000000..1b9771ab720 --- /dev/null +++ b/question/type/calculatedsimple/tests/questiontype_test.php @@ -0,0 +1,122 @@ +. + +/** + * Unit tests for the calculatedsimple question type class. + * + * @package qtype_calculatedsimple + * @copyright 2013 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/question/type/calculatedsimple/questiontype.php'); +require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); +require_once($CFG->dirroot . '/question/type/edit_question_form.php'); +require_once($CFG->dirroot . '/question/type/calculatedsimple/edit_calculatedsimple_form.php'); + + +/** + * Unit tests for the calculatedsimple question type class. + * + * @copyright 2007 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_calculatedsimple_test extends advanced_testcase { + public static $includecoverage = array( + 'question/type/questiontypebase.php', + 'question/type/calculatedsimple/questiontype.php', + 'question/type/edit_question_form.php', + 'question/type/calculatedsimple/edit_calculatedsimple_form.php' + ); + + protected $qtype; + + protected function setUp() { + $this->qtype = new qtype_calculatedsimple(); + } + + protected function tearDown() { + $this->qtype = null; + } + + public function test_name() { + $this->assertEquals($this->qtype->name(), 'calculatedsimple'); + } + + public function test_can_analyse_responses() { + $this->assertTrue($this->qtype->can_analyse_responses()); + } + + + public function test_question_saving_sumwithvariants() { + $this->resetAfterTest(true); + $this->setAdminUser(); + + $questiondata = test_question_maker::get_question_data('calculatedsimple', 'sumwithvariants'); + $formdata = test_question_maker::get_question_form_data('calculatedsimple', 'sumwithvariants'); + + $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $cat = $generator->create_question_category(array()); + + $formdata->category = "{$cat->id},{$cat->contextid}"; + qtype_calculatedsimple_edit_form::mock_submit((array)$formdata); + + $form = qtype_calculatedsimple_test_helper::get_question_editing_form($cat, $questiondata); + + $this->assertTrue($form->is_validated()); + + $fromform = $form->get_data(); + + $returnedfromsave = $this->qtype->save_question($questiondata, $fromform); + $actualquestionsdata = question_load_questions(array($returnedfromsave->id)); + $actualquestiondata = end($actualquestionsdata); + + foreach ($questiondata as $property => $value) { + if (!in_array($property, array('id', 'version', 'timemodified', 'timecreated', 'options'))) { + $this->assertAttributeEquals($value, $property, $actualquestiondata); + } + } + + foreach ($questiondata->options as $optionname => $value) { + if ($optionname != 'answers') { + $this->assertAttributeEquals($value, $optionname, $actualquestiondata->options); + } + } + + foreach ($questiondata->options->answers as $answer) { + $actualanswer = array_shift($actualquestiondata->options->answers); + foreach ($answer as $ansproperty => $ansvalue) { + if (!in_array($ansproperty, array('id', 'question', 'answerformat'))) { + $this->assertAttributeEquals($ansvalue, $ansproperty, $actualanswer); + } + } + } + + $datasetloader = new qtype_calculated_dataset_loader($actualquestiondata->id); + + $this->assertEquals(10, $datasetloader->get_number_of_items()); + + for ($itemno = 1; $itemno <= 10; $itemno++) { + $item = $datasetloader->get_values($itemno); + $this->assertEquals($formdata->number[($itemno -1)*2 + 2], $item['a']); + $this->assertEquals($formdata->number[($itemno -1)*2 + 1], $item['b']); + } + } +} diff --git a/question/type/description/tests/helper.php b/question/type/description/tests/helper.php index d571b5d8119..a8c68ff435d 100644 --- a/question/type/description/tests/helper.php +++ b/question/type/description/tests/helper.php @@ -17,9 +17,8 @@ /** * Test helper code for the description question type. * - * @package qtype - * @subpackage description - * @copyright 2010 The Open University + * @package qtype_description + * @copyright 2013 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -30,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); /** * Test helper class for the description question type. * - * @copyright 2010 The Open University + * @copyright 2013 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_description_test_helper extends question_test_helper { @@ -59,11 +58,10 @@ class qtype_description_test_helper extends question_test_helper { } /** - * Get the question data, as it would be loaded by get_question_options, for - * the question returned by {@link make_an_oumultiresponse_two_of_four()}. + * Get the question data, as it would be loaded by get_question_options. * @return object */ - public static function get_question_data() { + public static function get_description_question_data_info() { global $USER; $qdata = new stdClass(); @@ -87,7 +85,28 @@ class qtype_description_test_helper extends question_test_helper { $qdata->length = 0; $qdata->penalty = 0; $qdata->hidden = 0; + $qdata->hints = array(); + $qdata->options = new stdClass(); + $qdata->options->answers = array(); return $qdata; } + + + /** + * Get the question form data. + * @return object + */ + public static function get_description_question_form_data_info() { + $form = new stdClass(); + + $form->name = 'Description'; + $form->questiontext = array('text' => 'Here is some information about the questions you are about to attempt.', + 'format' => FORMAT_HTML); + $form->generalfeedback = array('text' => 'And here is some more text shown only on the review page.', + 'format' => FORMAT_HTML); + + return $form; + } + } diff --git a/question/type/description/tests/questiontype_test.php b/question/type/description/tests/questiontype_test.php index ae97ed8da95..60da13ef1c8 100644 --- a/question/type/description/tests/questiontype_test.php +++ b/question/type/description/tests/questiontype_test.php @@ -17,9 +17,8 @@ /** * Unit tests for the description question type class. * - * @package qtype - * @subpackage description - * @copyright 2010 The Open University + * @package qtype_description + * @copyright 2013 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -28,12 +27,15 @@ defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->dirroot . '/question/type/description/questiontype.php'); +require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); +require_once($CFG->dirroot . '/question/type/edit_question_form.php'); +require_once($CFG->dirroot . '/question/type/description/edit_description_form.php'); /** * Unit tests for the description question type class. * - * @copyright 2010 The Open University + * @copyright 2013 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_description_test extends advanced_testcase { @@ -66,4 +68,35 @@ class qtype_description_test extends advanced_testcase { public function test_get_possible_responses() { $this->assertEquals(array(), $this->qtype->get_possible_responses(null)); } + + + public function test_question_saving() { + $this->resetAfterTest(true); + $this->setAdminUser(); + + $questiondata = test_question_maker::get_question_data('description'); + $formdata = test_question_maker::get_question_form_data('description'); + + $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $cat = $generator->create_question_category(array()); + + $formdata->category = "{$cat->id},{$cat->contextid}"; + qtype_description_edit_form::mock_submit((array)$formdata); + + $form = qtype_description_test_helper::get_question_editing_form($cat, $questiondata); + + $this->assertTrue($form->is_validated()); + + $fromform = $form->get_data(); + + $returnedfromsave = $this->qtype->save_question($questiondata, $fromform); + $actualquestionsdata = question_load_questions(array($returnedfromsave->id)); + $actualquestiondata = end($actualquestionsdata); + + foreach ($questiondata as $property => $value) { + if (!in_array($property, array('id', 'version', 'timemodified', 'timecreated'))) { + $this->assertAttributeEquals($value, $property, $actualquestiondata); + } + } + } } diff --git a/question/type/match/tests/helper.php b/question/type/match/tests/helper.php new file mode 100644 index 00000000000..d69b9eea8be --- /dev/null +++ b/question/type/match/tests/helper.php @@ -0,0 +1,131 @@ +. + +/** + * Test helpers for the match question type. + * + * @package qtype_match + * @copyright 2013 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/question/type/match/question.php'); + + +/** + * Test helper class for the match question type. + * + * @copyright 2013 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_match_test_helper extends question_test_helper { + public function get_test_questions() { + return array('foursubq'); + } + + + /** + * Makes a match question about completing two blanks in some text. + * @return object the question definition data, as it might be returned from + * get_question_options. + */ + public function get_match_question_data_foursubq() { + global $USER; + $q = new stdClass(); + test_question_maker::initialise_question_data($q); + $q->name = 'Matching question'; + $q->qtype = 'match'; + $q->parent = 0; + $q->questiontext = 'Classify the animals.'; + $q->questiontextformat = FORMAT_HTML; + $q->generalfeedback = 'General feedback.'; + $q->generalfeedbackformat = FORMAT_HTML; + $q->defaultmark = 1; + $q->penalty = 0.3333333; + $q->length = 1; + $q->hidden = 0; + $q->createdby = $USER->id; + $q->modifiedby = $USER->id; + + $q->options = new stdClass(); + $q->options->shuffleanswers = 0; + test_question_maker::set_standard_combined_feedback_fields($q->options); + + $q->options->subquestions = array( + 14 => (object) array( + 'id' => 14, + 'questiontext' => 'frog', + 'questiontextformat' => FORMAT_HTML, + 'answertext' => 'amphibian'), + 15 => (object) array( + 'id' => 15, + 'questiontext' => 'cat', + 'questiontextformat' => FORMAT_HTML, + 'answertext' => 'mammal'), + 16 => (object) array( + 'id' => 16, + 'questiontext' => 'newt', + 'questiontextformat' => FORMAT_HTML, + 'answertext' => 'amphibian'), + 17 => (object) array( + 'id' => 17, + 'questiontext' => '', + 'questiontextformat' => FORMAT_HTML, + 'answertext' => 'insect'), + ); + + return $q; + } + + /** + * Makes a match question about completing two blanks in some text. + * @return object the question definition data, as it might be returned from + * the question editing form. + */ + public function get_match_question_form_data_foursubq() { + $q = new stdClass(); + $q->name = 'Matching question'; + $q->questiontext = array('text' => 'Classify the animals.', 'format' => FORMAT_HTML); + $q->generalfeedback = array('text' => 'General feedback.', 'format' => FORMAT_HTML); + $q->defaultmark = 1; + $q->penalty = 0.3333333; + + $q->shuffleanswers = 0; + test_question_maker::set_standard_combined_feedback_form_data($q); + + $q->subquestions = array( + 0 => array('text' => 'frog', 'format' => FORMAT_HTML), + 1 => array('text' => 'cat', 'format' => FORMAT_HTML), + 2 => array('text' => 'newt', 'format' => FORMAT_HTML), + 3 => array('text' => '', 'format' => FORMAT_HTML)); + + $q->subanswers = array( + 0 => 'amphibian', + 1 => 'mammal', + 2 => 'amphibian', + 3 => 'insect' + ); + + $q->noanswers = 4; + + return $q; + } + +} diff --git a/question/type/match/tests/questiontype_test.php b/question/type/match/tests/questiontype_test.php index 4ec6f4e6555..2a8af385245 100644 --- a/question/type/match/tests/questiontype_test.php +++ b/question/type/match/tests/questiontype_test.php @@ -28,6 +28,8 @@ defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); require_once($CFG->dirroot . '/question/type/match/questiontype.php'); +require_once($CFG->dirroot . '/question/type/edit_question_form.php'); +require_once($CFG->dirroot . '/question/type/match/edit_match_form.php'); /** @@ -135,4 +137,53 @@ class qtype_match_test extends advanced_testcase { null => question_possible_response::no_response()), ), $this->qtype->get_possible_responses($q)); } + + + public function test_question_saving_foursubq() { + $this->resetAfterTest(true); + $this->setAdminUser(); + + $questiondata = test_question_maker::get_question_data('match'); + $formdata = test_question_maker::get_question_form_data('match'); + + $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $cat = $generator->create_question_category(array()); + + $formdata->category = "{$cat->id},{$cat->contextid}"; + + qtype_match_edit_form::mock_submit((array)$formdata); + + $form = qtype_match_test_helper::get_question_editing_form($cat, $questiondata); + $this->assertTrue($form->is_validated()); + + $fromform = $form->get_data(); + + $returnedfromsave = $this->qtype->save_question($questiondata, $fromform); + $actualquestionsdata = question_load_questions(array($returnedfromsave->id)); + $actualquestiondata = end($actualquestionsdata); + + foreach ($questiondata as $property => $value) { + if (!in_array($property, array('id', 'version', 'timemodified', 'timecreated', 'options', 'stamp'))) { + $this->assertAttributeEquals($value, $property, $actualquestiondata); + } + } + + foreach ($questiondata->options as $optionname => $value) { + if ($optionname != 'subquestions') { + $this->assertAttributeEquals($value, $optionname, $actualquestiondata->options); + } + } + + $this->assertObjectHasAttribute('subquestions', $actualquestiondata->options); + + $subqpropstoignore = array('id'); + foreach ($questiondata->options->subquestions as $subq) { + $actualsubq = array_shift($actualquestiondata->options->subquestions); + foreach ($subq as $subqproperty => $subqvalue) { + if (!in_array($subqproperty, $subqpropstoignore)) { + $this->assertAttributeEquals($subqvalue, $subqproperty, $actualsubq); + } + } + } + } } diff --git a/question/type/multianswer/tests/helper.php b/question/type/multianswer/tests/helper.php index 743058e7789..92a51e489be 100644 --- a/question/type/multianswer/tests/helper.php +++ b/question/type/multianswer/tests/helper.php @@ -17,9 +17,8 @@ /** * Test helpers for the multianswer question type. * - * @package qtype - * @subpackage multianswer - * @copyright 2011 The Open University + * @package qtype_multianswer + * @copyright 2013 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -33,7 +32,7 @@ require_once($CFG->dirroot . '/question/type/multianswer/question.php'); /** * Test helper class for the multianswer question type. * - * @copyright 2011 The Open University + * @copyright 2013 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_multianswer_test_helper extends question_test_helper { @@ -171,7 +170,7 @@ class qtype_multianswer_test_helper extends question_test_helper { $mc->options->partiallycorrectfeedbackformat = 1; $mc->options->incorrectfeedback = ''; $mc->options->incorrectfeedbackformat = 1; - $mc->options->answernumbering = ''; + $mc->options->answernumbering = 0; $mc->options->shownumcorrect = 0; $mc->options->answers = array( @@ -190,8 +189,8 @@ class qtype_multianswer_test_helper extends question_test_helper { ); $qdata->hints = array( - new question_hint(0, 'Hint 1', FORMAT_HTML), - new question_hint(0, 'Hint 2', FORMAT_HTML), + new question_hint_with_parts(0, 'Hint 1', FORMAT_HTML, 0, 0), + new question_hint_with_parts(0, 'Hint 2', FORMAT_HTML, 0, 0), ); return $qdata; @@ -204,16 +203,14 @@ class qtype_multianswer_test_helper extends question_test_helper { */ public function get_multianswer_question_form_data_twosubq() { $formdata = new stdClass(); - test_question_maker::initialise_question_form_data($formdata); - $formdata->name = 'Simple multianswer'; - $formdata->questiontext = 'Complete this opening line of verse: "The ' . + $formdata->questiontext = array('text' => '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".'; - $formdata->generalfeedback = 'General feedback: It\'s from "The Owl and the Pussy-cat" ' . - 'by Lear: "The owl and the pussycat went to sea'; + ' went to sea".', 'format' => FORMAT_HTML); + $formdata->generalfeedback = array('text' => 'General feedback: It\'s from "The Owl and the Pussy-cat" ' . + 'by Lear: "The owl and the pussycat went to sea', 'format' => FORMAT_HTML); $formdata->hint = array( 0 => array('text' => 'Hint 1', 'format' => FORMAT_HTML, 'itemid' => 0), diff --git a/question/type/multianswer/tests/questiontype_test.php b/question/type/multianswer/tests/questiontype_test.php index 9caffbfd823..241742d96ac 100644 --- a/question/type/multianswer/tests/questiontype_test.php +++ b/question/type/multianswer/tests/questiontype_test.php @@ -29,6 +29,8 @@ defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); require_once($CFG->dirroot . '/question/type/multianswer/questiontype.php'); +require_once($CFG->dirroot . '/question/type/edit_question_form.php'); +require_once($CFG->dirroot . '/question/type/multianswer/edit_multianswer_form.php'); /** @@ -112,4 +114,77 @@ class qtype_multianswer_test extends advanced_testcase { $q = test_question_maker::get_question_data('multianswer', 'twosubq'); $this->assertEquals(0.1666667, $this->qtype->get_random_guess_score($q), '', 0.0000001); } + + public function test_question_saving_twosubq() { + $this->resetAfterTest(true); + $this->setAdminUser(); + + $questiondata = test_question_maker::get_question_data('multianswer'); + $formdata = test_question_maker::get_question_form_data('multianswer'); + + $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $cat = $generator->create_question_category(array()); + + $formdata->category = "{$cat->id},{$cat->contextid}"; + qtype_multianswer_edit_form::mock_submit((array)$formdata); + + $form = qtype_multianswer_test_helper::get_question_editing_form($cat, $questiondata); + + $this->assertTrue($form->is_validated()); + + $fromform = $form->get_data(); + + $returnedfromsave = $this->qtype->save_question($questiondata, $fromform); + $actualquestionsdata = question_load_questions(array($returnedfromsave->id)); + $actualquestiondata = end($actualquestionsdata); + + foreach ($questiondata as $property => $value) { + if (!in_array($property, array('id', 'version', 'timemodified', 'timecreated', 'options', 'hints', 'stamp'))) { + $this->assertAttributeEquals($value, $property, $actualquestiondata); + } + } + + foreach ($questiondata->options as $optionname => $value) { + if ($optionname != 'questions') { + $this->assertAttributeEquals($value, $optionname, $actualquestiondata->options); + } + } + + foreach ($questiondata->hints as $hint) { + $actualhint = array_shift($actualquestiondata->hints); + foreach ($hint as $property => $value) { + if (!in_array($property, array('id', 'questionid', 'options'))) { + $this->assertAttributeEquals($value, $property, $actualhint); + } + } + } + + $this->assertObjectHasAttribute('questions', $actualquestiondata->options); + + $subqpropstoignore = + array('id', 'category', 'parent', 'contextid', 'question', 'options', 'stamp', 'version', 'timemodified', + 'timecreated'); + foreach ($questiondata->options->questions as $subqno => $subq) { + $actualsubq = $actualquestiondata->options->questions[$subqno]; + foreach ($subq as $subqproperty => $subqvalue) { + if (!in_array($subqproperty, $subqpropstoignore)) { + $this->assertAttributeEquals($subqvalue, $subqproperty, $actualsubq); + } + } + foreach ($subq->options as $optionname => $value) { + if (!in_array($optionname, array('answers'))) { + $this->assertAttributeEquals($value, $optionname, $actualsubq->options); + } + } + foreach ($subq->options->answers as $answer) { + $actualanswer = array_shift($actualsubq->options->answers); + foreach ($answer as $ansproperty => $ansvalue) { + // These questions do not use 'answerformat', will ignore it. + if (!in_array($ansproperty, array('id', 'question', 'answerformat'))) { + $this->assertAttributeEquals($ansvalue, $ansproperty, $actualanswer); + } + } + } + } + } } diff --git a/question/type/multichoice/tests/helper.php b/question/type/multichoice/tests/helper.php new file mode 100644 index 00000000000..0746b51a813 --- /dev/null +++ b/question/type/multichoice/tests/helper.php @@ -0,0 +1,219 @@ +. + +/** + * Test helper code for the multiple choice question type. + * + * @package qtype_multichoice + * @copyright 2013 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + + +/** + * Test helper class for the multiple choice question type. + * + * @copyright 2013 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_multichoice_test_helper extends question_test_helper { + public function get_test_questions() { + return array('two_of_four'); + } + + /** + * Get the question data, as it would be loaded by get_question_options. + * @return object + */ + public static function get_multichoice_question_data_two_of_four() { + global $USER; + + $qdata = new stdClass(); + + $qdata->createdby = $USER->id; + $qdata->modifiedby = $USER->id; + $qdata->qtype = 'multichoice'; + $qdata->name = 'Multiple choice question'; + $qdata->questiontext = 'Which are the odd numbers?'; + $qdata->questiontextformat = FORMAT_HTML; + $qdata->generalfeedback = 'The odd numbers are One and Three.'; + $qdata->generalfeedbackformat = FORMAT_HTML; + $qdata->defaultmark = 1; + $qdata->length = 1; + $qdata->penalty = 0.3333333; + $qdata->hidden = 0; + + $qdata->options = new stdClass(); + $qdata->options->shuffleanswers = 1; + $qdata->options->answernumbering = '123'; + $qdata->options->layout = 0; + $qdata->options->single = 0; + $qdata->options->correctfeedback = + test_question_maker::STANDARD_OVERALL_CORRECT_FEEDBACK; + $qdata->options->correctfeedbackformat = FORMAT_HTML; + $qdata->options->partiallycorrectfeedback = + test_question_maker::STANDARD_OVERALL_PARTIALLYCORRECT_FEEDBACK; + $qdata->options->partiallycorrectfeedbackformat = FORMAT_HTML; + $qdata->options->shownumcorrect = 1; + $qdata->options->incorrectfeedback = + test_question_maker::STANDARD_OVERALL_INCORRECT_FEEDBACK; + $qdata->options->incorrectfeedbackformat = FORMAT_HTML; + + $qdata->options->answers = array( + 13 => (object) array( + 'id' => 13, + 'answer' => 'One', + 'answerformat' => FORMAT_PLAIN, + 'fraction' => '0.5', + 'feedback' => 'One is odd.', + 'feedbackformat' => FORMAT_HTML, + ), + 14 => (object) array( + 'id' => 14, + 'answer' => 'Two', + 'answerformat' => FORMAT_PLAIN, + 'fraction' => '0.0', + 'feedback' => 'Two is even.', + 'feedbackformat' => FORMAT_HTML, + ), + 15 => (object) array( + 'id' => 15, + 'answer' => 'Three', + 'answerformat' => FORMAT_PLAIN, + 'fraction' => '0.5', + 'feedback' => 'Three is odd.', + 'feedbackformat' => FORMAT_HTML, + ), + 16 => (object) array( + 'id' => 16, + 'answer' => 'Four', + 'answerformat' => FORMAT_PLAIN, + 'fraction' => '0.0', + 'feedback' => 'Four is even.', + 'feedbackformat' => FORMAT_HTML, + ), + ); + + $qdata->hints = array( + 1 => (object) array( + 'hint' => 'Hint 1.', + 'hintformat' => FORMAT_HTML, + 'shownumcorrect' => 1, + 'clearwrong' => 0, + 'options' => 0, + ), + 2 => (object) array( + 'hint' => 'Hint 2.', + 'hintformat' => FORMAT_HTML, + 'shownumcorrect' => 1, + 'clearwrong' => 1, + 'options' => 1, + ), + ); + + return $qdata; + } + /** + * Get the question data, as it would be loaded by get_question_options. + * @return object + */ + public static function get_multichoice_question_form_data_two_of_four() { + $qdata = new stdClass(); + + $qdata->name = 'multiple choice question'; + $qdata->questiontext = array('text' => 'Which are the odd numbers?', 'format' => FORMAT_HTML); + $qdata->generalfeedback = array('text' => 'The odd numbers are One and Three.', 'format' => FORMAT_HTML); + $qdata->defaultmark = 1; + $qdata->noanswers = 5; + $qdata->numhints = 2; + $qdata->penalty = 0.3333333; + + $qdata->shuffleanswers = 1; + $qdata->answernumbering = '123'; + $qdata->single = '0'; + $qdata->correctfeedback = array('text' => test_question_maker::STANDARD_OVERALL_CORRECT_FEEDBACK, + 'format' => FORMAT_HTML); + $qdata->partiallycorrectfeedback = array('text' => test_question_maker::STANDARD_OVERALL_PARTIALLYCORRECT_FEEDBACK, + 'format' => FORMAT_HTML); + $qdata->shownumcorrect = 1; + $qdata->incorrectfeedback = array('text' => test_question_maker::STANDARD_OVERALL_INCORRECT_FEEDBACK, + 'format' => FORMAT_HTML); + $qdata->fraction = array('0.5', '0.0', '0.5', '0.0', '0.0'); + $qdata->answer = array( + 0 => array( + 'text' => 'One', + 'format' => FORMAT_PLAIN + ), + 1 => array( + 'text' => 'Two', + 'format' => FORMAT_PLAIN + ), + 2 => array( + 'text' => 'Three', + 'format' => FORMAT_PLAIN + ), + 3 => array( + 'text' => 'Four', + 'format' => FORMAT_PLAIN + ), + 4 => array( + 'text' => '', + 'format' => FORMAT_PLAIN + ) + ); + + $qdata->feedback = array( + 0 => array( + 'text' => 'One is odd.', + 'format' => FORMAT_HTML + ), + 1 => array( + 'text' => 'Two is even.', + 'format' => FORMAT_HTML + ), + 2 => array( + 'text' => 'Three is odd.', + 'format' => FORMAT_HTML + ), + 3 => array( + 'text' => 'Four is even.', + 'format' => FORMAT_HTML + ), + 4 => array( + 'text' => '', + 'format' => FORMAT_HTML + ) + ); + + $qdata->hint = array( + 0 => array( + 'text' => 'Hint 1.', + 'format' => FORMAT_HTML + ), + 1 => array( + 'text' => 'Hint 2.', + 'format' => FORMAT_HTML + ) + ); + $qdata->hintclearwrong = array(0, 1); + $qdata->hintshownumcorrect = array(1, 1); + + return $qdata; + } +} diff --git a/question/type/multichoice/tests/questiontype_test.php b/question/type/multichoice/tests/questiontype_test.php index 17e50db7b56..1f1f100f1d0 100644 --- a/question/type/multichoice/tests/questiontype_test.php +++ b/question/type/multichoice/tests/questiontype_test.php @@ -17,9 +17,8 @@ /** * Unit tests for the mulitple choice question definition class. * - * @package qtype - * @subpackage multichoice - * @copyright 2009 The Open University + * @package qtype_multichoice + * @copyright 2013 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -27,8 +26,10 @@ defined('MOODLE_INTERNAL') || die(); global $CFG; +require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); require_once($CFG->dirroot . '/question/type/multichoice/questiontype.php'); - +require_once($CFG->dirroot . '/question/type/edit_question_form.php'); +require_once($CFG->dirroot . '/question/type/multichoice/edit_multichoice_form.php'); /** * Unit tests for the multiple choice question definition class. @@ -100,4 +101,59 @@ class qtype_multichoice_test extends advanced_testcase { 2 => array(2 => new question_possible_response('toad', 0)), ), $this->qtype->get_possible_responses($q)); } + + public function test_question_saving_two_of_four() { + $this->resetAfterTest(true); + $this->setAdminUser(); + + $questiondata = test_question_maker::get_question_data('multichoice'); + $formdata = test_question_maker::get_question_form_data('multichoice'); + + $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $cat = $generator->create_question_category(array()); + + $formdata->category = "{$cat->id},{$cat->contextid}"; + qtype_multichoice_edit_form::mock_submit((array)$formdata); + + $form = qtype_multichoice_test_helper::get_question_editing_form($cat, $questiondata); + + $this->assertTrue($form->is_validated()); + + $fromform = $form->get_data(); + + $returnedfromsave = $this->qtype->save_question($questiondata, $fromform); + $actualquestionsdata = question_load_questions(array($returnedfromsave->id)); + $actualquestiondata = end($actualquestionsdata); + + foreach ($questiondata as $property => $value) { + if (!in_array($property, array('id', 'version', 'timemodified', 'timecreated', 'options', 'hints', 'stamp'))) { + $this->assertAttributeEquals($value, $property, $actualquestiondata); + } + } + + foreach ($questiondata->options as $optionname => $value) { + if (!in_array($optionname, array('answers'))) { + $this->assertAttributeEquals($value, $optionname, $actualquestiondata->options); + } + } + + foreach ($questiondata->hints as $hint) { + $actualhint = array_shift($actualquestiondata->hints); + foreach ($hint as $property => $value) { + if (!in_array($property, array('id', 'questionid', 'options'))) { + $this->assertAttributeEquals($value, $property, $actualhint); + } + } + } + + foreach ($questiondata->options->answers as $answer) { + $actualanswer = array_shift($actualquestiondata->options->answers); + foreach ($answer as $ansproperty => $ansvalue) { + // This question does not use 'answerformat', will ignore it. + if (!in_array($ansproperty, array('id', 'question', 'answerformat'))) { + $this->assertAttributeEquals($ansvalue, $ansproperty, $actualanswer); + } + } + } + } } diff --git a/question/type/numerical/tests/helper.php b/question/type/numerical/tests/helper.php index ffd15bb2329..7157dfb3460 100644 --- a/question/type/numerical/tests/helper.php +++ b/question/type/numerical/tests/helper.php @@ -71,7 +71,155 @@ class qtype_numerical_test_helper extends question_test_helper { return $num; } - /** + public function get_numerical_question_form_data_pi() { + $form = new stdClass(); + $form->name = 'Pi to two d.p.'; + $form->questiontext = array(); + $form->questiontext['format'] = '1'; + $form->questiontext['text'] = 'What is pi to two d.p.?'; + + $form->defaultmark = 1; + $form->generalfeedback = array(); + $form->generalfeedback['format'] = '1'; + $form->generalfeedback['text'] = 'Generalfeedback: 3.14 is the right answer.'; + + $form->noanswers = 6; + $form->answer = array(); + $form->answer[0] = '3.14'; + $form->answer[1] = '3.142'; + $form->answer[2] = '3.1'; + $form->answer[3] = '3'; + $form->answer[4] = '*'; + $form->answer[5] = ''; + + $form->tolerance = array(); + $form->tolerance[0] = 0; + $form->tolerance[1] = 0; + $form->tolerance[2] = 0; + $form->tolerance[3] = 0; + $form->tolerance[4] = 0; + $form->tolerance[5] = 0; + + $form->fraction = array(); + $form->fraction[0] = '1.0'; + $form->fraction[1] = '0.0'; + $form->fraction[2] = '0.0'; + $form->fraction[3] = '0.0'; + $form->fraction[4] = '0.0'; + $form->fraction[5] = '0.0'; + + $form->feedback = array(); + $form->feedback[0] = array(); + $form->feedback[0]['format'] = '1'; + $form->feedback[0]['text'] = 'Very good.'; + + $form->feedback[1] = array(); + $form->feedback[1]['format'] = '1'; + $form->feedback[1]['text'] = 'Too accurate.'; + + $form->feedback[2] = array(); + $form->feedback[2]['format'] = '1'; + $form->feedback[2]['text'] = 'Not accurate enough.'; + + $form->feedback[3] = array(); + $form->feedback[3]['format'] = '1'; + $form->feedback[3]['text'] = 'Not accurate enough.'; + + $form->feedback[4] = array(); + $form->feedback[4]['format'] = '1'; + $form->feedback[4]['text'] = 'Completely wrong.'; + + $form->feedback[5] = array(); + $form->feedback[5]['format'] = '1'; + $form->feedback[5]['text'] = ''; + + $form->unitrole = '3'; + $form->unitpenalty = 0.1; + $form->unitgradingtypes = '1'; + $form->unitsleft = '0'; + $form->nounits = 1; + $form->multiplier = array(); + $form->multiplier[0] = '1.0'; + + $form->penalty = '0.3333333'; + $form->numhints = 2; + $form->hint = array(); + $form->hint[0] = array(); + $form->hint[0]['format'] = '1'; + $form->hint[0]['text'] = ''; + + $form->hint[1] = array(); + $form->hint[1]['format'] = '1'; + $form->hint[1]['text'] = ''; + + $form->qtype = 'numerical'; + return $form; + } + + public function get_numerical_question_data_pi() { + $q = new stdClass(); + $q->name = 'Pi to two d.p.'; + $q->questiontext = 'What is pi to two d.p.?'; + $q->questiontextformat = FORMAT_HTML; + $q->generalfeedback = 'Generalfeedback: 3.14 is the right answer.'; + $q->generalfeedbackformat = FORMAT_HTML; + $q->defaultmark = 1; + $q->penalty = 0.3333333; + $q->qtype = 'numerical'; + $q->length = '1'; + $q->hidden = '0'; + $q->createdby = '2'; + $q->modifiedby = '2'; + $q->options = new stdClass(); + $q->options->answers = array(); + $q->options->answers[0] = new stdClass(); + $q->options->answers[0]->answer = '3.14'; + $q->options->answers[0]->fraction = '1.0000000'; + $q->options->answers[0]->feedback = 'Very good.'; + $q->options->answers[0]->feedbackformat = FORMAT_HTML; + $q->options->answers[0]->tolerance = '0'; + + $q->options->answers[1] = new stdClass(); + $q->options->answers[1]->answer = '3.142'; + $q->options->answers[1]->fraction = '0.0000000'; + $q->options->answers[1]->feedback = 'Too accurate.'; + $q->options->answers[1]->feedbackformat = FORMAT_HTML; + $q->options->answers[1]->tolerance = '0'; + + $q->options->answers[2] = new stdClass(); + $q->options->answers[2]->answer = '3.1'; + $q->options->answers[2]->fraction = '0.0000000'; + $q->options->answers[2]->feedback = 'Not accurate enough.'; + $q->options->answers[2]->feedbackformat = FORMAT_HTML; + $q->options->answers[2]->tolerance = '0'; + + $q->options->answers[3] = new stdClass(); + $q->options->answers[3]->answer = '3'; + $q->options->answers[3]->answerformat = '0'; + $q->options->answers[3]->fraction = '0.0000000'; + $q->options->answers[3]->feedback = 'Not accurate enough.'; + $q->options->answers[3]->feedbackformat = FORMAT_HTML; + $q->options->answers[3]->tolerance = '0'; + + $q->options->answers[4] = new stdClass(); + $q->options->answers[4]->answer = '*'; + $q->options->answers[4]->answerformat = '0'; + $q->options->answers[4]->fraction = '0.0000000'; + $q->options->answers[4]->feedback = 'Completely wrong.'; + $q->options->answers[4]->feedbackformat = FORMAT_HTML; + $q->options->answers[4]->tolerance = '0'; + + $q->options->units = array(); + + $q->options->unitgradingtype = '0'; + $q->options->unitpenalty = '0.1000000'; + $q->options->showunits = '3'; + $q->options->unitsleft = '0'; + + return $q; + } + + /** * Makes a numerical question with a choice (select menu) of units. * @return qtype_numerical_question */ diff --git a/question/type/numerical/tests/questiontype_test.php b/question/type/numerical/tests/questiontype_test.php index d54408ae371..1d19a2fadd9 100644 --- a/question/type/numerical/tests/questiontype_test.php +++ b/question/type/numerical/tests/questiontype_test.php @@ -28,7 +28,9 @@ defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->dirroot . '/question/type/numerical/questiontype.php'); - +require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); +require_once($CFG->dirroot . '/question/type/edit_question_form.php'); +require_once($CFG->dirroot . '/question/type/numerical/edit_numerical_form.php'); /** * Unit tests for question/type/numerical/questiontype.php. @@ -121,4 +123,50 @@ class qtype_numerical_test extends advanced_testcase { ), ), $this->qtype->get_possible_responses($q)); } + + public function test_question_saving_pi() { + $this->resetAfterTest(true); + $this->setAdminUser(); + + $questiondata = test_question_maker::get_question_data('numerical'); + $formdata = test_question_maker::get_question_form_data('numerical'); + + $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $cat = $generator->create_question_category(array()); + + $formdata->category = "{$cat->id},{$cat->contextid}"; + qtype_numerical_edit_form::mock_submit((array)$formdata); + + $form = qtype_numerical_test_helper::get_question_editing_form($cat, $questiondata); + + $this->assertTrue($form->is_validated()); + + $fromform = $form->get_data(); + + $returnedfromsave = $this->qtype->save_question($questiondata, $fromform); + $actualquestionsdata = question_load_questions(array($returnedfromsave->id)); + $actualquestiondata = end($actualquestionsdata); + + foreach ($questiondata as $property => $value) { + if (!in_array($property, array('options'))) { + $this->assertAttributeEquals($value, $property, $actualquestiondata); + } + } + + foreach ($questiondata->options as $optionname => $value) { + if (!in_array($optionname, array('answers'))) { + $this->assertAttributeEquals($value, $optionname, $actualquestiondata->options); + } + } + + foreach ($questiondata->options->answers as $ansindex => $answer) { + $actualanswer = array_shift($actualquestiondata->options->answers); + foreach ($answer as $ansproperty => $ansvalue) { + // This question does not use 'answerformat', will ignore it. + if (!in_array($ansproperty, array('id', 'question', 'answerformat'))) { + $this->assertAttributeEquals($ansvalue, $ansproperty, $actualanswer); + } + } + } + } } diff --git a/question/type/questionbase.php b/question/type/questionbase.php index 452b1a487e5..5b9c7487a4c 100644 --- a/question/type/questionbase.php +++ b/question/type/questionbase.php @@ -768,7 +768,6 @@ class question_answer { * Constructor. * @param int $id the answer. * @param string $answer the answer. - * @param int $answerformat the format of the answer. * @param number $fraction the fraction this answer is worth. * @param string $feedback the feedback for this answer. * @param int $feedbackformat the format of the feedback. @@ -966,4 +965,4 @@ class question_first_matching_answer_grading_strategy implements question_gradin } return null; } -} \ No newline at end of file +} diff --git a/question/type/shortanswer/tests/helper.php b/question/type/shortanswer/tests/helper.php index 40180a7e9e5..08899194224 100644 --- a/question/type/shortanswer/tests/helper.php +++ b/question/type/shortanswer/tests/helper.php @@ -77,7 +77,7 @@ class qtype_shortanswer_test_helper extends question_test_helper { $qdata->generalfeedback = 'Generalfeedback: frog or toad would have been OK.'; $qdata->options = new stdClass(); - $qdata->options->usecase = false; + $qdata->options->usecase = 0; $qdata->options->answers = array( 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), @@ -88,29 +88,28 @@ class qtype_shortanswer_test_helper extends question_test_helper { } /** - * Gets the question data for a shortanswer question with with correct - * ansewer 'frog', partially correct answer 'toad' and defaultmark 1. + * Gets the question form data for a shortanswer question with with correct + * answer 'frog', partially correct answer 'toad' and defaultmark 1. * This question also has a '*' match anything answer. * @return stdClass */ public function get_shortanswer_question_form_data_frogtoad() { - $fromform = new stdClass(); - test_question_maker::initialise_question_form_data($fromform); + $form = new stdClass(); - $fromform->qtype = 'shortanswer'; - $fromform->name = 'Short answer question'; - $fromform->questiontext = array('text' => 'Name an amphibian: __________', 'format' => FORMAT_HTML); - $fromform->generalfeedback = array('text' => 'Generalfeedback: frog or toad would have been OK.', 'format' => FORMAT_HTML); - $fromform->usecase = false; - $fromform->answer = array('frog', 'toad', '*'); - $fromform->fraction = array(1.0, 0.8, 0.0); - $fromform->feedback = array( + $form->name = 'Short answer question'; + $form->questiontext = array('text' => 'Name an amphibian: __________', 'format' => FORMAT_HTML); + $form->defaultmark = 1.0; + $form->generalfeedback = array('text' => 'Generalfeedback: frog or toad would have been OK.', 'format' => FORMAT_HTML); + $form->usecase = false; + $form->answer = array('frog', 'toad', '*'); + $form->fraction = array('1.0', '0.8', '0.0'); + $form->feedback = array( array('text' => 'Frog is a very good answer.', 'format' => FORMAT_HTML), array('text' => 'Toad is an OK good answer.', 'format' => FORMAT_HTML), array('text' => 'That is a bad answer.', 'format' => FORMAT_HTML), ); - return $fromform; + return $form; } /** diff --git a/question/type/shortanswer/tests/questiontype_test.php b/question/type/shortanswer/tests/questiontype_test.php index 512b6353c63..91d2bcd420c 100644 --- a/question/type/shortanswer/tests/questiontype_test.php +++ b/question/type/shortanswer/tests/questiontype_test.php @@ -17,9 +17,8 @@ /** * Unit tests for the shortanswer question type class. * - * @package qtype - * @subpackage shortanswer - * @copyright 2007 The Open University + * @package qtype_shortanswer + * @copyright 2013 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -29,7 +28,8 @@ defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->dirroot . '/question/type/shortanswer/questiontype.php'); require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); - +require_once($CFG->dirroot . '/question/type/edit_question_form.php'); +require_once($CFG->dirroot . '/question/type/shortanswer/edit_shortanswer_form.php'); /** * Unit tests for the shortanswer question type class. @@ -95,4 +95,50 @@ class qtype_shortanswer_test extends advanced_testcase { ), ), $this->qtype->get_possible_responses($q)); } + + public function test_question_saving_frogtoad() { + $this->resetAfterTest(true); + $this->setAdminUser(); + + $questiondata = test_question_maker::get_question_data('shortanswer'); + $formdata = test_question_maker::get_question_form_data('shortanswer'); + + $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $cat = $generator->create_question_category(array()); + + $formdata->category = "{$cat->id},{$cat->contextid}"; + qtype_shortanswer_edit_form::mock_submit((array)$formdata); + + $form = qtype_shortanswer_test_helper::get_question_editing_form($cat, $questiondata); + + $this->assertTrue($form->is_validated()); + + $fromform = $form->get_data(); + + $returnedfromsave = $this->qtype->save_question($questiondata, $fromform); + $actualquestionsdata = question_load_questions(array($returnedfromsave->id)); + $actualquestiondata = end($actualquestionsdata); + + foreach ($questiondata as $property => $value) { + if (!in_array($property, array('id', 'version', 'timemodified', 'timecreated', 'options'))) { + $this->assertAttributeEquals($value, $property, $actualquestiondata); + } + } + + foreach ($questiondata->options as $optionname => $value) { + if ($optionname != 'answers') { + $this->assertAttributeEquals($value, $optionname, $actualquestiondata->options); + } + } + + foreach ($questiondata->options->answers as $answer) { + $actualanswer = array_shift($actualquestiondata->options->answers); + foreach ($answer as $ansproperty => $ansvalue) { + // This question does not use 'answerformat', will ignore it. + if (!in_array($ansproperty, array('id', 'question', 'answerformat'))) { + $this->assertAttributeEquals($ansvalue, $ansproperty, $actualanswer); + } + } + } + } } diff --git a/question/type/truefalse/tests/helper.php b/question/type/truefalse/tests/helper.php index 1ee7e8e947a..359ade0b9ee 100644 --- a/question/type/truefalse/tests/helper.php +++ b/question/type/truefalse/tests/helper.php @@ -63,6 +63,67 @@ class qtype_truefalse_test_helper extends question_test_helper { return $tf; } + public function get_truefalse_question_form_data_true() { + + $form = new stdClass(); + $form->name = 'True/false question'; + $form->questiontext = array(); + $form->questiontext['format'] = '1'; + $form->questiontext['text'] = 'The answer is true.'; + + $form->defaultmark = 1; + $form->generalfeedback = array(); + $form->generalfeedback['format'] = '1'; + $form->generalfeedback['text'] = 'You should have selected true.'; + + $form->correctanswer = '1'; + $form->feedbacktrue = array(); + $form->feedbacktrue['format'] = '1'; + $form->feedbacktrue['text'] = 'This is the right answer.'; + + $form->feedbackfalse = array(); + $form->feedbackfalse['format'] = '1'; + $form->feedbackfalse['text'] = 'This is the wrong answer.'; + + $form->penalty = 1; + + return $form; + } + + function get_truefalse_question_data_true() { + + $q = new stdClass(); + $q->name = 'True/false question'; + $q->questiontext = 'The answer is true.'; + $q->questiontextformat = FORMAT_HTML; + $q->generalfeedback = 'You should have selected true.'; + $q->generalfeedbackformat = FORMAT_HTML; + $q->defaultmark = 1; + $q->penalty = 1; + $q->qtype = 'truefalse'; + $q->length = '1'; + $q->hidden = '0'; + $q->createdby = '2'; + $q->modifiedby = '2'; + $q->options = new stdClass(); + $q->options->trueanswer = '0'; + $q->options->falseanswer = '1'; + $q->options->answers = array(); + $q->options->answers[0] = new stdClass(); + $q->options->answers[0]->answer = 'True'; + $q->options->answers[0]->fraction = '1.0000000'; + $q->options->answers[0]->feedback = 'This is the right answer.'; + $q->options->answers[0]->feedbackformat = FORMAT_HTML; + + $q->options->answers[1] = new stdClass(); + $q->options->answers[1]->answer = 'False'; + $q->options->answers[1]->fraction = '0.0000000'; + $q->options->answers[1]->feedback = 'This is the wrong answer.'; + $q->options->answers[1]->feedbackformat = FORMAT_HTML; + + return $q; + } + /** * Makes a truefalse question with correct answer false. * @return qtype_truefalse_question diff --git a/question/type/truefalse/tests/questiontype_test.php b/question/type/truefalse/tests/questiontype_test.php index 57f699936db..824f256171b 100644 --- a/question/type/truefalse/tests/questiontype_test.php +++ b/question/type/truefalse/tests/questiontype_test.php @@ -28,7 +28,9 @@ defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->dirroot . '/question/type/truefalse/questiontype.php'); - +require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); +require_once($CFG->dirroot . '/question/type/edit_question_form.php'); +require_once($CFG->dirroot . '/question/type/truefalse/edit_truefalse_form.php'); /** * Unit tests for the true-false question definition class. @@ -75,4 +77,55 @@ class qtype_truefalse_test extends advanced_testcase { null => question_possible_response::no_response()), ), $this->qtype->get_possible_responses($q)); } + + public function test_question_saving_true() { + $this->resetAfterTest(true); + $this->setAdminUser(); + + $questiondata = test_question_maker::get_question_data('truefalse'); + $formdata = test_question_maker::get_question_form_data('truefalse'); + + $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $cat = $generator->create_question_category(array()); + + $formdata->category = "{$cat->id},{$cat->contextid}"; + qtype_truefalse_edit_form::mock_submit((array)$formdata); + + $form = qtype_truefalse_test_helper::get_question_editing_form($cat, $questiondata); + + $this->assertTrue($form->is_validated()); + + $fromform = $form->get_data(); + + $returnedfromsave = $this->qtype->save_question($questiondata, $fromform); + $actualquestionsdata = question_load_questions(array($returnedfromsave->id)); + $actualquestiondata = end($actualquestionsdata); + + foreach ($questiondata as $property => $value) { + if (!in_array($property, array('options'))) { + $this->assertAttributeEquals($value, $property, $actualquestiondata); + } + } + + foreach ($questiondata->options as $optionname => $value) { + if (!in_array($optionname, array('trueanswer', 'falseanswer', 'answers'))) { + $this->assertAttributeEquals($value, $optionname, $actualquestiondata->options); + } + } + + $answerindexes = array(); + foreach ($questiondata->options->answers as $ansindex => $answer) { + $actualanswer = array_shift($actualquestiondata->options->answers); + foreach ($answer as $ansproperty => $ansvalue) { + // This question does not use 'answerformat', will ignore it. + if (!in_array($ansproperty, array('id', 'question', 'answerformat'))) { + $this->assertAttributeEquals($ansvalue, $ansproperty, $actualanswer); + } + } + $answerindexes[$answer->answer] = $ansindex; + } + + $this->assertEquals($questiondata->options->trueanswer, $answerindexes['True']); + $this->assertEquals($questiondata->options->falseanswer, $answerindexes['False']); + } }