Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.
   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  defined('MOODLE_INTERNAL') || die();
  18  
  19  global $CFG;
  20  
  21  require_once($CFG->dirroot . '/webservice/tests/helpers.php');
  22  
  23  /**
  24   * Unit tests for the grading API defined in core_grading_external class.
  25   *
  26   * @package core_grading
  27   * @category external
  28   * @copyright 2013 Paul Charsley
  29   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  30   */
  31  class core_grading_externallib_testcase extends externallib_advanced_testcase {
  32  
  33      /**
  34       * Test get_definitions
  35       */
  36      public function test_get_definitions() {
  37          global $DB, $CFG, $USER;
  38  
  39          $this->resetAfterTest(true);
  40          // Create a course and assignment.
  41          $coursedata['idnumber'] = 'idnumbercourse';
  42          $coursedata['fullname'] = 'Lightwork Course';
  43          $coursedata['summary'] = 'Lightwork Course description';
  44          $coursedata['summaryformat'] = FORMAT_MOODLE;
  45          $course = self::getDataGenerator()->create_course($coursedata);
  46  
  47          $assigndata['course'] = $course->id;
  48          $assigndata['name'] = 'lightwork assignment';
  49  
  50          $cm = self::getDataGenerator()->create_module('assign', $assigndata);
  51  
  52          // Create manual enrolment record.
  53          $manualenroldata['enrol'] = 'manual';
  54          $manualenroldata['status'] = 0;
  55          $manualenroldata['courseid'] = $course->id;
  56          $enrolid = $DB->insert_record('enrol', $manualenroldata);
  57  
  58          // Create a teacher and give them capabilities.
  59          $coursecontext = context_course::instance($course->id);
  60          $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $coursecontext->id, 3);
  61          $modulecontext = context_module::instance($cm->cmid);
  62          $this->assignUserCapability('mod/assign:grade', $modulecontext->id, $roleid);
  63  
  64          // Create the teacher's enrolment record.
  65          $userenrolmentdata['status'] = 0;
  66          $userenrolmentdata['enrolid'] = $enrolid;
  67          $userenrolmentdata['userid'] = $USER->id;
  68          $DB->insert_record('user_enrolments', $userenrolmentdata);
  69  
  70          // Create a grading area.
  71          $gradingarea = array(
  72              'contextid' => $modulecontext->id,
  73              'component' => 'mod_assign',
  74              'areaname' => 'submissions',
  75              'activemethod' => 'rubric'
  76          );
  77          $areaid = $DB->insert_record('grading_areas', $gradingarea);
  78  
  79          // Create a rubric grading definition.
  80          $rubricdefinition = array (
  81              'areaid' => $areaid,
  82              'method' => 'rubric',
  83              'name' => 'test',
  84              'status' => 20,
  85              'copiedfromid' => 1,
  86              'timecreated' => 1,
  87              'usercreated' => $USER->id,
  88              'timemodified' => 1,
  89              'usermodified' => $USER->id,
  90              'timecopied' => 0
  91          );
  92          $definitionid = $DB->insert_record('grading_definitions', $rubricdefinition);
  93  
  94          // Create a criterion with levels.
  95          $rubriccriteria1 = array (
  96              'definitionid' => $definitionid,
  97              'sortorder' => 1,
  98              'description' => 'Demonstrate an understanding of disease control',
  99              'descriptionformat' => 0
 100          );
 101          $criterionid1 = $DB->insert_record('gradingform_rubric_criteria', $rubriccriteria1);
 102          $rubriclevel1 = array (
 103              'criterionid' => $criterionid1,
 104              'score' => 5,
 105              'definition' => 'pass',
 106              'definitionformat' => 0
 107          );
 108          $DB->insert_record('gradingform_rubric_levels', $rubriclevel1);
 109          $rubriclevel2 = array (
 110              'criterionid' => $criterionid1,
 111              'score' => 10,
 112              'definition' => 'excellent',
 113              'definitionformat' => 0
 114          );
 115          $DB->insert_record('gradingform_rubric_levels', $rubriclevel2);
 116  
 117          // Create a second criterion with levels.
 118          $rubriccriteria2 = array (
 119              'definitionid' => $definitionid,
 120              'sortorder' => 2,
 121              'description' => 'Demonstrate an understanding of brucellosis',
 122              'descriptionformat' => 0
 123          );
 124          $criterionid2 = $DB->insert_record('gradingform_rubric_criteria', $rubriccriteria2);
 125          $rubriclevel1 = array (
 126              'criterionid' => $criterionid2,
 127              'score' => 5,
 128              'definition' => 'pass',
 129              'definitionformat' => 0
 130          );
 131          $DB->insert_record('gradingform_rubric_levels', $rubriclevel1);
 132          $rubriclevel2 = array (
 133              'criterionid' => $criterionid2,
 134              'score' => 10,
 135              'definition' => 'excellent',
 136              'definitionformat' => 0
 137          );
 138          $DB->insert_record('gradingform_rubric_levels', $rubriclevel2);
 139  
 140          // Call the external function.
 141          $cmids = array ($cm->cmid);
 142          $areaname = 'submissions';
 143          $result = core_grading_external::get_definitions($cmids, $areaname);
 144          $result = external_api::clean_returnvalue(core_grading_external::get_definitions_returns(), $result);
 145  
 146          $this->assertEquals(1, count($result['areas']));
 147          $this->assertEquals(1, count($result['areas'][0]['definitions']));
 148          $definition = $result['areas'][0]['definitions'][0];
 149  
 150          $this->assertEquals($rubricdefinition['method'], $definition['method']);
 151          $this->assertEquals($USER->id, $definition['usercreated']);
 152  
 153          require_once("$CFG->dirroot/grade/grading/lib.php");
 154          require_once($CFG->dirroot.'/grade/grading/form/'.$rubricdefinition['method'].'/lib.php');
 155  
 156          $gradingmanager = get_grading_manager($areaid);
 157  
 158          $this->assertEquals(1, count($definition[$rubricdefinition['method']]));
 159  
 160          $rubricdetails = $definition[$rubricdefinition['method']];
 161          $details = call_user_func('gradingform_'.$rubricdefinition['method'].'_controller::get_external_definition_details');
 162  
 163          $this->assertEquals(2, count($rubricdetails[key($details)]));
 164  
 165          $found = false;
 166          foreach ($rubricdetails[key($details)] as $criterion) {
 167              if ($criterion['id'] == $criterionid1) {
 168                  $this->assertEquals($rubriccriteria1['description'], $criterion['description']);
 169                  $this->assertEquals(2, count($criterion['levels']));
 170                  $found = true;
 171                  break;
 172              }
 173          }
 174          $this->assertTrue($found);
 175      }
 176  
 177      /**
 178       * Test get_gradingform_instances
 179       */
 180      public function test_get_gradingform_instances() {
 181          global $DB, $USER;
 182  
 183          $this->resetAfterTest(true);
 184          // Create a course and assignment.
 185          $coursedata['idnumber'] = 'idnumbercourse';
 186          $coursedata['fullname'] = 'Lightwork Course';
 187          $coursedata['summary'] = 'Lightwork Course description';
 188          $coursedata['summaryformat'] = FORMAT_MOODLE;
 189          $course = self::getDataGenerator()->create_course($coursedata);
 190  
 191          $assigndata['course'] = $course->id;
 192          $assigndata['name'] = 'lightwork assignment';
 193  
 194          $assign = self::getDataGenerator()->create_module('assign', $assigndata);
 195  
 196          // Create manual enrolment record.
 197          $manualenroldata['enrol'] = 'manual';
 198          $manualenroldata['status'] = 0;
 199          $manualenroldata['courseid'] = $course->id;
 200          $enrolid = $DB->insert_record('enrol', $manualenroldata);
 201  
 202          // Create a teacher and give them capabilities.
 203          $coursecontext = context_course::instance($course->id);
 204          $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $coursecontext->id, 3);
 205          $modulecontext = context_module::instance($assign->cmid);
 206          $this->assignUserCapability('mod/assign:grade', $modulecontext->id, $roleid);
 207  
 208          // Create the teacher's enrolment record.
 209          $userenrolmentdata['status'] = 0;
 210          $userenrolmentdata['enrolid'] = $enrolid;
 211          $userenrolmentdata['userid'] = $USER->id;
 212          $DB->insert_record('user_enrolments', $userenrolmentdata);
 213  
 214          // Create a student with an assignment grade.
 215          $student = self::getDataGenerator()->create_user();
 216          $assigngrade = new stdClass();
 217          $assigngrade->assignment = $assign->id;
 218          $assigngrade->userid = $student->id;
 219          $assigngrade->timecreated = time();
 220          $assigngrade->timemodified = $assigngrade->timecreated;
 221          $assigngrade->grader = $USER->id;
 222          $assigngrade->grade = 50;
 223          $assigngrade->attemptnumber = 0;
 224          $gid = $DB->insert_record('assign_grades', $assigngrade);
 225  
 226          // Create a grading area.
 227          $gradingarea = array(
 228              'contextid' => $modulecontext->id,
 229              'component' => 'mod_assign',
 230              'areaname' => 'submissions',
 231              'activemethod' => 'rubric'
 232          );
 233          $areaid = $DB->insert_record('grading_areas', $gradingarea);
 234  
 235          // Create a rubric grading definition.
 236          $rubricdefinition = array (
 237              'areaid' => $areaid,
 238              'method' => 'rubric',
 239              'name' => 'test',
 240              'status' => 20,
 241              'copiedfromid' => 1,
 242              'timecreated' => 1,
 243              'usercreated' => $USER->id,
 244              'timemodified' => 1,
 245              'usermodified' => $USER->id,
 246              'timecopied' => 0
 247          );
 248          $definitionid = $DB->insert_record('grading_definitions', $rubricdefinition);
 249  
 250          // Create a criterion with a level.
 251          $rubriccriteria = array (
 252              'definitionid' => $definitionid,
 253              'sortorder' => 1,
 254              'description' => 'Demonstrate an understanding of disease control',
 255              'descriptionformat' => 0
 256          );
 257          $criterionid = $DB->insert_record('gradingform_rubric_criteria', $rubriccriteria);
 258          $rubriclevel = array (
 259              'criterionid' => $criterionid,
 260              'score' => 50,
 261              'definition' => 'pass',
 262              'definitionformat' => 0
 263          );
 264          $levelid = $DB->insert_record('gradingform_rubric_levels', $rubriclevel);
 265  
 266          // Create a grading instance.
 267          $instance = array (
 268              'definitionid' => $definitionid,
 269              'raterid' => $USER->id,
 270              'itemid' => $gid,
 271              'status' => 1,
 272              'feedbackformat' => 0,
 273              'timemodified' => 1
 274          );
 275          $instanceid = $DB->insert_record('grading_instances', $instance);
 276  
 277          // Create a filling.
 278          $filling = array (
 279              'instanceid' => $instanceid,
 280              'criterionid' => $criterionid,
 281              'levelid' => $levelid,
 282              'remark' => 'excellent work',
 283              'remarkformat' => 0
 284          );
 285          $DB->insert_record('gradingform_rubric_fillings', $filling);
 286  
 287          // Call the external function.
 288          $result = core_grading_external::get_gradingform_instances($definitionid, 0);
 289          $result = external_api::clean_returnvalue(core_grading_external::get_gradingform_instances_returns(), $result);
 290  
 291          $this->assertEquals(1, count($result['instances']));
 292          $this->assertEquals($USER->id, $result['instances'][0]['raterid']);
 293          $this->assertEquals($gid, $result['instances'][0]['itemid']);
 294          $this->assertEquals(1, $result['instances'][0]['status']);
 295          $this->assertEquals(1, $result['instances'][0]['timemodified']);
 296          $this->assertEquals(1, count($result['instances'][0]['rubric']));
 297          $this->assertEquals(1, count($result['instances'][0]['rubric']['criteria']));
 298          $criteria = $result['instances'][0]['rubric']['criteria'];
 299          $this->assertEquals($criterionid, $criteria[0]['criterionid']);
 300          $this->assertEquals($levelid, $criteria[0]['levelid']);
 301          $this->assertEquals('excellent work', $criteria[0]['remark']);
 302      }
 303  
 304      /**
 305       *
 306       * Test save_definitions for rubric grading method
 307       */
 308      public function test_save_definitions_rubric() {
 309          global $DB, $CFG, $USER;
 310  
 311          $this->resetAfterTest(true);
 312          // Create a course and assignment.
 313          $course = self::getDataGenerator()->create_course();
 314          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 315          $params['course'] = $course->id;
 316          $instance = $generator->create_instance($params);
 317          $cm = get_coursemodule_from_instance('assign', $instance->id);
 318          $context = context_module::instance($cm->id);
 319          $coursecontext = context_course::instance($course->id);
 320  
 321          // Create the teacher.
 322          $teacher = self::getDataGenerator()->create_user();
 323          $USER->id = $teacher->id;
 324          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
 325          $this->assignUserCapability('moodle/grade:managegradingforms', $context->id, $teacherrole->id);
 326          $this->getDataGenerator()->enrol_user($teacher->id,
 327                                                $course->id,
 328                                                $teacherrole->id);
 329  
 330          // The grading area to insert.
 331          $gradingarea = array(
 332              'cmid' => $cm->id,
 333              'contextid' => $context->id,
 334              'component' => 'mod_assign',
 335              'areaname'  => 'submissions',
 336              'activemethod' => 'rubric'
 337          );
 338  
 339          // The rubric definition to insert.
 340          $rubricdefinition = array(
 341              'method' => 'rubric',
 342              'name' => 'test',
 343              'description' => '',
 344              'status' => 20,
 345              'copiedfromid' => 1,
 346              'timecreated' => 1,
 347              'usercreated' => $teacher->id,
 348              'timemodified' => 1,
 349              'usermodified' => $teacher->id,
 350              'timecopied' => 0
 351          );
 352  
 353          // The criterion to insert.
 354          $rubriccriteria1 = array (
 355               'sortorder' => 1,
 356               'description' => 'Demonstrate an understanding of disease control',
 357               'descriptionformat' => 0
 358          );
 359  
 360          // 3 levels for the criterion.
 361          $rubriclevel1 = array (
 362              'score' => 50,
 363              'definition' => 'pass',
 364              'definitionformat' => 0
 365          );
 366          $rubriclevel2 = array (
 367              'score' => 100,
 368              'definition' => 'excellent',
 369              'definitionformat' => 0
 370          );
 371          $rubriclevel3 = array (
 372              'score' => 0,
 373              'definition' => 'fail',
 374              'definitionformat' => 0
 375          );
 376  
 377          $rubriccriteria1['levels'] = array($rubriclevel1, $rubriclevel2, $rubriclevel3);
 378          $rubricdefinition['rubric'] = array('rubric_criteria' => array($rubriccriteria1));
 379          $gradingarea['definitions'] = array($rubricdefinition);
 380  
 381          $results = core_grading_external::save_definitions(array($gradingarea));
 382  
 383          $area = $DB->get_record('grading_areas',
 384                                  array('contextid' => $context->id, 'component' => 'mod_assign', 'areaname' => 'submissions'),
 385                                  '*', MUST_EXIST);
 386          $this->assertEquals($area->activemethod, 'rubric');
 387  
 388          $definition = $DB->get_record('grading_definitions', array('areaid' => $area->id, 'method' => 'rubric'), '*', MUST_EXIST);
 389          $this->assertEquals($rubricdefinition['name'], $definition->name);
 390  
 391          $criterion1 = $DB->get_record('gradingform_rubric_criteria', array('definitionid' => $definition->id), '*', MUST_EXIST);
 392          $levels = $DB->get_records('gradingform_rubric_levels', array('criterionid' => $criterion1->id));
 393          $validlevelcount = 0;
 394          $expectedvalue = true;
 395          foreach ($levels as $level) {
 396              if ($level->score == 0) {
 397                  $this->assertEquals('fail', $level->definition);
 398                  $validlevelcount++;
 399              } else if ($level->score == 50) {
 400                  $this->assertEquals('pass', $level->definition);
 401                  $validlevelcount++;
 402              } else if ($level->score == 100) {
 403                  $this->assertEquals('excellent', $level->definition);
 404                  $excellentlevelid = $level->id;
 405                  $validlevelcount++;
 406              } else {
 407                  $expectedvalue = false;
 408              }
 409          }
 410          $this->assertEquals(3, $validlevelcount);
 411          $this->assertTrue($expectedvalue, 'A level with an unexpected score was found');
 412  
 413          // Test add a new level and modify an existing.
 414          // Test add a new criteria and modify an existing.
 415          // Test modify a definition.
 416  
 417          // The rubric definition to update.
 418          $rubricdefinition = array(
 419              'id' => $definition->id,
 420              'method' => 'rubric',
 421              'name' => 'test changed',
 422              'description' => '',
 423              'status' => 20,
 424              'copiedfromid' => 1,
 425              'timecreated' => 1,
 426              'usercreated' => $teacher->id,
 427              'timemodified' => 1,
 428              'usermodified' => $teacher->id,
 429              'timecopied' => 0
 430          );
 431  
 432          // A criterion to update.
 433          $rubriccriteria1 = array (
 434               'id' => $criterion1->id,
 435               'sortorder' => 1,
 436               'description' => 'Demonstrate an understanding of rabies control',
 437               'descriptionformat' => 0
 438          );
 439  
 440          // A new criterion to add.
 441          $rubriccriteria2 = array (
 442               'sortorder' => 2,
 443               'description' => 'Demonstrate an understanding of anthrax control',
 444               'descriptionformat' => 0
 445          );
 446  
 447          // A level to update.
 448          $rubriclevel2 = array (
 449              'id' => $excellentlevelid,
 450              'score' => 75,
 451              'definition' => 'excellent',
 452              'definitionformat' => 0
 453          );
 454  
 455          // A level to insert.
 456          $rubriclevel4 = array (
 457              'score' => 100,
 458              'definition' => 'superb',
 459              'definitionformat' => 0
 460          );
 461  
 462          $rubriccriteria1['levels'] = array($rubriclevel1, $rubriclevel2, $rubriclevel3, $rubriclevel4);
 463          $rubricdefinition['rubric'] = array('rubric_criteria' => array($rubriccriteria1, $rubriccriteria2));
 464          $gradingarea['definitions'] = array($rubricdefinition);
 465  
 466          $results = core_grading_external::save_definitions(array($gradingarea));
 467  
 468          // Test definition name change.
 469          $definition = $DB->get_record('grading_definitions', array('id' => $definition->id), '*', MUST_EXIST);
 470          $this->assertEquals('test changed', $definition->name);
 471  
 472          // Test criteria description change.
 473          $modifiedcriteria = $DB->get_record('gradingform_rubric_criteria', array('id' => $criterion1->id), '*', MUST_EXIST);
 474          $this->assertEquals('Demonstrate an understanding of rabies control', $modifiedcriteria->description);
 475  
 476          // Test new criteria added.
 477          $newcriteria = $DB->get_record('gradingform_rubric_criteria',
 478                                         array('definitionid' => $definition->id, 'sortorder' => 2), '*', MUST_EXIST);
 479          $this->assertEquals('Demonstrate an understanding of anthrax control', $newcriteria->description);
 480  
 481          // Test excellent level score change from 100 to 75.
 482          $modifiedlevel = $DB->get_record('gradingform_rubric_levels', array('id' => $excellentlevelid), '*', MUST_EXIST);
 483          $this->assertEquals(75, $modifiedlevel->score);
 484  
 485          // Test new superb level added.
 486          $newlevel = $DB->get_record('gradingform_rubric_levels',
 487                                         array('criterionid' => $criterion1->id, 'score' => 100), '*', MUST_EXIST);
 488          $this->assertEquals('superb', $newlevel->definition);
 489  
 490          // Test remove a level
 491          // Test remove a criterion
 492          // The rubric definition with the removed criterion and levels.
 493          $rubricdefinition = array(
 494              'id' => $definition->id,
 495              'method' => 'rubric',
 496              'name' => 'test changed',
 497              'description' => '',
 498              'status' => 20,
 499              'copiedfromid' => 1,
 500              'timecreated' => 1,
 501              'usercreated' => $teacher->id,
 502              'timemodified' => 1,
 503              'usermodified' => $teacher->id,
 504              'timecopied' => 0
 505          );
 506  
 507          $rubriccriteria1 = array (
 508               'id' => $criterion1->id,
 509               'sortorder' => 1,
 510               'description' => 'Demonstrate an understanding of rabies control',
 511               'descriptionformat' => 0
 512          );
 513  
 514          $rubriclevel1 = array (
 515              'score' => 0,
 516              'definition' => 'fail',
 517              'definitionformat' => 0
 518          );
 519          $rubriclevel2 = array (
 520              'score' => 100,
 521              'definition' => 'pass',
 522              'definitionformat' => 0
 523          );
 524  
 525          $rubriccriteria1['levels'] = array($rubriclevel1, $rubriclevel2);
 526          $rubricdefinition['rubric'] = array('rubric_criteria' => array($rubriccriteria1));
 527          $gradingarea['definitions'] = array($rubricdefinition);
 528  
 529          $results = core_grading_external::save_definitions(array($gradingarea));
 530  
 531          // Only 1 criterion should now exist.
 532          $this->assertEquals(1, $DB->count_records('gradingform_rubric_criteria', array('definitionid' => $definition->id)));
 533          $criterion1 = $DB->get_record('gradingform_rubric_criteria', array('definitionid' => $definition->id), '*', MUST_EXIST);
 534          $this->assertEquals('Demonstrate an understanding of rabies control', $criterion1->description);
 535          // This criterion should only have 2 levels.
 536          $this->assertEquals(2, $DB->count_records('gradingform_rubric_levels', array('criterionid' => $criterion1->id)));
 537  
 538          $gradingarea['activemethod'] = 'invalid';
 539          $this->expectException('moodle_exception');
 540          $results = core_grading_external::save_definitions(array($gradingarea));
 541      }
 542  
 543      /**
 544       *
 545       * Tests save_definitions for the marking guide grading method
 546       */
 547      public function test_save_definitions_marking_guide() {
 548          global $DB, $CFG, $USER;
 549  
 550          $this->resetAfterTest(true);
 551          // Create a course and assignment.
 552          $course = self::getDataGenerator()->create_course();
 553          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 554          $params['course'] = $course->id;
 555          $instance = $generator->create_instance($params);
 556          $cm = get_coursemodule_from_instance('assign', $instance->id);
 557          $context = context_module::instance($cm->id);
 558          $coursecontext = context_course::instance($course->id);
 559  
 560          // Create the teacher.
 561          $teacher = self::getDataGenerator()->create_user();
 562          $USER->id = $teacher->id;
 563          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
 564          $this->assignUserCapability('moodle/grade:managegradingforms', $context->id, $teacherrole->id);
 565          $this->getDataGenerator()->enrol_user($teacher->id,
 566                                                $course->id,
 567                                                $teacherrole->id);
 568  
 569          // Test insert a grading area with guide definition, criteria and comments.
 570          $gradingarea = array(
 571              'cmid' => $cm->id,
 572              'contextid' => $context->id,
 573              'component' => 'mod_assign',
 574              'areaname'  => 'submissions',
 575              'activemethod' => 'guide'
 576          );
 577  
 578          $guidedefinition = array(
 579              'method' => 'guide',
 580              'name' => 'test',
 581              'description' => '',
 582              'status' => 20,
 583              'copiedfromid' => 1,
 584              'timecreated' => 1,
 585              'usercreated' => $teacher->id,
 586              'timemodified' => 1,
 587              'usermodified' => $teacher->id,
 588              'timecopied' => 0
 589          );
 590  
 591          $guidecomment = array(
 592               'sortorder' => 1,
 593               'description' => 'Students need to show that they understand the control of zoonoses',
 594               'descriptionformat' => 0
 595          );
 596          $guidecriteria1 = array (
 597               'sortorder' => 1,
 598               'shortname' => 'Rabies Control',
 599               'description' => 'Understand rabies control techniques',
 600               'descriptionformat' => 0,
 601               'descriptionmarkers' => 'Student must demonstrate that they understand rabies control',
 602               'descriptionmarkersformat' => 0,
 603               'maxscore' => 50
 604          );
 605          $guidecriteria2 = array (
 606               'sortorder' => 2,
 607               'shortname' => 'Anthrax Control',
 608               'description' => 'Understand anthrax control',
 609               'descriptionformat' => 0,
 610               'descriptionmarkers' => 'Student must demonstrate that they understand anthrax control',
 611               'descriptionmarkersformat' => 0,
 612               'maxscore' => 50
 613          );
 614  
 615          $guidedefinition['guide'] = array('guide_criteria' => array($guidecriteria1, $guidecriteria2),
 616                                            'guide_comments' => array($guidecomment));
 617          $gradingarea['definitions'] = array($guidedefinition);
 618  
 619          $results = core_grading_external::save_definitions(array($gradingarea));
 620          $area = $DB->get_record('grading_areas',
 621                                  array('contextid' => $context->id, 'component' => 'mod_assign', 'areaname' => 'submissions'),
 622                                  '*', MUST_EXIST);
 623          $this->assertEquals($area->activemethod, 'guide');
 624  
 625          $definition = $DB->get_record('grading_definitions', array('areaid' => $area->id, 'method' => 'guide'), '*', MUST_EXIST);
 626          $this->assertEquals($guidedefinition['name'], $definition->name);
 627          $this->assertEquals(2, $DB->count_records('gradingform_guide_criteria', array('definitionid' => $definition->id)));
 628          $this->assertEquals(1, $DB->count_records('gradingform_guide_comments', array('definitionid' => $definition->id)));
 629  
 630          // Test removal of a criteria.
 631          $guidedefinition['guide'] = array('guide_criteria' => array($guidecriteria1),
 632                                            'guide_comments' => array($guidecomment));
 633          $gradingarea['definitions'] = array($guidedefinition);
 634          $results = core_grading_external::save_definitions(array($gradingarea));
 635          $this->assertEquals(1, $DB->count_records('gradingform_guide_criteria', array('definitionid' => $definition->id)));
 636  
 637          // Test an invalid method in the definition.
 638          $guidedefinition['method'] = 'invalid';
 639          $gradingarea['definitions'] = array($guidedefinition);
 640          $this->expectException('invalid_parameter_exception');
 641          $results = core_grading_external::save_definitions(array($gradingarea));
 642      }
 643  }