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.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]

   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 short answer question definition class.
  19   *
  20   * @package    qtype
  21   * @subpackage shortanswer
  22   * @copyright  2008 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($CFG->dirroot . '/question/engine/tests/helpers.php');
  31  require_once($CFG->dirroot . '/question/type/shortanswer/question.php');
  32  
  33  
  34  /**
  35   * Unit tests for the short answer question definition class.
  36   *
  37   * @copyright  2008 The Open University
  38   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  39   */
  40  class qtype_shortanswer_question_test extends advanced_testcase {
  41      public function test_compare_string_with_wildcard() {
  42          // Test case sensitive literal matches.
  43          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  44                  'Frog', 'Frog', false));
  45          $this->assertFalse((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  46                  'Frog', 'frog', false));
  47          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  48                  '   Frog   ', 'Frog', false));
  49          $this->assertFalse((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  50                  'Frogs', 'Frog', false));
  51  
  52          // Test case insensitive literal matches.
  53          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  54                  'Frog', 'frog', true));
  55          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  56                  '   FROG   ', 'Frog', true));
  57          $this->assertFalse((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  58                  'Frogs', 'Frog', true));
  59  
  60          // Test case sensitive wildcard matches.
  61          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  62                  'Frog', 'F*og', false));
  63          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  64                  'Fog', 'F*og', false));
  65          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  66                  '   Fat dog   ', 'F*og', false));
  67          $this->assertFalse((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  68                  'Frogs', 'F*og', false));
  69          $this->assertFalse((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  70                  'Fg', 'F*og', false));
  71          $this->assertFalse((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  72                  'frog', 'F*og', false));
  73          $this->assertFalse((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  74                  '   fat dog   ', 'F*og', false));
  75  
  76          // Test case insensitive wildcard matches.
  77          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  78                  'Frog', 'F*og', true));
  79          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  80                  'Fog', 'F*og', true));
  81          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  82                  '   Fat dog   ', 'F*og', true));
  83          $this->assertFalse((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  84                  'Frogs', 'F*og', true));
  85          $this->assertFalse((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  86                  'Fg', 'F*og', true));
  87          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  88                  'frog', 'F*og', true));
  89          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  90                  '   fat dog   ', 'F*og', true));
  91  
  92          // Test match using regexp special chars.
  93          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  94                  '   *   ', '\*', false));
  95          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  96                  '*', '\*', false));
  97          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
  98                  'Frog*toad', 'Frog\*toad', false));
  99          $this->assertFalse((bool)qtype_shortanswer_question::compare_string_with_wildcard(
 100                  'a', '[a-z]', false));
 101          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
 102                  '[a-z]', '[a-z]', false));
 103          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
 104                  '\{}/', '\{}/', true));
 105  
 106          // See http://moodle.org/mod/forum/discuss.php?d=120557.
 107          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
 108                  'ITÁLIE', 'Itálie', true));
 109  
 110          if (function_exists('normalizer_normalize')) {
 111              // Test ambiguous unicode representations.
 112              $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
 113                      'départ', 'DÉPART', true));
 114              $this->assertFalse((bool)qtype_shortanswer_question::compare_string_with_wildcard(
 115                      'départ', 'DÉPART', false));
 116              $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
 117                      'd'."\xC3\xA9".'part', 'd'."\x65\xCC\x81".'part', false));
 118              $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
 119                      'd'."\xC3\xA9".'part', 'D'."\x45\xCC\x81".'PART', true));
 120          }
 121      }
 122  
 123      public function test_compare_0_with_wildcard() {
 124          // Test the classic PHP problem case with '0'.
 125          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
 126                  '0', '0', false));
 127          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
 128                  '0', '0*', false));
 129          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
 130                  '0', '*0', false));
 131          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
 132                  '0', '*0*', false));
 133      }
 134  
 135      public function test_compare_string_with_wildcard_many_stars() {
 136          // Test the classic PHP problem case with '0'.
 137          $this->assertTrue((bool)qtype_shortanswer_question::compare_string_with_wildcard(
 138                  '<em></em>', '***********************************<em>***********************************</em>', false));
 139      }
 140  
 141      public function test_is_complete_response() {
 142          $question = test_question_maker::make_question('shortanswer');
 143  
 144          $this->assertFalse($question->is_complete_response(array()));
 145          $this->assertFalse($question->is_complete_response(array('answer' => '')));
 146          $this->assertTrue($question->is_complete_response(array('answer' => '0')));
 147          $this->assertTrue($question->is_complete_response(array('answer' => '0.0')));
 148          $this->assertTrue($question->is_complete_response(array('answer' => 'x')));
 149      }
 150  
 151      public function test_is_gradable_response() {
 152          $question = test_question_maker::make_question('shortanswer');
 153  
 154          $this->assertFalse($question->is_gradable_response(array()));
 155          $this->assertFalse($question->is_gradable_response(array('answer' => '')));
 156          $this->assertTrue($question->is_gradable_response(array('answer' => '0')));
 157          $this->assertTrue($question->is_gradable_response(array('answer' => '0.0')));
 158          $this->assertTrue($question->is_gradable_response(array('answer' => 'x')));
 159      }
 160  
 161      public function test_grading() {
 162          $question = test_question_maker::make_question('shortanswer');
 163  
 164          $this->assertEquals(array(0, question_state::$gradedwrong),
 165                  $question->grade_response(array('answer' => 'x')));
 166          $this->assertEquals(array(1, question_state::$gradedright),
 167                  $question->grade_response(array('answer' => 'frog')));
 168          $this->assertEquals(array(0.8, question_state::$gradedpartial),
 169                  $question->grade_response(array('answer' => 'toad')));
 170      }
 171  
 172      public function test_get_correct_response() {
 173          $question = test_question_maker::make_question('shortanswer');
 174  
 175          $this->assertEquals(array('answer' => 'frog'),
 176                  $question->get_correct_response());
 177      }
 178  
 179      public function test_get_correct_response_escapedwildcards() {
 180          $question = test_question_maker::make_question('shortanswer', 'escapedwildcards');
 181  
 182          $this->assertEquals(array('answer' => 'x*y'), $question->get_correct_response());
 183      }
 184  
 185      public function test_get_question_summary() {
 186          $sa = test_question_maker::make_question('shortanswer');
 187          $qsummary = $sa->get_question_summary();
 188          $this->assertEquals('Name an amphibian: __________', $qsummary);
 189      }
 190  
 191      public function test_summarise_response() {
 192          $sa = test_question_maker::make_question('shortanswer');
 193          $summary = $sa->summarise_response(array('answer' => 'dog'));
 194          $this->assertEquals('dog', $summary);
 195      }
 196  
 197      public function test_classify_response() {
 198          $sa = test_question_maker::make_question('shortanswer');
 199          $sa->start_attempt(new question_attempt_step(), 1);
 200  
 201          $this->assertEquals(array(
 202                  new question_classified_response(13, 'frog', 1.0)),
 203                  $sa->classify_response(array('answer' => 'frog')));
 204          $this->assertEquals(array(
 205                  new question_classified_response(14, 'toad', 0.8)),
 206                  $sa->classify_response(array('answer' => 'toad')));
 207          $this->assertEquals(array(
 208                  new question_classified_response(15, 'cat', 0.0)),
 209                  $sa->classify_response(array('answer' => 'cat')));
 210          $this->assertEquals(array(
 211                  question_classified_response::no_response()),
 212                  $sa->classify_response(array('answer' => '')));
 213      }
 214  
 215      public function test_classify_response_no_star() {
 216          $sa = test_question_maker::make_question('shortanswer', 'frogonly');
 217          $sa->start_attempt(new question_attempt_step(), 1);
 218  
 219          $this->assertEquals(array(
 220                  new question_classified_response(13, 'frog', 1.0)),
 221                  $sa->classify_response(array('answer' => 'frog')));
 222          $this->assertEquals(array(
 223                  new question_classified_response(0, 'toad', 0.0)),
 224                  $sa->classify_response(array('answer' => 'toad')));
 225          $this->assertEquals(array(
 226                  question_classified_response::no_response()),
 227                  $sa->classify_response(array('answer' => '')));
 228      }
 229  
 230      /**
 231       * test_get_question_definition_for_external_rendering
 232       */
 233      public function test_get_question_definition_for_external_rendering() {
 234          $this->resetAfterTest();
 235  
 236          $question = test_question_maker::make_question('shortanswer');
 237          $question->start_attempt(new question_attempt_step(), 1);
 238          $qa = test_question_maker::get_a_qa($question);
 239          $displayoptions = new question_display_options();
 240  
 241          $options = $question->get_question_definition_for_external_rendering($qa, $displayoptions);
 242          $this->assertNull($options);
 243      }
 244  }