[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 /** 18 * Unit tests for the parts of {@link question_engine_data_mapper} related to reporting. 19 * 20 * @package core_question 21 * @category test 22 * @copyright 2013 The Open University 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 global $CFG; 30 require_once (__DIR__ . '/../lib.php'); 31 require_once (__DIR__ . '/helpers.php'); 32 33 34 /** 35 * Unit tests for the parts of {@link question_engine_data_mapper} related to reporting. 36 * 37 * @copyright 2013 The Open University 38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 39 */ 40 class question_engine_data_mapper_reporting_testcase extends qbehaviour_walkthrough_test_base { 41 42 /** @var question_engine_data_mapper */ 43 protected $dm; 44 45 /** @var qtype_shortanswer_question */ 46 protected $sa; 47 48 /** @var qtype_essay_question */ 49 protected $essay; 50 51 /** @var array */ 52 protected $usageids = array(); 53 54 /** @var qubaid_condition */ 55 protected $bothusages; 56 57 /** @var array */ 58 protected $allslots = array(); 59 60 /** 61 * Test the various methods that load data for reporting. 62 * 63 * Since these methods need an expensive set-up, and then only do read-only 64 * operations on the data, we use a single method to do the set-up, which 65 * calls diffents methods to test each query. 66 */ 67 public function test_reporting_queries() { 68 // We create two usages, each with two questions, a short-answer marked 69 // out of 5, and and essay marked out of 10. 70 // 71 // In the first usage, the student answers the short-answer 72 // question correctly, and enters something in the essay. 73 // 74 // In the second useage, the student answers the short-answer question 75 // wrongly, and leaves the essay blank. 76 $this->resetAfterTest(); 77 $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); 78 $cat = $generator->create_question_category(); 79 $this->sa = $generator->create_question('shortanswer', null, 80 array('category' => $cat->id)); 81 $this->essay = $generator->create_question('essay', null, 82 array('category' => $cat->id)); 83 84 $this->usageids = array(); 85 86 // Create the first usage. 87 $q = question_bank::load_question($this->sa->id); 88 $this->start_attempt_at_question($q, 'interactive', 5); 89 $this->allslots[] = $this->slot; 90 $this->process_submission(array('answer' => 'cat')); 91 $this->process_submission(array('answer' => 'frog', '-submit' => 1)); 92 93 $q = question_bank::load_question($this->essay->id); 94 $this->start_attempt_at_question($q, 'interactive', 10); 95 $this->allslots[] = $this->slot; 96 $this->process_submission(array('answer' => '<p>The cat sat on the mat.</p>', 'answerformat' => FORMAT_HTML)); 97 98 $this->finish(); 99 $this->save_quba(); 100 $this->usageids[] = $this->quba->get_id(); 101 102 // Create the second usage. 103 $this->quba = question_engine::make_questions_usage_by_activity('unit_test', 104 context_system::instance()); 105 106 $q = question_bank::load_question($this->sa->id); 107 $this->start_attempt_at_question($q, 'interactive', 5); 108 $this->process_submission(array('answer' => 'fish')); 109 110 $q = question_bank::load_question($this->essay->id); 111 $this->start_attempt_at_question($q, 'interactive', 10); 112 113 $this->finish(); 114 $this->save_quba(); 115 $this->usageids[] = $this->quba->get_id(); 116 117 // Set up some things the tests will need. 118 $this->dm = new question_engine_data_mapper(); 119 $this->bothusages = new qubaid_list($this->usageids); 120 121 // Now test the various queries. 122 $this->dotest_load_questions_usages_latest_steps(); 123 $this->dotest_load_questions_usages_question_state_summary(); 124 $this->dotest_load_questions_usages_where_question_in_state(); 125 $this->dotest_load_average_marks(); 126 $this->dotest_sum_usage_marks_subquery(); 127 $this->dotest_question_attempt_latest_state_view(); 128 } 129 130 /** 131 * This test is executed by {@link test_reporting_queries()}. 132 */ 133 protected function dotest_load_questions_usages_latest_steps() { 134 $rawstates = $this->dm->load_questions_usages_latest_steps($this->bothusages, $this->allslots, 135 'qa.id AS questionattemptid, qa.questionusageid, qa.slot, ' . 136 'qa.questionid, qa.maxmark, qas.sequencenumber, qas.state'); 137 138 $states = array(); 139 foreach ($rawstates as $state) { 140 $states[$state->questionusageid][$state->slot] = $state; 141 unset($state->questionattemptid); 142 unset($state->questionusageid); 143 unset($state->slot); 144 } 145 146 $state = $states[$this->usageids[0]][$this->allslots[0]]; 147 $this->assertEquals((object) array( 148 'questionid' => $this->sa->id, 149 'maxmark' => '5.0000000', 150 'sequencenumber' => 2, 151 'state' => (string) question_state::$gradedright, 152 ), $state); 153 154 $state = $states[$this->usageids[0]][$this->allslots[1]]; 155 $this->assertEquals((object) array( 156 'questionid' => $this->essay->id, 157 'maxmark' => '10.0000000', 158 'sequencenumber' => 2, 159 'state' => (string) question_state::$needsgrading, 160 ), $state); 161 162 $state = $states[$this->usageids[1]][$this->allslots[0]]; 163 $this->assertEquals((object) array( 164 'questionid' => $this->sa->id, 165 'maxmark' => '5.0000000', 166 'sequencenumber' => 2, 167 'state' => (string) question_state::$gradedwrong, 168 ), $state); 169 170 $state = $states[$this->usageids[1]][$this->allslots[1]]; 171 $this->assertEquals((object) array( 172 'questionid' => $this->essay->id, 173 'maxmark' => '10.0000000', 174 'sequencenumber' => 1, 175 'state' => (string) question_state::$gaveup, 176 ), $state); 177 } 178 179 /** 180 * This test is executed by {@link test_reporting_queries()}. 181 */ 182 protected function dotest_load_questions_usages_question_state_summary() { 183 $summary = $this->dm->load_questions_usages_question_state_summary( 184 $this->bothusages, $this->allslots); 185 186 $this->assertEquals($summary[$this->allslots[0] . ',' . $this->sa->id], 187 (object) array( 188 'slot' => $this->allslots[0], 189 'questionid' => $this->sa->id, 190 'name' => $this->sa->name, 191 'inprogress' => 0, 192 'needsgrading' => 0, 193 'autograded' => 2, 194 'manuallygraded' => 0, 195 'all' => 2, 196 )); 197 $this->assertEquals($summary[$this->allslots[1] . ',' . $this->essay->id], 198 (object) array( 199 'slot' => $this->allslots[1], 200 'questionid' => $this->essay->id, 201 'name' => $this->essay->name, 202 'inprogress' => 0, 203 'needsgrading' => 1, 204 'autograded' => 1, 205 'manuallygraded' => 0, 206 'all' => 2, 207 )); 208 } 209 210 /** 211 * This test is executed by {@link test_reporting_queries()}. 212 */ 213 protected function dotest_load_questions_usages_where_question_in_state() { 214 $this->assertEquals( 215 array(array($this->usageids[0], $this->usageids[1]), 2), 216 $this->dm->load_questions_usages_where_question_in_state($this->bothusages, 217 'all', $this->allslots[1], null, 'questionusageid')); 218 219 $this->assertEquals( 220 array(array($this->usageids[0], $this->usageids[1]), 2), 221 $this->dm->load_questions_usages_where_question_in_state($this->bothusages, 222 'autograded', $this->allslots[0], null, 'questionusageid')); 223 224 $this->assertEquals( 225 array(array($this->usageids[0]), 1), 226 $this->dm->load_questions_usages_where_question_in_state($this->bothusages, 227 'needsgrading', $this->allslots[1], null, 'questionusageid')); 228 } 229 230 /** 231 * This test is executed by {@link test_reporting_queries()}. 232 */ 233 protected function dotest_load_average_marks() { 234 $averages = $this->dm->load_average_marks($this->bothusages); 235 236 $this->assertEquals(array( 237 $this->allslots[0] => (object) array( 238 'slot' => $this->allslots[0], 239 'averagefraction' => 0.5, 240 'numaveraged' => 2, 241 ), 242 $this->allslots[1] => (object) array( 243 'slot' => $this->allslots[1], 244 'averagefraction' => 0, 245 'numaveraged' => 1, 246 ), 247 ), $averages); 248 } 249 250 /** 251 * This test is executed by {@link test_reporting_queries()}. 252 */ 253 protected function dotest_sum_usage_marks_subquery() { 254 global $DB; 255 256 $totals = $DB->get_records_sql_menu("SELECT qu.id, ({$this->dm->sum_usage_marks_subquery('qu.id')}) AS totalmark 257 FROM {question_usages} qu 258 WHERE qu.id IN ({$this->usageids[0]}, {$this->usageids[1]})"); 259 260 $this->assertNull($totals[$this->usageids[0]]); // Since a question requires grading. 261 262 $this->assertNotNull($totals[$this->usageids[1]]); // Grrr! PHP null == 0 makes this hard. 263 $this->assertEquals(0, $totals[$this->usageids[1]]); 264 } 265 266 /** 267 * This test is executed by {@link test_reporting_queries()}. 268 */ 269 protected function dotest_question_attempt_latest_state_view() { 270 global $DB; 271 272 list($inlineview, $viewparams) = $this->dm->question_attempt_latest_state_view( 273 'lateststate', $this->bothusages); 274 275 $rawstates = $DB->get_records_sql(" 276 SELECT lateststate.questionattemptid, 277 qu.id AS questionusageid, 278 lateststate.slot, 279 lateststate.questionid, 280 lateststate.maxmark, 281 lateststate.sequencenumber, 282 lateststate.state 283 FROM {question_usages} qu 284 LEFT JOIN $inlineview ON lateststate.questionusageid = qu.id 285 WHERE qu.id IN ({$this->usageids[0]}, {$this->usageids[1]})", $viewparams); 286 287 $states = array(); 288 foreach ($rawstates as $state) { 289 $states[$state->questionusageid][$state->slot] = $state; 290 unset($state->questionattemptid); 291 unset($state->questionusageid); 292 unset($state->slot); 293 } 294 295 $state = $states[$this->usageids[0]][$this->allslots[0]]; 296 $this->assertEquals((object) array( 297 'questionid' => $this->sa->id, 298 'maxmark' => '5.0000000', 299 'sequencenumber' => 2, 300 'state' => (string) question_state::$gradedright, 301 ), $state); 302 303 $state = $states[$this->usageids[0]][$this->allslots[1]]; 304 $this->assertEquals((object) array( 305 'questionid' => $this->essay->id, 306 'maxmark' => '10.0000000', 307 'sequencenumber' => 2, 308 'state' => (string) question_state::$needsgrading, 309 ), $state); 310 311 $state = $states[$this->usageids[1]][$this->allslots[0]]; 312 $this->assertEquals((object) array( 313 'questionid' => $this->sa->id, 314 'maxmark' => '5.0000000', 315 'sequencenumber' => 2, 316 'state' => (string) question_state::$gradedwrong, 317 ), $state); 318 319 $state = $states[$this->usageids[1]][$this->allslots[1]]; 320 $this->assertEquals((object) array( 321 'questionid' => $this->essay->id, 322 'maxmark' => '10.0000000', 323 'sequencenumber' => 1, 324 'state' => (string) question_state::$gaveup, 325 ), $state); 326 } 327 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |