From e39a2faa58d7cadaa80c4b3402bb69c517c01dd3 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 18 Jul 2013 10:44:46 +0700 Subject: [PATCH] MDL-40729 check marks and grades from quiz attempts compare to marks in csv file. --- .../attempt_walkthrough_from_csv_test.php | 127 +++++++++++++----- mod/quiz/tests/fixtures/results00.csv | 11 ++ mod/quiz/tests/fixtures/steps00.csv | 14 +- 3 files changed, 112 insertions(+), 40 deletions(-) create mode 100644 mod/quiz/tests/fixtures/results00.csv diff --git a/mod/quiz/tests/attempt_walkthrough_from_csv_test.php b/mod/quiz/tests/attempt_walkthrough_from_csv_test.php index dfca2b15002..553e021ccb3 100644 --- a/mod/quiz/tests/attempt_walkthrough_from_csv_test.php +++ b/mod/quiz/tests/attempt_walkthrough_from_csv_test.php @@ -128,7 +128,8 @@ class mod_quiz_attempt_walkthrough_from_csv_testcase extends advanced_testcase { foreach ($this->tests as $test) { $qs = $this->load_csv_data_file('questions', $test); $steps = $this->load_csv_data_file('steps', $test); - $dataset[] = array($qs, $steps); + $results = $this->load_csv_data_file('results', $test); + $dataset[] = array($qs, $steps, $results); } return $dataset; } @@ -156,20 +157,48 @@ class mod_quiz_attempt_walkthrough_from_csv_testcase extends advanced_testcase { return $this->createCsvDataSet($files)->getTable($setname); } + /** + * Break down row of csv data into sub arrays, according to column names. + * + * @param array $row from csv file with field names with parts separate by '.'. + * @return array the row with each part of the field name following a '.' being a separate sub array's index. + */ + protected function explode_dot_separated_keys_to_make_subindexs(array $row) { + $parts = array(); + foreach ($row as $columnkey => $value) { + $newkeys = explode('.', trim($columnkey)); + $placetoputvalue =& $parts; + foreach ($newkeys as $newkeydepth => $newkey) { + if ($newkeydepth + 1 === count($newkeys)) { + $placetoputvalue[$newkey] = $value; + } else { + // Going deeper down. + if (!isset($placetoputvalue[$newkey])) { + $placetoputvalue[$newkey] = array(); + } + $placetoputvalue =& $placetoputvalue[$newkey]; + } + } + } + return $parts; + } + /** * Create a quiz add questions to it, walk through quiz attempts and then check results. * * @param PHPUnit_Extensions_Database_DataSet_ITable $qs questions to add to quiz, read from csv file "questionsXX.csv". * @param PHPUnit_Extensions_Database_DataSet_ITable $steps steps to simulate, read from csv file "stepsXX.csv". + * @param PHPUnit_Extensions_Database_DataSet_ITable $results results expected, read from csv file "resultsXX.csv". * @dataProvider get_data_for_walkthrough */ - public function test_walkthrough_from_csv($qs, $steps) { + public function test_walkthrough_from_csv($qs, $steps, $results) { global $DB; $this->resetAfterTest(true); question_bank::get_qtype('random')->clear_caches_before_testing(); $this->create_quiz($qs); + $attemptids = array(); for ($rowno = 0; $rowno < $steps->getRowCount(); $rowno++) { $step = $this->explode_dot_separated_keys_to_make_subindexs($steps->getRow($rowno)); @@ -203,6 +232,8 @@ class mod_quiz_attempt_walkthrough_from_csv_testcase extends advanced_testcase { quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow, $step['randqs'], $step['variants']); quiz_attempt_save_started($quizobj, $quba, $attempt); + $attemptids[$step['quizattempt']] = $attempt->id; + // Process some responses from the student. $attemptobj = quiz_attempt::create($attempt->id); $attemptobj->process_submitted_actions($timenow, false, $step['responses']); @@ -211,51 +242,73 @@ class mod_quiz_attempt_walkthrough_from_csv_testcase extends advanced_testcase { $attemptobj = quiz_attempt::create($attempt->id); $attemptobj->process_finish($timenow, false); + + } + + for ($rowno = 0; $rowno < $results->getRowCount(); $rowno++) { + $result = $this->explode_dot_separated_keys_to_make_subindexs($results->getRow($rowno)); // Re-load quiz attempt data. - $attemptobj = quiz_attempt::create($attempt->id); + $attemptobj = quiz_attempt::create($attemptids[$result['quizattempt']]); + $this->check_attempt_results($result, $attemptobj); - // Check that results are stored as expected. - $this->assertEquals(1, $attemptobj->get_attempt_number()); - $this->assertEquals(true, $attemptobj->is_finished()); - $this->assertEquals($timenow, $attemptobj->get_submitted_date()); - $this->assertEquals($user->id, $attemptobj->get_userid()); - - // Check quiz grades. - $grades = quiz_get_user_grades($this->quiz, $user->id); - $grade = array_shift($grades); - $this->assertEquals(100.0, $grade->rawgrade); - - // Check grade book. - $gradebookgrades = grade_get_grades($attemptobj->get_courseid(), 'mod', 'quiz', $this->quiz->id, $user->id); - $gradebookitem = array_shift($gradebookgrades->items); - $gradebookgrade = array_shift($gradebookitem->grades); - $this->assertEquals(100, $gradebookgrade->grade); } } /** - * Break down row of csv data into sub arrays, according to column names. + * Check that attempt results are as specified in $result. * - * @param array $row from csv file with field names with parts separate by '.'. - * @return array the row with each part of the field name following a '.' being a separate sub array's index. + * @param array $result row of data read from csv file. + * @param quiz_attempt $attemptobj the attempt object loaded from db. + * @throws coding_exception */ - protected function explode_dot_separated_keys_to_make_subindexs(array $row) { - $parts = array(); - foreach ($row as $columnkey => $value) { - $newkeys = explode('.', trim($columnkey)); - $placetoputvalue =& $parts; - foreach ($newkeys as $newkeydepth => $newkey) { - if ($newkeydepth + 1 === count($newkeys)) { - $placetoputvalue[$newkey] = $value; - } else { - // Going deeper down. - if (!isset($placetoputvalue[$newkey])) { - $placetoputvalue[$newkey] = array(); + protected function check_attempt_results($result, $attemptobj) { + foreach ($result as $fieldname => $value) { + switch ($fieldname) { + case 'quizattempt' : + break; + case 'attemptnumber' : + $this->assertEquals($value, $attemptobj->get_attempt_number()); + break; + case 'slots' : + foreach ($value as $slotno => $slottests) { + foreach ($slottests as $slotfieldname => $slotvalue) { + switch ($slotfieldname) { + case 'mark' : + $this->assertEquals(round($slotvalue, 2), $attemptobj->get_question_mark($slotno), + "Mark for slot $slotno of attempt {$result['quizattempt']}."); + break; + default : + throw new coding_exception('Unknown slots sub field column in csv file ' + .s($slotfieldname)); + } + } } - $placetoputvalue =& $placetoputvalue[$newkey]; - } + break; + case 'finished' : + $this->assertEquals($value, $attemptobj->is_finished()); + break; + case 'summarks' : + $this->assertEquals($value, $attemptobj->get_sum_marks(), "Sum of marks of attempt {$result['quizattempt']}."); + break; + case 'quizgrade' : + // Check quiz grades. + $grades = quiz_get_user_grades($attemptobj->get_quiz(), $attemptobj->get_userid()); + $grade = array_shift($grades); + $this->assertEquals($value, $grade->rawgrade, "Quiz grade for attempt {$result['quizattempt']}."); + break; + case 'gradebookgrade' : + // Check grade book. + $gradebookgrades = grade_get_grades($attemptobj->get_courseid(), + 'mod', 'quiz', + $attemptobj->get_quizid(), + $attemptobj->get_userid()); + $gradebookitem = array_shift($gradebookgrades->items); + $gradebookgrade = array_shift($gradebookitem->grades); + $this->assertEquals($value, $gradebookgrade->grade, "Gradebook grade for attempt {$result['quizattempt']}."); + break; + default : + throw new coding_exception('Unknown column in csv file '.s($fieldname)); } } - return $parts; } } diff --git a/mod/quiz/tests/fixtures/results00.csv b/mod/quiz/tests/fixtures/results00.csv new file mode 100644 index 00000000000..95e9afbc2f5 --- /dev/null +++ b/mod/quiz/tests/fixtures/results00.csv @@ -0,0 +1,11 @@ +quizattempt,slots.1.mark,slots.2.mark,slots.3.mark,slots.4.mark,slots.5.mark,slots.6.mark,slots.7.mark,summarks +1,0.8,1,1,1,0.5,1,0,5.3 +2,1,0,1,1,0.5,0,0.5,4 +3,0,1,1,0,0.5,0,0.5,3 +4,0,1,0.3333333,1,1,1,1,5.33333 +5,1,1,1,1,0.5,1,1,6.5 +6,0,1,1,1,0.5,1,1,5.5 +7,0,0,1,0,0.5,0,0,1.5 +8,0.8,1,1,1,0.5,1,0,5.3 +9,0,0,0.3333333,0,0.5,1,1,2.83333 +10,0.8,1,1,1,0.5,1,0.5,5.8 diff --git a/mod/quiz/tests/fixtures/steps00.csv b/mod/quiz/tests/fixtures/steps00.csv index 8eb77fa1449..a44c003a9c4 100644 --- a/mod/quiz/tests/fixtures/steps00.csv +++ b/mod/quiz/tests/fixtures/steps00.csv @@ -1,3 +1,11 @@ -quizattempt,firstname,lastname,randqs.1,responses.1.answer,responses.2.answer,variants.2,responses.3.0,responses.3.1,responses.3.2,responses.4.answer,responses.5.0,responses.5.1,responses.5.2,responses.5.3,responses.6.answer,responses.7.1.answer,responses.7.2.answer -1,John,Doe,shortanswer,frog,3.3,3,amphibian,mammal,amphibian,1,1,0,1,0,0,Owl,2 -2,Jane,Doe,numerical,3.14,19.4,4,amphibian,mammal,amphibian,1,1,0,1,0,0,Owl,2 +quizattempt,firstname,lastname,randqs.1,responses.1.answer,variants.2,responses.2.answer,responses.3.0,responses.3.1,responses.3.2,responses.4.answer,responses.5.0,responses.5.1,responses.5.2,responses.5.3,responses.6.answer,responses.7.1.answer,responses.7.2.answer +1,John,Jones,shortanswer,toad,4,19.4,amphibian,mammal,amphibian,1,0,1,1,0,0,Pussy-cat,0 +2,John,Smith,shortanswer,frog,6,-0.6,amphibian,mammal,amphibian,1,1,1,0,0,3,Dog,2 +3,John,Vicars,numerical,3.142,4,19.4,amphibian,mammal,amphibian,0,0,0,1,1,1,Owl,1 +4,John,Pacino,numerical,3.142,6,9.4,mammal,amphibian,amphibian,1,1,0,1,0,0,Owl,2 +5,John,Deniro,shortanswer,frog,9,7.1,amphibian,mammal,amphibian,1,0,0,1,1,0,Owl,2 +6,John,Banks,numerical,3.1,7,9.1,amphibian,mammal,amphibian,1,1,0,0,1,0,Owl,2 +7,John,Asimov,numerical,2.5,3,-0.2,amphibian,mammal,amphibian,0,1,1,0,0,1,Dog,1 +8,John,Chomsky,shortanswer,toad,2,8.5,amphibian,mammal,amphibian,1,0,0,1,1,0,Dog,1 +9,John,Yamaguchi,shortanswer,tadpole,5,-0.1,amphibian,amphibian,mammal,0,1,1,0,0,0,Owl,2 +10,John,Robbins,shortanswer,toad,7,9.1,amphibian,mammal,amphibian,1,1,0,0,1,0,Owl,1