MDL-79905 qtype_ordering: Improve test coverage for question ordering

Part of: MDL-79863
This commit is contained in:
Mathew May 2024-01-04 13:57:02 +08:00
parent ec320c2e49
commit 63ed08c050
3 changed files with 113 additions and 4 deletions

View File

@ -789,6 +789,7 @@ class qtype_ordering_question extends question_graded_automatically {
*
* @param int|null $type
* @return array|string array if $type is not specified and single string if $type is specified
* @codeCoverageIgnore
*/
public static function get_select_types(int $type = null): array|string {
$plugin = 'qtype_ordering';
@ -805,6 +806,7 @@ class qtype_ordering_question extends question_graded_automatically {
*
* @param int|null $type
* @return array|string array if $type is not specified and single string if $type is specified
* @codeCoverageIgnore
*/
public static function get_layout_types(int $type = null): array|string {
$plugin = 'qtype_ordering';
@ -820,6 +822,7 @@ class qtype_ordering_question extends question_graded_automatically {
*
* @param int|null $type
* @return array|string array if $type is not specified and single string if $type is specified
* @codeCoverageIgnore
*/
public static function get_grading_types(int $type = null): array|string {
$plugin = 'qtype_ordering';
@ -846,6 +849,7 @@ class qtype_ordering_question extends question_graded_automatically {
* @param string|null $style The specific numbering style to retrieve.
* @return array|string Numbering style(s).
* The keys are style identifiers, and the values are the corresponding language strings.
* @codeCoverageIgnore
*/
public static function get_numbering_styles(string $style = null): array|string {
$plugin = 'qtype_ordering';

View File

@ -44,20 +44,23 @@ class specific_grade_detail_feedback_test extends advanced_testcase {
* @param int $gradingtype Grading type.
* @param string $layouttype The type of the layout.
* @param array $expected The expected exported data.
* @param int $selecttype The type of the select.
* @return void
* @covers ::export_for_template
*/
public function test_export_for_template(array $answeritems, int $gradingtype, string $layouttype, array $expected): void {
public function test_export_for_template(array $answeritems, int $gradingtype, string $layouttype, array $expected, int $selecttype): void {
global $PAGE;
$this->resetAfterTest();
$question = test_question_maker::make_question('ordering');
// Options need to be set before starting the attempt otherwise they are not passed along.
$question->options->layouttype = $layouttype === 'horizontal' ? qtype_ordering_question::LAYOUT_HORIZONTAL :
qtype_ordering_question::LAYOUT_VERTICAL;
$question->options->gradingtype = $gradingtype;
$question->options->selecttype = $selecttype;
$qa = new \testable_question_attempt($question, 0);
$step = new \question_attempt_step();
$qa->add_step($step);
$question->start_attempt($step, 1);
$question->options->gradingtype = $gradingtype;
$keys = implode(',', array_keys($answeritems));
$values = array_values($answeritems);
@ -71,7 +74,16 @@ class specific_grade_detail_feedback_test extends advanced_testcase {
$specificgradedetailfeedback = new specific_grade_detail_feedback($qa);
$actual = $specificgradedetailfeedback->export_for_template($renderer);
$this->assertEquals($expected, $actual);
if ($selecttype === qtype_ordering_question::SELECT_ALL) {
$this->assertEquals($expected, $actual);
} else {
// Since the order of the scores is random or contiguous, we need to check the score details separately.
$this->assertEquals($expected['showpartialwrong'], $actual['showpartialwrong']);
$this->assertEquals($expected['gradingtype'], $actual['gradingtype']);
$this->assertEquals($expected['orderinglayoutclass'], $actual['orderinglayoutclass']);
$this->assertEquals($expected['totalmaxscore'], $actual['totalmaxscore']);
$this->assertArrayHasKey('scoredetails', $actual);
}
}
/**
@ -91,6 +103,7 @@ class specific_grade_detail_feedback_test extends advanced_testcase {
[
'showpartialwrong' => false,
],
qtype_ordering_question::SELECT_ALL,
],
'Partially correct question attempt (horizontal layout). Relative to ALL the previous and next items' => [
[13 => 'Modular', 14 => 'Object', 15 => 'Oriented', 17 => 'Learning', 16 => 'Dynamic', 18 => 'Environment'],
@ -112,6 +125,7 @@ class specific_grade_detail_feedback_test extends advanced_testcase {
['score' => 5, 'maxscore' => 5, 'percent' => 100],
],
],
qtype_ordering_question::SELECT_ALL,
],
'Incorrect question attempt (horizontal layout). Relative to ALL the previous and next items' => [
[14 => 'Object', 16 => 'Dynamic', 13 => 'Modular', 17 => 'Learning', 18 => 'Environment', 15 => 'Oriented'],
@ -133,6 +147,7 @@ class specific_grade_detail_feedback_test extends advanced_testcase {
['score' => 2, 'maxscore' => 5, 'percent' => 40],
],
],
qtype_ordering_question::SELECT_ALL,
],
'Incorrect question attempt (vertical layout). Grading type: Relative to the next item (excluding last)' => [
[14 => 'Object', 16 => 'Dynamic', 13 => 'Modular', 17 => 'Learning', 18 => 'Environment', 15 => 'Oriented'],
@ -154,6 +169,73 @@ class specific_grade_detail_feedback_test extends advanced_testcase {
['score' => 0, 'maxscore' => 1, 'percent' => 0.0],
],
],
qtype_ordering_question::SELECT_ALL,
],
'Incorrect question attempt (vertical layout). Grading type: GRADING_LONGEST_ORDERED_SUBSET' => [
[14 => 'Object', 16 => 'Dynamic', 13 => 'Modular', 17 => 'Learning', 18 => 'Environment', 15 => 'Oriented'],
qtype_ordering_question::GRADING_LONGEST_ORDERED_SUBSET,
'vertical',
[
'showpartialwrong' => 1,
'gradingtype' => 'Grading type: Longest ordered subset',
'orderinglayoutclass' => 'vertical',
'gradedetails' => 67.0,
'totalscore' => 4,
'totalmaxscore' => 6,
'scoredetails' => [
['score' => 1, 'maxscore' => 1, 'percent' => 100.0],
['score' => 1, 'maxscore' => 1, 'percent' => 100.0],
['score' => 0, 'maxscore' => 1, 'percent' => 0.0],
['score' => 1, 'maxscore' => 1, 'percent' => 100.0],
['score' => 1, 'maxscore' => 1, 'percent' => 100.0],
['score' => 0, 'maxscore' => 1, 'percent' => 0.0],
],
],
qtype_ordering_question::SELECT_ALL,
],
'Incorrect question attempt (SELECT_RANDOM). Grading type: GRADING_ABSOLUTE_POSITION' => [
[14 => 'Object', 16 => 'Dynamic', 13 => 'Modular', 17 => 'Learning', 18 => 'Environment', 15 => 'Oriented'],
qtype_ordering_question::GRADING_ABSOLUTE_POSITION,
'vertical',
[
'showpartialwrong' => 1,
'gradingtype' => 'Grading type: Absolute position',
'orderinglayoutclass' => 'vertical',
'gradedetails' => 0,
'totalscore' => 0,
'totalmaxscore' => 3,
'scoredetails' => [
['score' => 0, 'maxscore' => 1, 'percent' => 0.0],
['score' => 0, 'maxscore' => 1, 'percent' => 0.0],
['score' => 0, 'maxscore' => 1, 'percent' => 0.0],
['score' => 'No score', 'maxscore' => null, 'percent' => 0],
['score' => 'No score', 'maxscore' => null, 'percent' => 0],
['score' => 'No score', 'maxscore' => null, 'percent' => 0],
],
],
qtype_ordering_question::SELECT_RANDOM,
],
'Incorrect question attempt (SELECT_CONTIGUOUS). Grading type: GRADING_ABSOLUTE_POSITION' => [
[14 => 'Object', 16 => 'Dynamic', 13 => 'Modular', 17 => 'Learning', 18 => 'Environment', 15 => 'Oriented'],
qtype_ordering_question::GRADING_ABSOLUTE_POSITION,
'vertical',
[
'showpartialwrong' => 1,
'gradingtype' => 'Grading type: Absolute position',
'orderinglayoutclass' => 'vertical',
'gradedetails' => 0,
'totalscore' => 0,
'totalmaxscore' => 3,
'scoredetails' => [
['score' => 0, 'maxscore' => 1, 'percent' => 0],
['score' => 1, 'maxscore' => 1, 'percent' => 100.0],
['score' => 0, 'maxscore' => 1, 'percent' => 0],
['score' => 'No score', 'maxscore' => null, 'percent' => 0],
['score' => 'No score', 'maxscore' => null, 'percent' => 0],
['score' => 'No score', 'maxscore' => null, 'percent' => 0],
],
],
qtype_ordering_question::SELECT_CONTIGUOUS,
],
];
}

View File

@ -555,6 +555,15 @@ class question_test extends \advanced_testcase {
)
);
$this->assertEquals($expected, $actual);
// Confirm that if a passed array contains an item that does not exist in the question, it is ignored.
$actual = $question->summarise_response(
qtype_ordering_test_helper::get_response(
$question,
['notexist']
)
);
$this->assertEquals('', $actual);
}
public function test_initialise_question_instance(): void {
@ -575,6 +584,10 @@ class question_test extends \advanced_testcase {
} else if ($question->options->layouttype === 1) {
$this->assertEquals('horizontal', $question->get_ordering_layoutclass());
}
// Confirm that if an invalid layouttype is set, an empty string is returned.
$question->options->layouttype = 3;
$error = $question->get_ordering_layoutclass();
$this->assertEquals('', $error);
}
public function test_get_next_answerids(): void {
@ -795,4 +808,14 @@ class question_test extends \advanced_testcase {
$newq->update_attempt_state_data_for_new_version($oldstep, $question)
);
}
public function test_helpers(): void {
$question = test_question_maker::make_question('ordering');
$this->assertEquals(true, $question->is_complete_response([]));
$this->assertEquals(true, $question->is_gradable_response([]));
$this->assertEquals('', $question->get_validation_error([]));
$this->expectException(\coding_exception::class);
qtype_ordering_question::get_types(['foo', 'bar', 'baz'], 'notexist');
}
}