diff --git a/question/type/multianswer/questiontype.php b/question/type/multianswer/questiontype.php index 52ca37d5f13..e8594d1547d 100644 --- a/question/type/multianswer/questiontype.php +++ b/question/type/multianswer/questiontype.php @@ -314,11 +314,18 @@ class qtype_multianswer extends question_type { $fractionsum = 0; $fractionmax = 0; foreach ($questiondata->options->questions as $key => $subqdata) { + if ($subqdata->qtype == 'subquestion_replacement') { + continue; + } $fractionmax += $subqdata->defaultmark; $fractionsum += question_bank::get_qtype( $subqdata->qtype)->get_random_guess_score($subqdata); } - return $fractionsum / $fractionmax; + if ($fractionmax > question_utils::MARK_TOLERANCE) { + return $fractionsum / $fractionmax; + } else { + return null; + } } public function move_files($questionid, $oldcontextid, $newcontextid) { diff --git a/question/type/multianswer/tests/question_type_test.php b/question/type/multianswer/tests/question_type_test.php index d36a13e85a4..fe36a8b0a3a 100644 --- a/question/type/multianswer/tests/question_type_test.php +++ b/question/type/multianswer/tests/question_type_test.php @@ -34,9 +34,10 @@ require_once($CFG->dirroot . '/question/type/multianswer/edit_multianswer_form.p /** * Unit tests for the multianswer question definition class. * - * @package qtype_multianswer - * @copyright 2011 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype_multianswer + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @covers \qtype_multianswer */ class question_type_test extends \advanced_testcase { /** @var qtype_multianswer instance of the question type class to test. */ @@ -112,15 +113,46 @@ class question_type_test extends \advanced_testcase { } public function test_get_random_guess_score() { - $q = \test_question_maker::get_question_data('multianswer', 'twosubq'); + $q = test_question_maker::get_question_data('multianswer', 'twosubq'); $this->assertEqualsWithDelta(0.1666667, $this->qtype->get_random_guess_score($q), 0.0000001); } + public function test_get_random_guess_score_with_missing_subquestion() { + global $DB; + $this->resetAfterTest(); + + // Create a question referring to a subquesion that has got lost (which happens some time). + /** @var \core_question_generator $generator */ + $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $category = $generator->create_question_category(); + $question = $generator->create_question('multianswer', 'twosubq', ['category' => $category->id]); + // Add a non-existent subquestion id to the list. + $sequence = $DB->get_field('question_multianswer', 'sequence', ['question' => $question->id], MUST_EXIST); + $DB->set_field('question_multianswer', 'sequence', $sequence . ',-1', ['question' => $question->id]); + + // Verify that computing the random guess score does not give an error. + $questiondata = question_bank::load_question_data($question->id); + $this->assertEqualsWithDelta(0.1666667, $this->qtype->get_random_guess_score($questiondata), 0.0000001); + } + + public function test_get_random_guess_score_with_all_missing_subquestions() { + $this->resetAfterTest(); + + // Create a question where all subquestions are missing. + $questiondata = test_question_maker::get_question_data('multianswer', 'twosubq'); + foreach ($questiondata->options->questions as $subq) { + $subq->qtype = 'subquestion_replacement'; + } + + // Verify that computing the random guess score does not give an error. + $this->assertNull($this->qtype->get_random_guess_score($questiondata)); + } + public function test_load_question() { $this->resetAfterTest(); $syscontext = \context_system::instance(); - /** @var core_question_generator $generator */ + /** @var \core_question_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); $category = $generator->create_question_category(['contextid' => $syscontext->id]);