From 764f6153d18710d11e2862d284a9949e0905d191 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 3 Sep 2013 20:15:59 +0700 Subject: [PATCH] MDL-41572 pass through question behaviour vars with correct prefix Through prepare_simulated_post_data. Also includes unit tests for multiple attempts and tries. --- .../statistics/tests/fixtures/quizzes.csv | 2 + .../stats_from_steps_walkthrough_test.php | 4 +- .../attempt_walkthrough_from_csv_test.php | 98 +++++++++++-------- mod/quiz/tests/fixtures/questions01.csv | 2 + mod/quiz/tests/fixtures/quizzes.csv | 3 + mod/quiz/tests/fixtures/results01.csv | 9 ++ mod/quiz/tests/fixtures/steps01.csv | 21 ++++ question/engine/questionusage.php | 18 +++- 8 files changed, 111 insertions(+), 46 deletions(-) create mode 100644 mod/quiz/report/statistics/tests/fixtures/quizzes.csv create mode 100644 mod/quiz/tests/fixtures/questions01.csv create mode 100644 mod/quiz/tests/fixtures/quizzes.csv create mode 100644 mod/quiz/tests/fixtures/results01.csv create mode 100644 mod/quiz/tests/fixtures/steps01.csv diff --git a/mod/quiz/report/statistics/tests/fixtures/quizzes.csv b/mod/quiz/report/statistics/tests/fixtures/quizzes.csv new file mode 100644 index 00000000000..1a3aaa8975d --- /dev/null +++ b/mod/quiz/report/statistics/tests/fixtures/quizzes.csv @@ -0,0 +1,2 @@ +testnumber,preferredbehaviour +00,deferredfeedback diff --git a/mod/quiz/report/statistics/tests/stats_from_steps_walkthrough_test.php b/mod/quiz/report/statistics/tests/stats_from_steps_walkthrough_test.php index 5fdc4534d3a..50169d6e262 100644 --- a/mod/quiz/report/statistics/tests/stats_from_steps_walkthrough_test.php +++ b/mod/quiz/report/statistics/tests/stats_from_steps_walkthrough_test.php @@ -79,7 +79,7 @@ class quiz_report_statistics_from_steps extends mod_quiz_attempt_walkthrough_fro * "stepsXX.csv" and "resultsXX.csv". * @dataProvider get_data_for_walkthrough */ - public function test_walkthrough_from_csv($csvdata) { + public function test_walkthrough_from_csv($quizsettings, $csvdata) { // CSV data files for these tests were generated using : // https://github.com/jamiepratt/moodle-quiz-tools/tree/master/responsegenerator @@ -87,7 +87,7 @@ class quiz_report_statistics_from_steps extends mod_quiz_attempt_walkthrough_fro $this->resetAfterTest(true); question_bank::get_qtype('random')->clear_caches_before_testing(); - $this->create_quiz($csvdata['questions']); + $this->create_quiz($quizsettings, $csvdata['questions']); $attemptids = $this->walkthrough_attempts($csvdata['steps']); diff --git a/mod/quiz/tests/attempt_walkthrough_from_csv_test.php b/mod/quiz/tests/attempt_walkthrough_from_csv_test.php index 6ab298f591f..ec5c2ee930b 100644 --- a/mod/quiz/tests/attempt_walkthrough_from_csv_test.php +++ b/mod/quiz/tests/attempt_walkthrough_from_csv_test.php @@ -41,11 +41,6 @@ require_once($CFG->dirroot . '/mod/quiz/locallib.php'); */ class mod_quiz_attempt_walkthrough_from_csv_testcase extends advanced_testcase { - /** - * @var array postfix number for sets of csv files to load data from. - */ - protected $tests = array('00'); - protected $files = array('questions', 'steps', 'results'); /** @@ -58,7 +53,7 @@ class mod_quiz_attempt_walkthrough_from_csv_testcase extends advanced_testcase { */ protected $randqids; - public function create_quiz($qs) { + public function create_quiz($quizsettings, $qs) { global $SITE, $DB; $this->setAdminUser(); @@ -106,10 +101,14 @@ class mod_quiz_attempt_walkthrough_from_csv_testcase extends advanced_testcase { // Make a quiz. $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); - $this->quiz = $quizgenerator->create_instance(array('course'=>$SITE->id, - 'questionsperpage' => 0, - 'grade' => 100.0, - 'sumgrades' => $sumofgrades)); + + // Settings from param override defaults. + $aggregratedsettings = $quizsettings + array('course'=>$SITE->id, + 'questionsperpage' => 0, + 'grade' => 100.0, + 'sumgrades' => $sumofgrades); + + $this->quiz = $quizgenerator->create_instance($aggregratedsettings); $this->randqids = array(); foreach ($slots as $slotno => $slotquestion) { @@ -143,7 +142,7 @@ class mod_quiz_attempt_walkthrough_from_csv_testcase extends advanced_testcase { * @param string $test * @return \PHPUnit_Extensions_Database_DataSet_ITable */ - protected function load_csv_data_file($setname, $test) { + protected function load_csv_data_file($setname, $test='') { $files = array($setname => $this->get_full_path_of_csv_file($setname, $test)); return $this->createCsvDataSet($files)->getTable($setname); } @@ -177,17 +176,19 @@ class mod_quiz_attempt_walkthrough_from_csv_testcase extends advanced_testcase { /** * Data provider method for test_walkthrough_from_csv. Called by PHPUnit. * - * @return array One array element for each run of the test. Each element contains an array with the one param for + * @return array One array element for each run of the test. Each element contains an array with the params for * test_walkthrough_from_csv. */ public function get_data_for_walkthrough() { + $quizzes = $this->load_csv_data_file('quizzes'); $datasets = array(); - foreach ($this->tests as $test) { + for ($rowno = 0; $rowno < $quizzes->getRowCount(); $rowno++) { + $quizsettings = $quizzes->getRow($rowno); $dataset = array(); foreach ($this->files as $file) { - $dataset[$file] = $this->load_csv_data_file($file, $test); + $dataset[$file] = $this->load_csv_data_file($file, $quizsettings['testnumber']); } - $datasets[] = array($dataset); + $datasets[] = array($quizsettings, $dataset); } return $datasets; } @@ -195,11 +196,12 @@ class mod_quiz_attempt_walkthrough_from_csv_testcase extends advanced_testcase { /** * Create a quiz add questions to it, walk through quiz attempts and then check results. * - * @param PHPUnit_Extensions_Database_DataSet_ITable[] of data read from csv file "questionsXX.csv", + * @param $quizsettings array of settings read from csv file quizzes.csv + * @param $csvdata \PHPUnit_Extensions_Database_DataSet_ITable[] of data read from csv file "questionsXX.csv", * "stepsXX.csv" and "resultsXX.csv". * @dataProvider get_data_for_walkthrough */ - public function test_walkthrough_from_csv($csvdata) { + public function test_walkthrough_from_csv($quizsettings, $csvdata) { // CSV data files for these tests were generated using : // https://github.com/jamiepratt/moodle-quiz-tools/tree/master/responsegenerator @@ -207,7 +209,7 @@ class mod_quiz_attempt_walkthrough_from_csv_testcase extends advanced_testcase { $this->resetAfterTest(true); question_bank::get_qtype('random')->clear_caches_before_testing(); - $this->create_quiz($csvdata['questions']); + $this->create_quiz($quizsettings, $csvdata['questions']); $attemptids = $this->walkthrough_attempts($csvdata['steps']); @@ -231,38 +233,47 @@ class mod_quiz_attempt_walkthrough_from_csv_testcase extends advanced_testcase { if (!$user = $DB->get_record('user', $username)) { $user = $this->getDataGenerator()->create_user($username); } - // Start the attempt. - $quizobj = quiz::create($this->quiz->id, $user->id); - $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); - $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); - - $timenow = time(); - $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, false, $user->id); - // Select variant and / or random sub question. - if (!isset($step['variants'])) { - $step['variants'] = array(); - } - if (isset($step['randqs'])) { - // Replace 'names' with ids. - foreach ($step['randqs'] as $slotno => $randqname) { - $step['randqs'][$slotno] = $this->randqids[$slotno][$randqname]; + + if (!isset($attemptids[$step['quizattempt']])) { + // Start the attempt. + $quizobj = quiz::create($this->quiz->id, $user->id); + $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); + $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); + + $prevattempts = quiz_get_user_attempts($this->quiz->id, $user->id, 'all', true); + $attemptnumber = count($prevattempts) + 1; + $timenow = time(); + $attempt = quiz_create_attempt($quizobj, $attemptnumber, false, $timenow, false, $user->id); + // Select variant and / or random sub question. + if (!isset($step['variants'])) { + $step['variants'] = array(); } + if (isset($step['randqs'])) { + // Replace 'names' with ids. + foreach ($step['randqs'] as $slotno => $randqname) { + $step['randqs'][$slotno] = $this->randqids[$slotno][$randqname]; + } + } else { + $step['randqs'] = array(); + } + + quiz_start_new_attempt($quizobj, $quba, $attempt, $attemptnumber, $timenow, $step['randqs'], $step['variants']); + quiz_attempt_save_started($quizobj, $quba, $attempt); + $attemptid = $attemptids[$step['quizattempt']] = $attempt->id; } else { - $step['randqs'] = array(); + $attemptid = $attemptids[$step['quizattempt']]; } - 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 = quiz_attempt::create($attemptid); $attemptobj->process_submitted_actions($timenow, false, $step['responses']); // Finish the attempt. - $attemptobj = quiz_attempt::create($attempt->id); - $attemptobj->process_finish($timenow, false); - + if (!isset($step['finished']) || ($step['finished'] == 1)) { + $attemptobj = quiz_attempt::create($attemptid); + $attemptobj->process_finish($timenow, false); + } } return $attemptids; } @@ -289,6 +300,9 @@ class mod_quiz_attempt_walkthrough_from_csv_testcase extends advanced_testcase { */ protected function check_attempt_results($result, $attemptobj) { foreach ($result as $fieldname => $value) { + if ($value === '!NULL!') { + $value = null; + } switch ($fieldname) { case 'quizattempt' : break; @@ -311,7 +325,7 @@ class mod_quiz_attempt_walkthrough_from_csv_testcase extends advanced_testcase { } break; case 'finished' : - $this->assertEquals($value, $attemptobj->is_finished()); + $this->assertEquals((bool)$value, $attemptobj->is_finished()); break; case 'summarks' : $this->assertEquals($value, $attemptobj->get_sum_marks(), "Sum of marks of attempt {$result['quizattempt']}."); diff --git a/mod/quiz/tests/fixtures/questions01.csv b/mod/quiz/tests/fixtures/questions01.csv new file mode 100644 index 00000000000..9e19fa8dd1d --- /dev/null +++ b/mod/quiz/tests/fixtures/questions01.csv @@ -0,0 +1,2 @@ +slot,type,which,cat,mark,overrides.penalty +1,multianswer,,maincat,100,0.3333333 diff --git a/mod/quiz/tests/fixtures/quizzes.csv b/mod/quiz/tests/fixtures/quizzes.csv new file mode 100644 index 00000000000..23bc727d0c6 --- /dev/null +++ b/mod/quiz/tests/fixtures/quizzes.csv @@ -0,0 +1,3 @@ +testnumber,preferredbehaviour +00,deferredfeedback +01,interactive diff --git a/mod/quiz/tests/fixtures/results01.csv b/mod/quiz/tests/fixtures/results01.csv new file mode 100644 index 00000000000..64b893a1f55 --- /dev/null +++ b/mod/quiz/tests/fixtures/results01.csv @@ -0,0 +1,9 @@ +quizattempt,finished,slots.1.mark,summarks,attemptnumber +1,1,33.33334,33.33334,1 +2,1,50,50,1 +3,1,50,50,1 +4,0,100,!NULL!,1 +5,1,33.33334,33.33334,2 +6,1,50,50,2 +7,1,50,50,2 +8,0,100,!NULL!,2 diff --git a/mod/quiz/tests/fixtures/steps01.csv b/mod/quiz/tests/fixtures/steps01.csv new file mode 100644 index 00000000000..830b2bbb954 --- /dev/null +++ b/mod/quiz/tests/fixtures/steps01.csv @@ -0,0 +1,21 @@ +quizattempt,firstname,lastname,responses.1.1.answer,responses.1.2.answer,responses.1.-submit,responses.1.-tryagain,finished +1,Juniper,Jones,Pussy-cat,0,1,0,0 +1,Juniper,Jones,Owl,0,0,1,0 +1,Juniper,Jones,Owl,0,1,0,1 +2,Juniper,Smith,Dog,2,1,0,0 +2,Juniper,Smith,Dog,2,0,1,0 +2,Juniper,Smith,Dog,2,1,0,1 +3,Juniper,Vicars,Owl,1,1,0,0 +3,Juniper,Vicars,Owl,1,1,0,0 +3,Juniper,Vicars,Owl,1,1,0,1 +4,Juniper,Pacino,Owl,2,1,0,0 +5,Juniper,Jones,Pussy-cat,0,1,0,0 +5,Juniper,Jones,Owl,0,0,1,0 +5,Juniper,Jones,Owl,0,1,0,1 +6,Juniper,Smith,Dog,2,1,0,0 +6,Juniper,Smith,Dog,2,0,1,0 +6,Juniper,Smith,Dog,2,1,0,1 +7,Juniper,Vicars,Owl,1,1,0,0 +7,Juniper,Vicars,Owl,1,1,0,0 +7,Juniper,Vicars,Owl,1,1,0,1 +8,Juniper,Pacino,Owl,2,1,0,0 diff --git a/question/engine/questionusage.php b/question/engine/questionusage.php index 96b5355a32c..be165b488d8 100644 --- a/question/engine/questionusage.php +++ b/question/engine/questionusage.php @@ -598,9 +598,23 @@ class question_usage_by_activity { $simulatedpostdata = array(); $simulatedpostdata['slots'] = implode(',', array_keys($simulatedresponses)); foreach ($simulatedresponses as $slot => $responsedata) { - $prefix = $this->get_field_prefix($slot); - $slotresponse = $this->get_question($slot)->prepare_simulated_post_data($responsedata); + $slotresponse = array(); + + // Behaviour vars should not be processed by question type, just add prefix. + $behaviourvars = $this->get_question_attempt($slot)->get_behaviour()->get_expected_data(); + foreach ($behaviourvars as $behaviourvarname => $unused) { + $behaviourvarkey = '-'.$behaviourvarname; + if (isset($responsedata[$behaviourvarkey])) { + $slotresponse[$behaviourvarkey] = $responsedata[$behaviourvarkey]; + unset($responsedata[$behaviourvarkey]); + } + } + + $slotresponse += $this->get_question($slot)->prepare_simulated_post_data($responsedata); $slotresponse[':sequencecheck'] = $this->get_question_attempt($slot)->get_sequence_check_count(); + + // Add this slot's prefix to slot data. + $prefix = $this->get_field_prefix($slot); foreach ($slotresponse as $key => $value) { $simulatedpostdata[$prefix.$key] = $value; } -- 2.43.0