Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace qtype_multianswer; 18 19 use question_attempt_step; 20 use question_display_options; 21 use question_state; 22 use question_testcase; 23 24 defined('MOODLE_INTERNAL') || die(); 25 26 global $CFG; 27 require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); 28 29 30 /** 31 * Unit tests for qtype_multianswer_question. 32 * 33 * @package qtype_multianswer 34 * @copyright 2011 The Open University 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 */ 37 class question_test extends \advanced_testcase { 38 public function test_get_expected_data() { 39 $question = \test_question_maker::make_question('multianswer'); 40 $this->assertEquals(array('sub1_answer' => PARAM_RAW_TRIMMED, 41 'sub2_answer' => PARAM_RAW), $question->get_expected_data()); 42 } 43 44 public function test_is_complete_response() { 45 $question = \test_question_maker::make_question('multianswer'); 46 47 $this->assertFalse($question->is_complete_response(array())); 48 $this->assertTrue($question->is_complete_response(array('sub1_answer' => 'Owl', 49 'sub2_answer' => '2'))); 50 $this->assertTrue($question->is_complete_response(array('sub1_answer' => '0', 51 'sub2_answer' => 0))); 52 $this->assertFalse($question->is_complete_response(array('sub1_answer' => 'Owl'))); 53 } 54 55 public function test_is_gradable_response() { 56 $question = \test_question_maker::make_question('multianswer'); 57 58 $this->assertFalse($question->is_gradable_response(array())); 59 $this->assertTrue($question->is_gradable_response(array('sub1_answer' => 'Owl', 60 'sub2_answer' => '2'))); 61 $this->assertTrue($question->is_gradable_response(array('sub1_answer' => '0', 62 'sub2_answer' => 0))); 63 $this->assertTrue($question->is_gradable_response(array('sub1_answer' => 'Owl'))); 64 } 65 66 public function test_grading() { 67 $question = \test_question_maker::make_question('multianswer'); 68 $question->start_attempt(new question_attempt_step(), 1); 69 70 $rightchoice = $question->subquestions[2]->get_correct_response(); 71 72 $this->assertEquals(array(1, question_state::$gradedright), $question->grade_response( 73 array('sub1_answer' => 'Owl', 'sub2_answer' => reset($rightchoice)))); 74 $this->assertEquals(array(0.5, question_state::$gradedpartial), $question->grade_response( 75 array('sub1_answer' => 'Owl'))); 76 $this->assertEquals(array(0.5, question_state::$gradedpartial), $question->grade_response( 77 array('sub1_answer' => 'Goat', 'sub2_answer' => reset($rightchoice)))); 78 $this->assertEquals(array(0, question_state::$gradedwrong), $question->grade_response( 79 array('sub1_answer' => 'Dog'))); 80 } 81 82 public function test_get_correct_response() { 83 $question = \test_question_maker::make_question('multianswer'); 84 $question->start_attempt(new question_attempt_step(), 1); 85 86 $rightchoice = $question->subquestions[2]->get_correct_response(); 87 88 $this->assertEquals(array('sub1_answer' => 'Owl', 'sub2_answer' => reset($rightchoice)), 89 $question->get_correct_response()); 90 } 91 92 public function test_get_question_summary() { 93 $question = \test_question_maker::make_question('multianswer'); 94 95 // Bit of a hack to make testing easier. 96 $question->subquestions[2]->shuffleanswers = false; 97 98 $question->start_attempt(new question_attempt_step(), 1); 99 100 $qsummary = $question->get_question_summary(); 101 $this->assertEquals('Complete this opening line of verse: "The _____ and the ' . 102 '{Bow-wow; Wiggly worm; Pussy-cat} went to sea".', $qsummary); 103 } 104 105 public function test_summarise_response() { 106 $question = \test_question_maker::make_question('multianswer'); 107 $question->start_attempt(new question_attempt_step(), 1); 108 109 $rightchoice = $question->subquestions[2]->get_correct_response(); 110 111 $this->assertEquals(get_string('subqresponse', 'qtype_multianswer', 112 array('i' => 1, 'response' => 'Owl')) . '; ' . 113 get_string('subqresponse', 'qtype_multianswer', 114 array('i' => 2, 'response' => 'Pussy-cat')), $question->summarise_response( 115 array('sub1_answer' => 'Owl', 'sub2_answer' => reset($rightchoice)))); 116 } 117 118 public function test_get_num_parts_right() { 119 $question = \test_question_maker::make_question('multianswer'); 120 $question->start_attempt(new question_attempt_step(), 1); 121 122 $rightchoice = $question->subquestions[2]->get_correct_response(); 123 $right = reset($rightchoice); 124 125 $response = array('sub1_answer' => 'Frog', 'sub2_answer' => $right); 126 list($numpartsright, $numparts) = $question->get_num_parts_right($response); 127 $this->assertEquals(1, $numpartsright); 128 $this->assertEquals(2, $numparts); 129 $response = array('sub1_answer' => 'Owl', 'sub2_answer' => $right); 130 list($numpartsright, $numparts) = $question->get_num_parts_right($response); 131 $this->assertEquals(2, $numpartsright); 132 $response = array('sub1_answer' => 'Dog', 'sub2_answer' => 3); 133 list($numpartsright, $numparts) = $question->get_num_parts_right($response); 134 $this->assertEquals(0, $numpartsright); 135 $response = array('sub1_answer' => 'Owl'); 136 list($numpartsright, $numparts) = $question->get_num_parts_right($response); 137 $this->assertEquals(1, $numpartsright); 138 $response = array('sub1_answer' => 'Dog'); 139 list($numpartsright, $numparts) = $question->get_num_parts_right($response); 140 $this->assertEquals(0, $numpartsright); 141 $response = array('sub2_answer' => $right); 142 list($numpartsright, $numparts) = $question->get_num_parts_right($response); 143 $this->assertEquals(1, $numpartsright); 144 } 145 146 public function test_get_num_parts_right_fourmc() { 147 // Create a multianswer question with four mcq. 148 $question = \test_question_maker::make_question('multianswer', 'fourmc'); 149 $question->start_attempt(new question_attempt_step(), 1); 150 151 $response = array('sub1_answer' => '1', 'sub2_answer' => '1', 152 'sub3_answer' => '1', 'sub4_answer' => '1'); 153 list($numpartsright, $numparts) = $question->get_num_parts_right($response); 154 $this->assertEquals(2, $numpartsright); 155 } 156 157 public function test_clear_wrong_from_response() { 158 $question = \test_question_maker::make_question('multianswer'); 159 $question->start_attempt(new question_attempt_step(), 1); 160 161 $rightchoice = $question->subquestions[2]->get_correct_response(); 162 $right = reset($rightchoice); 163 164 $response = array('sub1_answer' => 'Frog', 'sub2_answer' => $right); 165 $this->assertEquals($question->clear_wrong_from_response($response), 166 array('sub1_answer' => '', 'sub2_answer' => $right)); 167 $response = array('sub1_answer' => 'Owl', 'sub2_answer' => $right); 168 $this->assertEquals($question->clear_wrong_from_response($response), 169 array('sub1_answer' => 'Owl', 'sub2_answer' => $right)); 170 $response = array('sub1_answer' => 'Dog', 'sub2_answer' => 3); 171 $this->assertEquals($question->clear_wrong_from_response($response), 172 array('sub1_answer' => '', 'sub2_answer' => '')); 173 $response = array('sub1_answer' => 'Owl'); 174 $this->assertEquals($question->clear_wrong_from_response($response), 175 array('sub1_answer' => 'Owl')); 176 $response = array('sub2_answer' => $right); 177 $this->assertEquals($question->clear_wrong_from_response($response), 178 array('sub2_answer' => $right)); 179 } 180 181 public function test_compute_final_grade() { 182 $question = \test_question_maker::make_question('multianswer'); 183 // Set penalty to 0.2 to ease calculations. 184 $question->penalty = 0.2; 185 // Set subquestion 2 defaultmark to 2, to make it a better test, 186 // even thought (at the moment) that never happens for real. 187 $question->subquestions[2]->defaultmark = 2; 188 189 $question->start_attempt(new question_attempt_step(), 1); 190 191 // Compute right and wrong response for subquestion 2. 192 $rightchoice = $question->subquestions[2]->get_correct_response(); 193 $right = reset($rightchoice); 194 $wrong = ($right + 1) % 3; 195 196 // Get subquestion 1 right at 2nd try and subquestion 2 right at 3rd try. 197 $responses = array(0 => array('sub1_answer' => 'Dog', 'sub2_answer' => $wrong), 198 1 => array('sub1_answer' => 'Owl', 'sub2_answer' => $wrong), 199 2 => array('sub1_answer' => 'Owl', 'sub2_answer' => $right), 200 ); 201 $finalgrade = $question->compute_final_grade($responses, 1); 202 $this->assertEqualsWithDelta(1 / 3 * (1 - 0.2) + 2 / 3 * (1 - 2 * 0.2), $finalgrade, question_testcase::GRADE_DELTA); 203 204 // Get subquestion 1 right at 3rd try and subquestion 2 right at 2nd try. 205 $responses = array(0 => array('sub1_answer' => 'Dog', 'sub2_answer' => $wrong), 206 1 => array('sub1_answer' => 'Cat', 'sub2_answer' => $right), 207 2 => array('sub1_answer' => 'Owl', 'sub2_answer' => $right), 208 3 => array('sub1_answer' => 'Owl', 'sub2_answer' => $right), 209 ); 210 $finalgrade = $question->compute_final_grade($responses, 1); 211 $this->assertEqualsWithDelta(1 / 3 * (1 - 2 * 0.2) + 2 / 3 * (1 - 0.2), $finalgrade, question_testcase::GRADE_DELTA); 212 213 // Get subquestion 1 right at 4th try and subquestion 2 right at 1st try. 214 $responses = array(0 => array('sub1_answer' => 'Dog', 'sub2_answer' => $right), 215 1 => array('sub1_answer' => 'Dog', 'sub2_answer' => $right), 216 2 => array('sub1_answer' => 'Dog', 'sub2_answer' => $right), 217 3 => array('sub1_answer' => 'Owl', 'sub2_answer' => $right), 218 ); 219 $finalgrade = $question->compute_final_grade($responses, 1); 220 $this->assertEqualsWithDelta(1 / 3 * (1 - 3 * 0.2) + 2 / 3, $finalgrade, question_testcase::GRADE_DELTA); 221 222 // Get subquestion 1 right at 4th try and subquestion 2 right 3rd try. 223 // Subquestion 2 was right at 1st try, but last change is at 3rd try. 224 $responses = array(0 => array('sub1_answer' => 'Dog', 'sub2_answer' => $right), 225 1 => array('sub1_answer' => 'Cat', 'sub2_answer' => $wrong), 226 2 => array('sub1_answer' => 'Frog', 'sub2_answer' => $right), 227 3 => array('sub1_answer' => 'Owl', 'sub2_answer' => $right), 228 ); 229 $finalgrade = $question->compute_final_grade($responses, 1); 230 $this->assertEqualsWithDelta(1 / 3 * (1 - 3 * 0.2) + 2 / 3 * (1 - 2 * 0.2), $finalgrade, question_testcase::GRADE_DELTA); 231 232 // Incomplete responses. Subquestion 1 is right at 4th try and subquestion 2 at 3rd try. 233 $responses = array(0 => array('sub1_answer' => 'Dog'), 234 1 => array('sub1_answer' => 'Cat'), 235 2 => array('sub1_answer' => 'Frog', 'sub2_answer' => $right), 236 3 => array('sub1_answer' => 'Owl', 'sub2_answer' => $right), 237 ); 238 $finalgrade = $question->compute_final_grade($responses, 1); 239 $this->assertEqualsWithDelta(1 / 3 * (1 - 3 * 0.2) + 2 / 3 * (1 - 2 * 0.2), $finalgrade, question_testcase::GRADE_DELTA); 240 } 241 242 /** 243 * test_get_question_definition_for_external_rendering 244 */ 245 public function test_get_question_definition_for_external_rendering() { 246 $this->resetAfterTest(); 247 248 $question = \test_question_maker::make_question('multianswer'); 249 $question->start_attempt(new question_attempt_step(), 1); 250 $qa = \test_question_maker::get_a_qa($question); 251 $displayoptions = new question_display_options(); 252 253 $options = $question->get_question_definition_for_external_rendering($qa, $displayoptions); 254 $this->assertNull($options); 255 } 256 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body