Skip to content

Commit

Permalink
MDL-40729 check marks and grades from quiz attempts
Browse files Browse the repository at this point in the history
compare to marks in csv file.
  • Loading branch information
jamiepratt authored and danpoltawski committed Jul 23, 2013
1 parent d735f3d commit e39a2fa
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 40 deletions.
127 changes: 90 additions & 37 deletions mod/quiz/tests/attempt_walkthrough_from_csv_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ public function get_data_for_walkthrough() {
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;
}
Expand Down Expand Up @@ -156,20 +157,48 @@ protected function load_csv_data_file($setname, $test) {
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));
Expand Down Expand Up @@ -203,6 +232,8 @@ public function test_walkthrough_from_csv($qs, $steps) {
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']);
Expand All @@ -211,51 +242,73 @@ public function test_walkthrough_from_csv($qs, $steps) {
$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;
}
}
11 changes: 11 additions & 0 deletions mod/quiz/tests/fixtures/results00.csv
Original file line number Diff line number Diff line change
@@ -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
14 changes: 11 additions & 3 deletions mod/quiz/tests/fixtures/steps00.csv
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit e39a2fa

Please sign in to comment.