Differences Between: [Versions 310 and 311] [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 core_question; 18 19 use qubaid_join; 20 use qubaid_list; 21 use question_bank; 22 use question_engine; 23 use question_engine_data_mapper; 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 global $CFG; 28 require_once (__DIR__ . '/../lib.php'); 29 require_once (__DIR__ . '/helpers.php'); 30 31 /** 32 * Unit tests for parts of {@link question_engine_data_mapper}. 33 * 34 * Note that many of the methods used when attempting questions, like 35 * load_questions_usage_by_activity, insert_question_*, delete_steps are 36 * tested elsewhere, e.g. by {@link question_usage_autosave_test}. We do not 37 * re-test them here. 38 * 39 * @package core_question 40 * @category test 41 * @copyright 2014 The Open University 42 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 43 */ 44 class datalib_test extends \qbehaviour_walkthrough_test_base { 45 46 /** 47 * We create two usages, each with two questions, a short-answer marked 48 * out of 5, and and essay marked out of 10. We just start these attempts. 49 * 50 * Then we change the max mark for the short-answer question in one of the 51 * usages to 20, using a qubaid_list, and verify. 52 * 53 * Then we change the max mark for the essay question in the other 54 * usage to 2, using a qubaid_join, and verify. 55 */ 56 public function test_set_max_mark_in_attempts() { 57 58 // Set up some things the tests will need. 59 $this->resetAfterTest(); 60 $dm = new question_engine_data_mapper(); 61 62 // Create the questions. 63 $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); 64 $cat = $generator->create_question_category(); 65 $sa = $generator->create_question('shortanswer', null, 66 array('category' => $cat->id)); 67 $essay = $generator->create_question('essay', null, 68 array('category' => $cat->id)); 69 70 // Create the first usage. 71 $q = question_bank::load_question($sa->id); 72 $this->start_attempt_at_question($q, 'interactive', 5); 73 74 $q = question_bank::load_question($essay->id); 75 $this->start_attempt_at_question($q, 'interactive', 10); 76 77 $this->finish(); 78 $this->save_quba(); 79 $usage1id = $this->quba->get_id(); 80 81 // Create the second usage. 82 $this->quba = question_engine::make_questions_usage_by_activity('unit_test', 83 \context_system::instance()); 84 85 $q = question_bank::load_question($sa->id); 86 $this->start_attempt_at_question($q, 'interactive', 5); 87 $this->process_submission(array('answer' => 'fish')); 88 89 $q = question_bank::load_question($essay->id); 90 $this->start_attempt_at_question($q, 'interactive', 10); 91 92 $this->finish(); 93 $this->save_quba(); 94 $usage2id = $this->quba->get_id(); 95 96 // Test set_max_mark_in_attempts with a qubaid_list. 97 $usagestoupdate = new qubaid_list(array($usage1id)); 98 $dm->set_max_mark_in_attempts($usagestoupdate, 1, 20.0); 99 $quba1 = question_engine::load_questions_usage_by_activity($usage1id); 100 $quba2 = question_engine::load_questions_usage_by_activity($usage2id); 101 $this->assertEquals(20, $quba1->get_question_max_mark(1)); 102 $this->assertEquals(10, $quba1->get_question_max_mark(2)); 103 $this->assertEquals( 5, $quba2->get_question_max_mark(1)); 104 $this->assertEquals(10, $quba2->get_question_max_mark(2)); 105 106 // Test set_max_mark_in_attempts with a qubaid_join. 107 $usagestoupdate = new qubaid_join('{question_usages} qu', 'qu.id', 108 'qu.id = :usageid', array('usageid' => $usage2id)); 109 $dm->set_max_mark_in_attempts($usagestoupdate, 2, 2.0); 110 $quba1 = question_engine::load_questions_usage_by_activity($usage1id); 111 $quba2 = question_engine::load_questions_usage_by_activity($usage2id); 112 $this->assertEquals(20, $quba1->get_question_max_mark(1)); 113 $this->assertEquals(10, $quba1->get_question_max_mark(2)); 114 $this->assertEquals( 5, $quba2->get_question_max_mark(1)); 115 $this->assertEquals( 2, $quba2->get_question_max_mark(2)); 116 117 // Test the nothing to do case. 118 $usagestoupdate = new qubaid_join('{question_usages} qu', 'qu.id', 119 'qu.id = :usageid', array('usageid' => -1)); 120 $dm->set_max_mark_in_attempts($usagestoupdate, 2, 2.0); 121 $quba1 = question_engine::load_questions_usage_by_activity($usage1id); 122 $quba2 = question_engine::load_questions_usage_by_activity($usage2id); 123 $this->assertEquals(20, $quba1->get_question_max_mark(1)); 124 $this->assertEquals(10, $quba1->get_question_max_mark(2)); 125 $this->assertEquals( 5, $quba2->get_question_max_mark(1)); 126 $this->assertEquals( 2, $quba2->get_question_max_mark(2)); 127 } 128 129 public function test_load_used_variants() { 130 $this->resetAfterTest(); 131 $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); 132 133 $cat = $generator->create_question_category(); 134 $questiondata1 = $generator->create_question('shortanswer', null, array('category' => $cat->id)); 135 $questiondata2 = $generator->create_question('shortanswer', null, array('category' => $cat->id)); 136 $questiondata3 = $generator->create_question('shortanswer', null, array('category' => $cat->id)); 137 138 $quba = question_engine::make_questions_usage_by_activity('test', \context_system::instance()); 139 $quba->set_preferred_behaviour('deferredfeedback'); 140 $question1 = question_bank::load_question($questiondata1->id); 141 $question3 = question_bank::load_question($questiondata3->id); 142 $quba->add_question($question1); 143 $quba->add_question($question1); 144 $quba->add_question($question3); 145 $quba->start_all_questions(); 146 question_engine::save_questions_usage_by_activity($quba); 147 148 $this->assertEquals(array( 149 $questiondata1->id => array(1 => 2), 150 $questiondata2->id => array(), 151 $questiondata3->id => array(1 => 1), 152 ), question_engine::load_used_variants( 153 array($questiondata1->id, $questiondata2->id, $questiondata3->id), 154 new qubaid_list(array($quba->get_id())))); 155 } 156 157 public function test_repeated_usage_saving_new_usage() { 158 global $DB; 159 160 $this->resetAfterTest(); 161 162 $initialqurows = $DB->count_records('question_usages'); 163 $initialqarows = $DB->count_records('question_attempts'); 164 $initialqasrows = $DB->count_records('question_attempt_steps'); 165 166 $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); 167 $cat = $generator->create_question_category(); 168 $questiondata1 = $generator->create_question('shortanswer', null, array('category' => $cat->id)); 169 170 $quba = question_engine::make_questions_usage_by_activity('test', \context_system::instance()); 171 $quba->set_preferred_behaviour('deferredfeedback'); 172 $quba->add_question(question_bank::load_question($questiondata1->id)); 173 $quba->start_all_questions(); 174 question_engine::save_questions_usage_by_activity($quba); 175 176 // Check one usage, question_attempts and step added. 177 $firstid = $quba->get_id(); 178 $this->assertEquals(1, $DB->count_records('question_usages') - $initialqurows); 179 $this->assertEquals(1, $DB->count_records('question_attempts') - $initialqarows); 180 $this->assertEquals(1, $DB->count_records('question_attempt_steps') - $initialqasrows); 181 182 $quba->finish_all_questions(); 183 question_engine::save_questions_usage_by_activity($quba); 184 185 // Check usage id not changed. 186 $this->assertEquals($firstid, $quba->get_id()); 187 188 // Check still one usage, question_attempts, but now two steps. 189 $this->assertEquals(1, $DB->count_records('question_usages') - $initialqurows); 190 $this->assertEquals(1, $DB->count_records('question_attempts') - $initialqarows); 191 $this->assertEquals(2, $DB->count_records('question_attempt_steps') - $initialqasrows); 192 } 193 194 public function test_repeated_usage_saving_existing_usage() { 195 global $DB; 196 197 $this->resetAfterTest(); 198 199 $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); 200 $cat = $generator->create_question_category(); 201 $questiondata1 = $generator->create_question('shortanswer', null, array('category' => $cat->id)); 202 203 $initquba = question_engine::make_questions_usage_by_activity('test', \context_system::instance()); 204 $initquba->set_preferred_behaviour('deferredfeedback'); 205 $slot = $initquba->add_question(question_bank::load_question($questiondata1->id)); 206 $initquba->start_all_questions(); 207 question_engine::save_questions_usage_by_activity($initquba); 208 209 $quba = question_engine::load_questions_usage_by_activity($initquba->get_id()); 210 211 $initialqurows = $DB->count_records('question_usages'); 212 $initialqarows = $DB->count_records('question_attempts'); 213 $initialqasrows = $DB->count_records('question_attempt_steps'); 214 215 $quba->process_all_actions(time(), $quba->prepare_simulated_post_data( 216 [$slot => ['answer' => 'Frog']])); 217 question_engine::save_questions_usage_by_activity($quba); 218 219 // Check one usage, question_attempts and step added. 220 $this->assertEquals(0, $DB->count_records('question_usages') - $initialqurows); 221 $this->assertEquals(0, $DB->count_records('question_attempts') - $initialqarows); 222 $this->assertEquals(1, $DB->count_records('question_attempt_steps') - $initialqasrows); 223 224 $quba->finish_all_questions(); 225 question_engine::save_questions_usage_by_activity($quba); 226 227 // Check still one usage, question_attempts, but now two steps. 228 $this->assertEquals(0, $DB->count_records('question_usages') - $initialqurows); 229 $this->assertEquals(0, $DB->count_records('question_attempts') - $initialqarows); 230 $this->assertEquals(2, $DB->count_records('question_attempt_steps') - $initialqasrows); 231 } 232 233 /** 234 * Test that database operations on an empty usage work without errors. 235 */ 236 public function test_save_and_load_an_empty_usage() { 237 $this->resetAfterTest(); 238 239 // Create a new usage. 240 $quba = question_engine::make_questions_usage_by_activity('test', \context_system::instance()); 241 $quba->set_preferred_behaviour('deferredfeedback'); 242 243 // Save it. 244 question_engine::save_questions_usage_by_activity($quba); 245 246 // Reload it. 247 $reloadedquba = question_engine::load_questions_usage_by_activity($quba->get_id()); 248 $this->assertCount(0, $quba->get_slots()); 249 250 // Delete it. 251 question_engine::delete_questions_usage_by_activity($quba->get_id()); 252 } 253 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body