mirror of
https://github.com/moodle/moodle.git
synced 2025-03-21 16:10:15 +01:00
MDL-76362 qtype_numeric: Refactor answer tests
This commit is contained in:
parent
4ff3447c8c
commit
5f412b3301
@ -27,17 +27,6 @@ namespace qtype_numerical;
|
||||
|
||||
use qtype_numerical_answer_processor;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot . '/question/type/numerical/questiontype.php');
|
||||
|
||||
class testable_qtype_numerical_answer_processor extends qtype_numerical_answer_processor {
|
||||
public function parse_response($response) {
|
||||
return parent::parse_response($response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unit test for the numerical questions answers processor.
|
||||
*
|
||||
@ -45,60 +34,109 @@ class testable_qtype_numerical_answer_processor extends qtype_numerical_answer_p
|
||||
* @category test
|
||||
* @copyright 2008 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @covers \qtype_numerical_answer_processor
|
||||
*/
|
||||
class answerprocessor_test extends \advanced_testcase {
|
||||
public function test_parse_response() {
|
||||
$ap = new testable_qtype_numerical_answer_processor(
|
||||
array('m' => 1, 'cm' => 100), false, '.', ',');
|
||||
/**
|
||||
* Test setup.
|
||||
*/
|
||||
public function setUp(): void {
|
||||
global $CFG;
|
||||
|
||||
$this->assertEquals(array('3', '142', '', ''), $ap->parse_response('3.142'));
|
||||
$this->assertEquals(array('', '2', '', ''), $ap->parse_response('.2'));
|
||||
$this->assertEquals(array('1', '', '', ''), $ap->parse_response('1.'));
|
||||
$this->assertEquals(array('1', '0', '', ''), $ap->parse_response('1.0'));
|
||||
$this->assertEquals(array('-1', '', '', ''), $ap->parse_response('-1.'));
|
||||
$this->assertEquals(array('+1', '0', '', ''), $ap->parse_response('+1.0'));
|
||||
|
||||
$this->assertEquals(array('1', '', '4', ''), $ap->parse_response('1e4'));
|
||||
$this->assertEquals(array('3', '142', '-4', ''), $ap->parse_response('3.142E-4'));
|
||||
$this->assertEquals(array('', '2', '+2', ''), $ap->parse_response('.2e+2'));
|
||||
$this->assertEquals(array('1', '', '-1', ''), $ap->parse_response('1.e-1'));
|
||||
$this->assertEquals(array('1', '0', '0', ''), $ap->parse_response('1.0e0'));
|
||||
|
||||
$this->assertEquals(array('3', '', '8', ''), $ap->parse_response('3x10^8'));
|
||||
$this->assertEquals(array('3', '', '8', ''), $ap->parse_response('3×10^8'));
|
||||
$this->assertEquals(array('3', '0', '8', ''), $ap->parse_response('3.0*10^8'));
|
||||
$this->assertEquals(array('3', '00', '-8', ''), $ap->parse_response('3.00x10**-8'));
|
||||
$this->assertEquals(array('0', '001', '7', ''), $ap->parse_response('0.001×10**7'));
|
||||
|
||||
$this->assertEquals(array('1', '', '', 'm'), $ap->parse_response('1m'));
|
||||
$this->assertEquals(array('3', '142', '', 'm'), $ap->parse_response('3.142 m'));
|
||||
$this->assertEquals(array('', '2', '', 'm'), $ap->parse_response('.2m'));
|
||||
$this->assertEquals(array('1', '', '', 'cm'), $ap->parse_response('1.cm'));
|
||||
$this->assertEquals(array('1', '0', '', 'cm'), $ap->parse_response('1.0 cm'));
|
||||
$this->assertEquals(array('-1', '', '', 'm'), $ap->parse_response('-1.m'));
|
||||
$this->assertEquals(array('+1', '0', '', 'cm'), $ap->parse_response('+1.0cm'));
|
||||
|
||||
$this->assertEquals(array('1', '', '4', 'm'), $ap->parse_response('1e4 m'));
|
||||
$this->assertEquals(array('3', '142', '-4', 'cm'), $ap->parse_response('3.142E-4 cm'));
|
||||
$this->assertEquals(array('', '2', '+2', 'm'), $ap->parse_response('.2e+2m'));
|
||||
$this->assertEquals(array('1', '', '-1', 'm'), $ap->parse_response('1.e-1 m'));
|
||||
$this->assertEquals(array('1', '0', '0', 'cm'), $ap->parse_response('1.0e0cm'));
|
||||
|
||||
$this->assertEquals(array('1000000', '', '', ''),
|
||||
$ap->parse_response('1,000,000'));
|
||||
$this->assertEquals(array('1000', '00', '', 'm'),
|
||||
$ap->parse_response('1,000.00 m'));
|
||||
|
||||
$this->assertEquals(array(null, null, null, null), $ap->parse_response('frog'));
|
||||
$this->assertEquals(array('3', '', '', 'frogs'), $ap->parse_response('3 frogs'));
|
||||
$this->assertEquals(array(null, null, null, null), $ap->parse_response('. m'));
|
||||
$this->assertEquals(array(null, null, null, null), $ap->parse_response('.e8 m'));
|
||||
$this->assertEquals(array(null, null, null, null), $ap->parse_response(','));
|
||||
require_once("{$CFG->dirroot}/question/type/numerical/questiontype.php");
|
||||
}
|
||||
|
||||
protected function verify_value_and_unit($exectedval, $expectedunit, $expectedmultiplier,
|
||||
qtype_numerical_answer_processor $ap, $input, $separateunit = null) {
|
||||
list($val, $unit, $multiplier) = $ap->apply_units($input, $separateunit);
|
||||
/**
|
||||
* Test the parse_response function.
|
||||
*
|
||||
* @covers ::parse_response
|
||||
* @dataProvider parse_response_provider
|
||||
* @param array $expected
|
||||
* @param mixed $args
|
||||
*/
|
||||
public function test_parse_response(array $expected, $args): void {
|
||||
$ap = new qtype_numerical_answer_processor([
|
||||
'm' => 1,
|
||||
'cm' => 100,
|
||||
], false, '.', ',');
|
||||
|
||||
$rc = new \ReflectionClass($ap);
|
||||
$rcm = $rc->getMethod('parse_response');
|
||||
$rcm->setAccessible(True);
|
||||
|
||||
$this->assertEquals($expected, $rcm->invoke($ap, $args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for the parse_response function.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function parse_response_provider(): array {
|
||||
return [
|
||||
[['3', '142', '', ''], '3.142'],
|
||||
[['', '2', '', ''], '.2'],
|
||||
[['1', '', '', ''], '1.'],
|
||||
[['1', '0', '', ''], '1.0'],
|
||||
[['-1', '', '', ''], '-1.'],
|
||||
[['+1', '0', '', ''], '+1.0'],
|
||||
|
||||
[['1', '', '4', ''], '1e4'],
|
||||
[['3', '142', '-4', ''], '3.142E-4'],
|
||||
[['', '2', '+2', ''], '.2e+2'],
|
||||
[['1', '', '-1', ''], '1.e-1'],
|
||||
[['1', '0', '0', ''], '1.0e0'],
|
||||
|
||||
[['3', '', '8', ''], '3x10^8'],
|
||||
[['3', '', '8', ''], '3×10^8'],
|
||||
[['3', '0', '8', ''], '3.0*10^8'],
|
||||
[['3', '00', '-8', ''], '3.00x10**-8'],
|
||||
[['0', '001', '7', ''], '0.001×10**7'],
|
||||
|
||||
[['1', '', '', 'm'], '1m'],
|
||||
[['3', '142', '', 'm'], '3.142 m'],
|
||||
[['', '2', '', 'm'], '.2m'],
|
||||
[['1', '', '', 'cm'], '1.cm'],
|
||||
[['1', '0', '', 'cm'], '1.0 cm'],
|
||||
[['-1', '', '', 'm'], '-1.m'],
|
||||
[['+1', '0', '', 'cm'], '+1.0cm'],
|
||||
|
||||
[['1', '', '4', 'm'], '1e4 m'],
|
||||
[['3', '142', '-4', 'cm'], '3.142E-4 cm'],
|
||||
[['', '2', '+2', 'm'], '.2e+2m'],
|
||||
[['1', '', '-1', 'm'], '1.e-1 m'],
|
||||
[['1', '0', '0', 'cm'], '1.0e0cm'],
|
||||
|
||||
[['1000000', '', '', ''], '1,000,000'],
|
||||
[['1000', '00', '', 'm'], '1,000.00 m'],
|
||||
|
||||
[[null, null, null, null], 'frog'],
|
||||
[['3', '', '', 'frogs'], '3 frogs'],
|
||||
[[null, null, null, null], '. m'],
|
||||
[[null, null, null, null], '.e8 m'],
|
||||
[[null, null, null, null], ','],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Call apply_units and verify the value and units returned.
|
||||
*
|
||||
* @param int|float $exectedval
|
||||
* @param null|string $expectedunit
|
||||
* @param int|float $expectedmultiplier
|
||||
* @param qtype_numerical_answer_processor $ap
|
||||
* @param null|int|float $input
|
||||
* @param null|string $separateunit
|
||||
*/
|
||||
protected function verify_value_and_unit(
|
||||
$exectedval,
|
||||
$expectedunit,
|
||||
$expectedmultiplier,
|
||||
qtype_numerical_answer_processor $ap,
|
||||
$input,
|
||||
$separateunit = null
|
||||
): void {
|
||||
[$val, $unit, $multiplier] = $ap->apply_units($input, $separateunit);
|
||||
if (is_null($exectedval)) {
|
||||
$this->assertNull($val);
|
||||
} else {
|
||||
@ -112,57 +150,195 @@ class answerprocessor_test extends \advanced_testcase {
|
||||
}
|
||||
}
|
||||
|
||||
public function test_apply_units() {
|
||||
/**
|
||||
* Test the apply_units function with various parameters.
|
||||
*
|
||||
* @covers \qtype_numerical_answer_processor::apply_units
|
||||
* @dataProvider apply_units_provider
|
||||
* @param mixed $expectedvalue
|
||||
* @param string|null $expectedunit
|
||||
* @param float|int|null $expectedmultiplier
|
||||
* @param string|null $input
|
||||
*/
|
||||
public function test_apply_units(
|
||||
$expectedvalue,
|
||||
$expectedunit,
|
||||
$expectedmultiplier,
|
||||
$input
|
||||
): void {
|
||||
$ap = new qtype_numerical_answer_processor(
|
||||
array('m/s' => 1, 'c' => 3.3356409519815E-9,
|
||||
'mph' => 2.2369362920544), false, '.', ',');
|
||||
[
|
||||
'm/s' => 1,
|
||||
'c' => 3.3356409519815E-9,
|
||||
'mph' => 2.2369362920544
|
||||
],
|
||||
false,
|
||||
'.',
|
||||
','
|
||||
);
|
||||
|
||||
$this->verify_value_and_unit(3e8, 'm/s', 1, $ap, '3x10^8 m/s');
|
||||
$this->verify_value_and_unit(3e8, '', null, $ap, '3x10^8');
|
||||
$this->verify_value_and_unit(1, 'c', 299792458, $ap, '1c');
|
||||
$this->verify_value_and_unit(1, 'mph', 0.44704, $ap, '0001.000 mph');
|
||||
|
||||
$this->verify_value_and_unit(1, 'frogs', null, $ap, '1 frogs');
|
||||
$this->verify_value_and_unit(null, null, null, $ap, '. m/s');
|
||||
$this->verify_value_and_unit(
|
||||
$expectedvalue,
|
||||
$expectedunit,
|
||||
$expectedmultiplier,
|
||||
$ap,
|
||||
$input
|
||||
);
|
||||
}
|
||||
|
||||
public function test_apply_units_separate_unit() {
|
||||
/**
|
||||
* Data provider for apply_units tests.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function apply_units_provider(): array {
|
||||
return [
|
||||
[3e8, 'm/s', 1, '3x10^8 m/s'],
|
||||
[3e8, '', null, '3x10^8'],
|
||||
[1, 'c', 299792458, '1c'],
|
||||
[1, 'mph', 0.44704, '0001.000 mph'],
|
||||
|
||||
[1, 'frogs', null, '1 frogs'],
|
||||
[null, null, null, '. m/s'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the apply_units function with various parameters and different units.
|
||||
*
|
||||
* @covers \qtype_numerical_answer_processor::apply_units
|
||||
* @dataProvider apply_units_provider_with_units
|
||||
* @param mixed $expectedvalue
|
||||
* @param string|null $expectedunit
|
||||
* @param float|int|null $expectedmultiplier
|
||||
* @param string|null $input
|
||||
* @param string $units
|
||||
*/
|
||||
public function test_apply_units_with_unit(
|
||||
$expectedvalue,
|
||||
$expectedunit,
|
||||
$expectedmultiplier,
|
||||
$input,
|
||||
$units
|
||||
): void {
|
||||
$ap = new qtype_numerical_answer_processor(
|
||||
array('m/s' => 1, 'c' => 3.3356409519815E-9,
|
||||
'mph' => 2.2369362920544), false, '.', ',');
|
||||
[
|
||||
'm/s' => 1,
|
||||
'c' => 3.3356409519815E-9,
|
||||
'mph' => 2.2369362920544
|
||||
],
|
||||
false,
|
||||
'.',
|
||||
','
|
||||
);
|
||||
|
||||
$this->verify_value_and_unit(3e8, 'm/s', 1, $ap, '3x10^8', 'm/s');
|
||||
$this->verify_value_and_unit(3e8, '', null, $ap, '3x10^8', '');
|
||||
$this->verify_value_and_unit(1, 'c', 299792458, $ap, '1', 'c');
|
||||
$this->verify_value_and_unit(1, 'mph', 0.44704, $ap, '0001.000', 'mph');
|
||||
|
||||
$this->verify_value_and_unit(1, 'frogs', null, $ap, '1', 'frogs');
|
||||
$this->verify_value_and_unit(null, null, null, $ap, '.', 'm/s');
|
||||
$this->verify_value_and_unit(
|
||||
$expectedvalue,
|
||||
$expectedunit,
|
||||
$expectedmultiplier,
|
||||
$ap,
|
||||
$input,
|
||||
$units
|
||||
);
|
||||
}
|
||||
|
||||
public function test_euro_style() {
|
||||
$ap = new qtype_numerical_answer_processor(array(), false, ',', ' ');
|
||||
/**
|
||||
* Data provider for apply_units with different units.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function apply_units_provider_with_units(): array {
|
||||
return [
|
||||
[3e8, 'm/s', 1, '3x10^8', 'm/s'],
|
||||
[3e8, '', null, '3x10^8', ''],
|
||||
[1, 'c', 299792458, '1', 'c'],
|
||||
[1, 'mph', 0.44704, '0001.000', 'mph'],
|
||||
|
||||
$this->assertEquals(array(-1000, '', null), $ap->apply_units('-1 000'));
|
||||
$this->assertEquals(array(3.14159, '', null), $ap->apply_units('3,14159'));
|
||||
[1, 'frogs', null, '1', 'frogs'],
|
||||
[null, null, null, '.', 'm/s'],
|
||||
];
|
||||
}
|
||||
|
||||
public function test_percent() {
|
||||
$ap = new qtype_numerical_answer_processor(array('%' => 100), false, '.', ',');
|
||||
|
||||
$this->assertEquals(array('3', '%', 0.01), $ap->apply_units('3%'));
|
||||
$this->assertEquals(array('1e-6', '%', 0.01), $ap->apply_units('1e-6 %'));
|
||||
$this->assertEquals(array('100', '', null), $ap->apply_units('100'));
|
||||
/**
|
||||
* Test apply_units with a comma float unit.
|
||||
*
|
||||
* @covers \qtype_numerical_answer_processor::apply_units
|
||||
* @dataProvider euro_provider
|
||||
* @param array $expected
|
||||
* @param string $params
|
||||
*/
|
||||
public function test_euro_style(array $expected, string $params): void {
|
||||
$ap = new qtype_numerical_answer_processor([], false, ',', ' ');
|
||||
$this->assertEquals($expected, $ap->apply_units($params));
|
||||
}
|
||||
|
||||
public function test_currency() {
|
||||
$ap = new qtype_numerical_answer_processor(array('$' => 1, '£' => 1), true, '.', ',');
|
||||
/**
|
||||
* Data provider for apply_units with euro float separators.
|
||||
*
|
||||
* return array
|
||||
*/
|
||||
public function euro_provider(): array {
|
||||
return [
|
||||
[[-1000, '', null], '-1 000'],
|
||||
[[3.14159, '', null], '3,14159'],
|
||||
];
|
||||
}
|
||||
|
||||
$this->assertEquals(array('1234.56', '£', 1), $ap->apply_units('£1,234.56'));
|
||||
$this->assertEquals(array('100', '$', 1), $ap->apply_units('$100'));
|
||||
$this->assertEquals(array('100', '$', 1), $ap->apply_units('$100.'));
|
||||
$this->assertEquals(array('100.00', '$', 1), $ap->apply_units('$100.00'));
|
||||
$this->assertEquals(array('100', '', null), $ap->apply_units('100'));
|
||||
$this->assertEquals(array('100', 'frog', null), $ap->apply_units('frog 100'));
|
||||
/**
|
||||
* Test apply_units with percentage values.
|
||||
*
|
||||
* @covers \qtype_numerical_answer_processor::apply_units
|
||||
* @dataProvider percent_provider
|
||||
* @param array $expected
|
||||
* @param string $params
|
||||
*/
|
||||
public function test_percent(array $expected, string $params): void {
|
||||
$ap = new qtype_numerical_answer_processor(['%' => 100], false, '.', ',');
|
||||
$this->assertEquals($expected, $ap->apply_units($params));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for apply_units with percentages.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function percent_provider(): array {
|
||||
return [
|
||||
[['3', '%', 0.01], '3%'],
|
||||
[['1e-6', '%', 0.01], '1e-6 %'],
|
||||
[['100', '', null], '100'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test apply_units with currency values.
|
||||
*
|
||||
* @covers \qtype_numerical_answer_processor::apply_units
|
||||
* @dataProvider currency_provider
|
||||
* @param array $expected
|
||||
* @param string $params
|
||||
*/
|
||||
public function test_currency(array $expected, string $params): void {
|
||||
$ap = new qtype_numerical_answer_processor([
|
||||
'$' => 1,
|
||||
'£' => 1,
|
||||
], true, '.', ',');
|
||||
$this->assertEquals($expected, $ap->apply_units($params));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for apply_units with currency values.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function currency_provider(): array {
|
||||
return [
|
||||
[['1234.56', '£', 1], '£1,234.56'],
|
||||
[['100', '$', 1], '$100'],
|
||||
[['100', '$', 1], '$100.'],
|
||||
[['100.00', '$', 1], '$100.00'],
|
||||
[['100', '', null], '100'],
|
||||
[['100', 'frog', null], 'frog 100'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
31
question/type/numerical/tests/coverage.php
Normal file
31
question/type/numerical/tests/coverage.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Coverage information for the qtype_numerical.
|
||||
*
|
||||
* @copyright 2022 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
return new class extends phpunit_coverage_info {
|
||||
/** @var array The list of files relative to the plugin root to include in coverage generation. */
|
||||
protected $includelistfiles = [
|
||||
'question.php',
|
||||
'questiontype.php',
|
||||
];
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user