[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/question/engine/tests/ -> unitofwork_test.php (source)

   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   * This file contains tests for the question_engine_unit_of_work class.
  19   *
  20   * @package    moodlecore
  21   * @subpackage questionengine
  22   * @copyright  2012 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(dirname(__FILE__) . '/../lib.php');
  31  require_once(dirname(__FILE__) . '/helpers.php');
  32  
  33  
  34  /**
  35   * Unit tests for the {@link question_engine_unit_of_work} class.
  36   *
  37   * @copyright  2012 The Open University
  38   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  39   */
  40  class question_engine_unit_of_work_test extends data_loading_method_test_base {
  41      /** @var question_usage_by_activity the test question usage. */
  42      protected $quba;
  43  
  44      /** @var int the slot number of the one qa in the test usage.*/
  45      protected $slot;
  46  
  47      /** @var testable_question_engine_unit_of_work the unit of work we are testing. */
  48      protected $observer;
  49  
  50      protected function setUp() {
  51          // Create a usage in an initial state, with one shortanswer question added,
  52          // and attempted in interactive mode submitted responses 'toad' then 'frog'.
  53          // Then set it to use a new unit of work for any subsequent changes.
  54          // Create a short answer question.
  55          $question = test_question_maker::make_question('shortanswer');
  56          $question->hints = array(
  57              new question_hint(0, 'This is the first hint.', FORMAT_HTML),
  58              new question_hint(0, 'This is the second hint.', FORMAT_HTML),
  59          );
  60          $question->id = -1;
  61          question_bank::start_unit_test();
  62          question_bank::load_test_question_data($question);
  63  
  64          $this->setup_initial_test_state($this->get_test_data());
  65       }
  66  
  67      public function tearDown() {
  68          question_bank::end_unit_test();
  69      }
  70  
  71      protected function setup_initial_test_state($testdata) {
  72          $records = new question_test_recordset($testdata);
  73  
  74          $this->quba = question_usage_by_activity::load_from_records($records, 1);
  75  
  76          $this->slot = 1;
  77          $this->observer = new testable_question_engine_unit_of_work($this->quba);
  78          $this->quba->set_observer($this->observer);
  79      }
  80  
  81      protected function get_test_data() {
  82          return array(
  83          array('qubaid', 'contextid', 'component', 'preferredbehaviour',
  84                                                  'questionattemptid', 'contextid', 'questionusageid', 'slot',
  85                                                                 'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'maxfraction', 'flagged',
  86                                                                                                                'questionsummary', 'rightanswer', 'responsesummary', 'timemodified',
  87                                                                                                                                       'attemptstepid', 'sequencenumber', 'state', 'fraction',
  88                                                                                                                                                                       'timecreated', 'userid', 'name', 'value'),
  89          array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 1, 0, 'todo',             null, 1256233700, 1, '-_triesleft', 3),
  90          array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 2, 1, 'todo',             null, 1256233720, 1, 'answer',     'toad'),
  91          array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 2, 1, 'todo',             null, 1256233720, 1, '-submit',     1),
  92          array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 2, 1, 'todo',             null, 1256233720, 1, '-_triesleft', 1),
  93          array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 3, 2, 'todo',             null, 1256233740, 1, '-tryagain',   1),
  94          array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 5, 3, 'gradedright',      null, 1256233790, 1, 'answer',     'frog'),
  95          array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 5, 3, 'gradedright', 1.0000000, 1256233790, 1, '-submit',     1),
  96          );
  97      }
  98  
  99      public function test_initial_state() {
 100          $this->assertFalse($this->observer->get_modified());
 101          $this->assertEquals(0, count($this->observer->get_attempts_added()));
 102          $this->assertEquals(0, count($this->observer->get_attempts_modified()));
 103          $this->assertEquals(0, count($this->observer->get_steps_added()));
 104          $this->assertEquals(0, count($this->observer->get_steps_modified()));
 105          $this->assertEquals(0, count($this->observer->get_steps_deleted()));
 106      }
 107  
 108      public function test_update_usage() {
 109  
 110          $this->quba->set_preferred_behaviour('deferredfeedback');
 111  
 112          $this->assertTrue($this->observer->get_modified());
 113      }
 114  
 115      public function test_add_question() {
 116  
 117          $slot = $this->quba->add_question(test_question_maker::make_question('truefalse'));
 118  
 119          $newattempts = $this->observer->get_attempts_added();
 120          $this->assertEquals(1, count($newattempts));
 121          $this->assertTrue($this->quba->get_question_attempt($slot) === reset($newattempts));
 122          $this->assertSame($slot, key($newattempts));
 123      }
 124  
 125      public function test_add_and_start_question() {
 126  
 127          $slot = $this->quba->add_question(test_question_maker::make_question('truefalse'));
 128                  $this->quba->start_question($slot);
 129  
 130          // The point here is that, although we have added a step, it is not listed
 131          // separately becuase it is part of a newly added attempt, and all steps
 132          // for a newly added attempt are automatically added to the DB, so it does
 133          // not need to be tracked separately.
 134          $newattempts = $this->observer->get_attempts_added();
 135          $this->assertEquals(1, count($newattempts));
 136          $this->assertTrue($this->quba->get_question_attempt($slot) === reset($newattempts));
 137          $this->assertSame($slot, key($newattempts));
 138          $this->assertEquals(0, count($this->observer->get_steps_added()));
 139      }
 140  
 141      public function test_process_action() {
 142  
 143          $this->quba->manual_grade($this->slot, 'Actually, that is not quite right', 0.5, FORMAT_HTML);
 144  
 145          // Here, however, were we are adding a step to an existing qa, we do need to track that.
 146          $this->assertEquals(0, count($this->observer->get_attempts_added()));
 147  
 148          $updatedattempts = $this->observer->get_attempts_modified();
 149          $this->assertEquals(1, count($updatedattempts));
 150  
 151          $updatedattempt = reset($updatedattempts);
 152          $this->assertTrue($this->quba->get_question_attempt($this->slot) === $updatedattempt);
 153          $this->assertSame($this->slot, key($updatedattempts));
 154  
 155          $newsteps = $this->observer->get_steps_added();
 156          $this->assertEquals(1, count($newsteps));
 157  
 158          list($newstep, $qaid, $seq) = reset($newsteps);
 159          $this->assertSame($this->quba->get_question_attempt($this->slot)->get_last_step(), $newstep);
 160      }
 161  
 162      public function test_regrade_same_steps() {
 163  
 164          // Change the question in a minor way and regrade.
 165          $this->quba->get_question($this->slot)->answers[14]->fraction = 0.5;
 166          $this->quba->regrade_all_questions();
 167  
 168          // Here, the qa, and all the steps, should be marked as updated.
 169          // Here, however, were we are adding a step to an existing qa, we do need to track that.
 170          $this->assertEquals(0, count($this->observer->get_attempts_added()));
 171          $this->assertEquals(0, count($this->observer->get_steps_added()));
 172          $this->assertEquals(0, count($this->observer->get_steps_deleted()));
 173  
 174          $updatedattempts = $this->observer->get_attempts_modified();
 175          $this->assertEquals(1, count($updatedattempts));
 176  
 177          $updatedattempt = reset($updatedattempts);
 178          $this->assertTrue($this->quba->get_question_attempt($this->slot) === $updatedattempt);
 179  
 180          $updatedsteps = $this->observer->get_steps_modified();
 181          $this->assertEquals($updatedattempt->get_num_steps(), count($updatedsteps));
 182  
 183          foreach ($updatedattempt->get_step_iterator() as $seq => $step) {
 184              $this->assertSame(array($step, $updatedattempt->get_database_id(), $seq),
 185                      $updatedsteps[$seq]);
 186          }
 187      }
 188  
 189      public function test_regrade_losing_steps() {
 190  
 191          // Change the question so that 'toad' is also right, and regrade. This
 192          // will mean that the try again, and second try states are no longer
 193          // needed, so they should be dropped.
 194          $this->quba->get_question($this->slot)->answers[14]->fraction = 1;
 195          $this->quba->regrade_all_questions();
 196  
 197          $this->assertEquals(0, count($this->observer->get_attempts_added()));
 198          $this->assertEquals(0, count($this->observer->get_steps_added()));
 199  
 200          $updatedattempts = $this->observer->get_attempts_modified();
 201          $this->assertEquals(1, count($updatedattempts));
 202  
 203          $updatedattempt = reset($updatedattempts);
 204          $this->assertTrue($this->quba->get_question_attempt($this->slot) === $updatedattempt);
 205  
 206          $updatedsteps = $this->observer->get_steps_modified();
 207          $this->assertEquals($updatedattempt->get_num_steps(), count($updatedsteps));
 208  
 209          foreach ($updatedattempt->get_step_iterator() as $seq => $step) {
 210              $this->assertSame(array($step, $updatedattempt->get_database_id(), $seq),
 211                      $updatedsteps[$seq]);
 212          }
 213  
 214          $deletedsteps = $this->observer->get_steps_deleted();
 215          $this->assertEquals(2, count($deletedsteps));
 216  
 217          $firstdeletedstep = reset($deletedsteps);
 218          $this->assertEquals(array('-tryagain' => 1), $firstdeletedstep->get_all_data());
 219  
 220          $seconddeletedstep = end($deletedsteps);
 221          $this->assertEquals(array('answer' => 'frog', '-submit' => 1),
 222                  $seconddeletedstep->get_all_data());
 223      }
 224  
 225      public function test_tricky_regrade() {
 226  
 227          // The tricky thing here is that we take a half-complete question-attempt,
 228          // and then as one transaction, we submit some more responses, and then
 229          // change the question attempt as in test_regrade_losing_steps, and regrade
 230          // before the steps are even written to the database the first time.
 231          $somedata = $this->get_test_data();
 232          $somedata = array_slice($somedata, 0, 5);
 233          $this->setup_initial_test_state($somedata);
 234  
 235          $this->quba->process_action($this->slot, array('-tryagain' => 1));
 236          $this->quba->process_action($this->slot, array('answer' => 'frog', '-submit' => 1));
 237          $this->quba->finish_all_questions();
 238  
 239          $this->quba->get_question($this->slot)->answers[14]->fraction = 1;
 240          $this->quba->regrade_all_questions();
 241  
 242          $this->assertEquals(0, count($this->observer->get_attempts_added()));
 243  
 244          $updatedattempts = $this->observer->get_attempts_modified();
 245          $this->assertEquals(1, count($updatedattempts));
 246  
 247          $updatedattempt = reset($updatedattempts);
 248          $this->assertTrue($this->quba->get_question_attempt($this->slot) === $updatedattempt);
 249  
 250          $this->assertEquals(0, count($this->observer->get_steps_added()));
 251  
 252          $updatedsteps = $this->observer->get_steps_modified();
 253          $this->assertEquals($updatedattempt->get_num_steps(), count($updatedsteps));
 254  
 255          foreach ($updatedattempt->get_step_iterator() as $seq => $step) {
 256              $this->assertSame(array($step, $updatedattempt->get_database_id(), $seq),
 257                      $updatedsteps[$seq]);
 258          }
 259  
 260          $this->assertEquals(0, count($this->observer->get_steps_deleted()));
 261      }
 262  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1