Skip to content
Browse files

MDL-38538 question unit tests: improve things a bit.

1. Split the question_attempt tests into one class per file.
2. Imporve the API to give tests more control, and to test more of the
   important code. Some of this is not used here, but it is about to be.
  • Loading branch information...
1 parent d8201d4 commit eca230b52197bec87bee059d15651a3886dd62f8 @timhunt timhunt committed Mar 28, 2013
View
102 question/engine/tests/helpers.php
@@ -50,6 +50,40 @@ public function set_behaviour(question_behaviour $behaviour) {
/**
+ * Test subclass to allow access to some protected data so that the correct
+ * behaviour can be verified.
+ *
+ * @copyright 2012 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class testable_question_engine_unit_of_work extends question_engine_unit_of_work {
+ public function get_modified() {
+ return $this->modified;
+ }
+
+ public function get_attempts_added() {
+ return $this->attemptsadded;
+ }
+
+ public function get_attempts_modified() {
+ return $this->attemptsmodified;
+ }
+
+ public function get_steps_added() {
+ return $this->stepsadded;
+ }
+
+ public function get_steps_modified() {
+ return $this->stepsmodified;
+ }
+
+ public function get_steps_deleted() {
+ return $this->stepsdeleted;
+ }
+}
+
+
+/**
* Base class for question type test helpers.
*
* @copyright 2011 The Open University
@@ -649,14 +683,50 @@ protected function start_attempt_at_question($question, $preferredbehaviour,
$this->slot = $this->quba->add_question($question, $maxmark);
$this->quba->start_question($this->slot, $variant);
}
+
protected function process_submission($data) {
- $this->quba->process_action($this->slot, $data);
+ // Backwards compatibility.
+ reset($data);
+ if (count($data) == 1 && key($data) === '-finish') {
+ $this->finish();
+ }
+
+ $prefix = $this->quba->get_field_prefix($this->slot);
+ $fulldata = array(
+ 'slots' => $this->slot,
+ $prefix . ':sequencecheck' => $this->get_question_attempt()->get_num_steps(),
+ );
+ foreach ($data as $name => $value) {
+ $fulldata[$prefix . $name] = $value;
+ }
+ $this->quba->process_all_actions(time(), $fulldata);
+ }
+
+ protected function process_autosave($data) {
+ $this->quba->process_autosave($this->slot, $data);
+ }
+
+ protected function finish() {
+ $this->quba->finish_all_questions();
}
protected function manual_grade($comment, $mark, $commentformat = null) {
$this->quba->manual_grade($this->slot, $comment, $mark, $commentformat);
}
+ protected function save_quba(moodle_database $db = null) {
+ question_engine::save_questions_usage_by_activity($this->quba, $db);
+ }
+
+ protected function load_quba(moodle_database $db = null) {
+ $this->quba = question_engine::load_questions_usage_by_activity($this->quba->get_id(), $db);
+ }
+
+ protected function delete_quba() {
+ question_engine::delete_questions_usage_by_activity($this->quba->get_id());
+ $this->quba = null;
+ }
+
protected function check_current_state($state) {
$this->assertEquals($state, $this->quba->get_question_state($this->slot),
'Questions is in the wrong state.');
@@ -684,6 +754,36 @@ protected function render() {
$this->currentoutput = $this->quba->render_question($this->slot, $this->displayoptions);
}
+ protected function check_output_contains_text_input($name, $value = null, $enabled = true) {
+ $attributes = array(
+ 'type' => 'text',
+ 'name' => $this->quba->get_field_prefix($this->slot) . $name,
+ );
+ if (!is_null($value)) {
+ $attributes['value'] = $value;
+ }
+ if (!$enabled) {
+ $attributes['readonly'] = 'readonly';
+ }
+ $matcher = $this->get_tag_matcher('input', $attributes);
+ $this->assertTag($matcher, $this->currentoutput,
+ 'Looking for an input with attributes ' . html_writer::attributes($attributes) . ' in ' . $this->currentoutput);
+
+ if ($enabled) {
+ $matcher['attributes']['readonly'] = 'readonly';
+ $this->assertNotTag($matcher, $this->currentoutput,
+ 'input with attributes ' . html_writer::attributes($attributes) .
+ ' should not be read-only in ' . $this->currentoutput);
+ }
+ }
+
+ protected function get_tag_matcher($tag, $attributes) {
+ return array(
+ 'tag' => $tag,
+ 'attributes' => $attributes,
+ );
+ }
+
/**
* @param $condition one or more Expectations. (users varargs).
*/
View
143 question/engine/tests/questionattempt_db_test.php
@@ -0,0 +1,143 @@
+<?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/>.
+
+/**
+ * This file contains tests for the question_attempt class.
+ *
+ * Action methods like start, process_action and finish are assumed to be
+ * tested by walkthrough tests in the various behaviours.
+ *
+ * @package moodlecore
+ * @subpackage questionengine
+ * @copyright 2009 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once(dirname(__FILE__) . '/../lib.php');
+require_once(dirname(__FILE__) . '/helpers.php');
+
+
+/**
+ * Unit tests for loading data into the {@link question_attempt} class.
+ *
+ * @copyright 2009 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class question_attempt_db_test extends data_loading_method_test_base {
+ public function test_load() {
+ $records = new question_test_recordset(array(
+ array('questionattemptid', 'contextid', 'questionusageid', 'slot',
+ 'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'flagged',
+ 'questionsummary', 'rightanswer', 'responsesummary', 'timemodified',
+ 'attemptstepid', 'sequencenumber', 'state', 'fraction',
+ 'timecreated', 'userid', 'name', 'value'),
+ array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 1, 0, 'todo', null, 1256233700, 1, null, null),
+ array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 2, 1, 'complete', null, 1256233705, 1, 'answer', '1'),
+ array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1, '', '', '', 1256233790, 3, 2, 'complete', null, 1256233710, 1, 'answer', '0'),
+ array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 4, 3, 'complete', null, 1256233715, 1, 'answer', '1'),
+ array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 5, 4, 'gradedright', 1.0000000, 1256233720, 1, '-finish', '1'),
+ array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 6, 5, 'mangrpartial', 0.5000000, 1256233790, 1, '-comment', 'Not good enough!'),
+ array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 6, 5, 'mangrpartial', 0.5000000, 1256233790, 1, '-mark', '1'),
+ array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 6, 5, 'mangrpartial', 0.5000000, 1256233790, 1, '-maxmark', '2'),
+ ));
+
+ $question = test_question_maker::make_question('truefalse', 'true');
+ $question->id = -1;
+
+ question_bank::start_unit_test();
+ question_bank::load_test_question_data($question);
+ $qa = question_attempt::load_from_records($records, 1, new question_usage_null_observer(), 'deferredfeedback');
+ question_bank::end_unit_test();
+
+ $this->assertEquals($question->questiontext, $qa->get_question()->questiontext);
+
+ $this->assertEquals(6, $qa->get_num_steps());
+
+ $step = $qa->get_step(0);
+ $this->assertEquals(question_state::$todo, $step->get_state());
+ $this->assertNull($step->get_fraction());
+ $this->assertEquals(1256233700, $step->get_timecreated());
+ $this->assertEquals(1, $step->get_user_id());
+ $this->assertEquals(array(), $step->get_all_data());
+
+ $step = $qa->get_step(1);
+ $this->assertEquals(question_state::$complete, $step->get_state());
+ $this->assertNull($step->get_fraction());
+ $this->assertEquals(1256233705, $step->get_timecreated());
+ $this->assertEquals(1, $step->get_user_id());
+ $this->assertEquals(array('answer' => '1'), $step->get_all_data());
+
+ $step = $qa->get_step(2);
+ $this->assertEquals(question_state::$complete, $step->get_state());
+ $this->assertNull($step->get_fraction());
+ $this->assertEquals(1256233710, $step->get_timecreated());
+ $this->assertEquals(1, $step->get_user_id());
+ $this->assertEquals(array('answer' => '0'), $step->get_all_data());
+
+ $step = $qa->get_step(3);
+ $this->assertEquals(question_state::$complete, $step->get_state());
+ $this->assertNull($step->get_fraction());
+ $this->assertEquals(1256233715, $step->get_timecreated());
+ $this->assertEquals(1, $step->get_user_id());
+ $this->assertEquals(array('answer' => '1'), $step->get_all_data());
+
+ $step = $qa->get_step(4);
+ $this->assertEquals(question_state::$gradedright, $step->get_state());
+ $this->assertEquals(1, $step->get_fraction());
+ $this->assertEquals(1256233720, $step->get_timecreated());
+ $this->assertEquals(1, $step->get_user_id());
+ $this->assertEquals(array('-finish' => '1'), $step->get_all_data());
+
+ $step = $qa->get_step(5);
+ $this->assertEquals(question_state::$mangrpartial, $step->get_state());
+ $this->assertEquals(0.5, $step->get_fraction());
+ $this->assertEquals(1256233790, $step->get_timecreated());
+ $this->assertEquals(1, $step->get_user_id());
+ $this->assertEquals(array('-comment' => 'Not good enough!', '-mark' => '1', '-maxmark' => '2'),
+ $step->get_all_data());
+ }
+
+ public function test_load_missing_question() {
+ $records = new question_test_recordset(array(
+ array('questionattemptid', 'contextid', 'questionusageid', 'slot',
+ 'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'flagged',
+ 'questionsummary', 'rightanswer', 'responsesummary', 'timemodified',
+ 'attemptstepid', 'sequencenumber', 'state', 'fraction',
+ 'timecreated', 'userid', 'name', 'value'),
+ array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 1, 0, 'todo', null, 1256233700, 1, null, null),
+ ));
+
+ question_bank::start_unit_test();
+ $qa = question_attempt::load_from_records($records, 1, new question_usage_null_observer(), 'deferredfeedback');
+ question_bank::end_unit_test();
+
+ $missingq = question_bank::get_qtype('missingtype')->make_deleted_instance(-1, 2);
+ $this->assertEquals($missingq, $qa->get_question());
+
+ $this->assertEquals(1, $qa->get_num_steps());
+
+ $step = $qa->get_step(0);
+ $this->assertEquals(question_state::$todo, $step->get_state());
+ $this->assertNull($step->get_fraction());
+ $this->assertEquals(1256233700, $step->get_timecreated());
+ $this->assertEquals(1, $step->get_user_id());
+ $this->assertEquals(array(), $step->get_all_data());
+ }
+}
View
232 question/engine/tests/questionattempt_test.php
@@ -139,235 +139,3 @@ public function test_get_submitted_var_param_mark_invalid() {
'name', question_attempt::PARAM_MARK, array('name' => 'frog')));
}
}
-
-
-/**
- * These tests use a standard fixture of a {@link question_attempt} with three steps.
- *
- * @copyright 2009 The Open University
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class question_attempt_with_steps_test extends advanced_testcase {
- private $question;
- private $qa;
-
- protected function setUp() {
- $this->question = test_question_maker::make_question('description');
- $this->qa = new testable_question_attempt($this->question, 0, null, 2);
- for ($i = 0; $i < 3; $i++) {
- $step = new question_attempt_step(array('i' => $i));
- $this->qa->add_step($step);
- }
- }
-
- protected function tearDown() {
- $this->qa = null;
- }
-
- public function test_get_step_before_start() {
- $this->setExpectedException('moodle_exception');
- $step = $this->qa->get_step(-1);
- }
-
- public function test_get_step_at_start() {
- $step = $this->qa->get_step(0);
- $this->assertEquals(0, $step->get_qt_var('i'));
- }
-
- public function test_get_step_at_end() {
- $step = $this->qa->get_step(2);
- $this->assertEquals(2, $step->get_qt_var('i'));
- }
-
- public function test_get_step_past_end() {
- $this->setExpectedException('moodle_exception');
- $step = $this->qa->get_step(3);
- }
-
- public function test_get_num_steps() {
- $this->assertEquals(3, $this->qa->get_num_steps());
- }
-
- public function test_get_last_step() {
- $step = $this->qa->get_last_step();
- $this->assertEquals(2, $step->get_qt_var('i'));
- }
-
- public function test_get_last_qt_var_there1() {
- $this->assertEquals(2, $this->qa->get_last_qt_var('i'));
- }
-
- public function test_get_last_qt_var_there2() {
- $this->qa->get_step(0)->set_qt_var('_x', 'a value');
- $this->assertEquals('a value', $this->qa->get_last_qt_var('_x'));
- }
-
- public function test_get_last_qt_var_missing() {
- $this->assertNull($this->qa->get_last_qt_var('notthere'));
- }
-
- public function test_get_last_qt_var_missing_default() {
- $this->assertEquals('default', $this->qa->get_last_qt_var('notthere', 'default'));
- }
-
- public function test_get_last_behaviour_var_missing() {
- $this->assertNull($this->qa->get_last_qt_var('notthere'));
- }
-
- public function test_get_last_behaviour_var_there() {
- $this->qa->get_step(1)->set_behaviour_var('_x', 'a value');
- $this->assertEquals('a value', '' . $this->qa->get_last_behaviour_var('_x'));
- }
-
- public function test_get_state_gets_state_of_last() {
- $this->qa->get_step(2)->set_state(question_state::$gradedright);
- $this->qa->get_step(1)->set_state(question_state::$gradedwrong);
- $this->assertEquals(question_state::$gradedright, $this->qa->get_state());
- }
-
- public function test_get_mark_gets_mark_of_last() {
- $this->assertEquals(2, $this->qa->get_max_mark());
- $this->qa->get_step(2)->set_fraction(0.5);
- $this->qa->get_step(1)->set_fraction(0.1);
- $this->assertEquals(1, $this->qa->get_mark());
- }
-
- public function test_get_fraction_gets_fraction_of_last() {
- $this->qa->get_step(2)->set_fraction(0.5);
- $this->qa->get_step(1)->set_fraction(0.1);
- $this->assertEquals(0.5, $this->qa->get_fraction());
- }
-
- public function test_get_fraction_returns_null_if_none() {
- $this->assertNull($this->qa->get_fraction());
- }
-
- public function test_format_mark() {
- $this->qa->get_step(2)->set_fraction(0.5);
- $this->assertEquals('1.00', $this->qa->format_mark(2));
- }
-
- public function test_format_max_mark() {
- $this->assertEquals('2.0000000', $this->qa->format_max_mark(7));
- }
-
- public function test_get_min_fraction() {
- $this->qa->set_min_fraction(-1);
- $this->assertEquals(-1, $this->qa->get_min_fraction(0));
- }
-
- public function test_cannot_get_min_fraction_before_start() {
- $qa = new question_attempt($this->question, 0);
- $this->setExpectedException('moodle_exception');
- $qa->get_min_fraction();
- }
-}
-
-
-/**
- * Unit tests for loading data into the {@link question_attempt} class.
- *
- * @copyright 2009 The Open University
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class question_attempt_db_test extends data_loading_method_test_base {
- public function test_load() {
- $records = new question_test_recordset(array(
- array('questionattemptid', 'contextid', 'questionusageid', 'slot',
- 'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'flagged',
- 'questionsummary', 'rightanswer', 'responsesummary', 'timemodified',
- 'attemptstepid', 'sequencenumber', 'state', 'fraction',
- 'timecreated', 'userid', 'name', 'value'),
- array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 1, 0, 'todo', null, 1256233700, 1, null, null),
- array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 2, 1, 'complete', null, 1256233705, 1, 'answer', '1'),
- array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1, '', '', '', 1256233790, 3, 2, 'complete', null, 1256233710, 1, 'answer', '0'),
- array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 4, 3, 'complete', null, 1256233715, 1, 'answer', '1'),
- array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 5, 4, 'gradedright', 1.0000000, 1256233720, 1, '-finish', '1'),
- array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 6, 5, 'mangrpartial', 0.5000000, 1256233790, 1, '-comment', 'Not good enough!'),
- array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 6, 5, 'mangrpartial', 0.5000000, 1256233790, 1, '-mark', '1'),
- array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 6, 5, 'mangrpartial', 0.5000000, 1256233790, 1, '-maxmark', '2'),
- ));
-
- $question = test_question_maker::make_question('truefalse', 'true');
- $question->id = -1;
-
- question_bank::start_unit_test();
- question_bank::load_test_question_data($question);
- $qa = question_attempt::load_from_records($records, 1, new question_usage_null_observer(), 'deferredfeedback');
- question_bank::end_unit_test();
-
- $this->assertEquals($question->questiontext, $qa->get_question()->questiontext);
-
- $this->assertEquals(6, $qa->get_num_steps());
-
- $step = $qa->get_step(0);
- $this->assertEquals(question_state::$todo, $step->get_state());
- $this->assertNull($step->get_fraction());
- $this->assertEquals(1256233700, $step->get_timecreated());
- $this->assertEquals(1, $step->get_user_id());
- $this->assertEquals(array(), $step->get_all_data());
-
- $step = $qa->get_step(1);
- $this->assertEquals(question_state::$complete, $step->get_state());
- $this->assertNull($step->get_fraction());
- $this->assertEquals(1256233705, $step->get_timecreated());
- $this->assertEquals(1, $step->get_user_id());
- $this->assertEquals(array('answer' => '1'), $step->get_all_data());
-
- $step = $qa->get_step(2);
- $this->assertEquals(question_state::$complete, $step->get_state());
- $this->assertNull($step->get_fraction());
- $this->assertEquals(1256233710, $step->get_timecreated());
- $this->assertEquals(1, $step->get_user_id());
- $this->assertEquals(array('answer' => '0'), $step->get_all_data());
-
- $step = $qa->get_step(3);
- $this->assertEquals(question_state::$complete, $step->get_state());
- $this->assertNull($step->get_fraction());
- $this->assertEquals(1256233715, $step->get_timecreated());
- $this->assertEquals(1, $step->get_user_id());
- $this->assertEquals(array('answer' => '1'), $step->get_all_data());
-
- $step = $qa->get_step(4);
- $this->assertEquals(question_state::$gradedright, $step->get_state());
- $this->assertEquals(1, $step->get_fraction());
- $this->assertEquals(1256233720, $step->get_timecreated());
- $this->assertEquals(1, $step->get_user_id());
- $this->assertEquals(array('-finish' => '1'), $step->get_all_data());
-
- $step = $qa->get_step(5);
- $this->assertEquals(question_state::$mangrpartial, $step->get_state());
- $this->assertEquals(0.5, $step->get_fraction());
- $this->assertEquals(1256233790, $step->get_timecreated());
- $this->assertEquals(1, $step->get_user_id());
- $this->assertEquals(array('-comment' => 'Not good enough!', '-mark' => '1', '-maxmark' => '2'),
- $step->get_all_data());
- }
-
- public function test_load_missing_question() {
- $records = new question_test_recordset(array(
- array('questionattemptid', 'contextid', 'questionusageid', 'slot',
- 'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'flagged',
- 'questionsummary', 'rightanswer', 'responsesummary', 'timemodified',
- 'attemptstepid', 'sequencenumber', 'state', 'fraction',
- 'timecreated', 'userid', 'name', 'value'),
- array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 1, 0, 'todo', null, 1256233700, 1, null, null),
- ));
-
- question_bank::start_unit_test();
- $qa = question_attempt::load_from_records($records, 1, new question_usage_null_observer(), 'deferredfeedback');
- question_bank::end_unit_test();
-
- $missingq = question_bank::get_qtype('missingtype')->make_deleted_instance(-1, 2);
- $this->assertEquals($missingq, $qa->get_question());
-
- $this->assertEquals(1, $qa->get_num_steps());
-
- $step = $qa->get_step(0);
- $this->assertEquals(question_state::$todo, $step->get_state());
- $this->assertNull($step->get_fraction());
- $this->assertEquals(1256233700, $step->get_timecreated());
- $this->assertEquals(1, $step->get_user_id());
- $this->assertEquals(array(), $step->get_all_data());
- }
-}
View
157 question/engine/tests/questionattempt_with_steps_test.php
@@ -0,0 +1,157 @@
+<?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/>.
+
+/**
+ * This file contains tests for the question_attempt class.
+ *
+ * Action methods like start, process_action and finish are assumed to be
+ * tested by walkthrough tests in the various behaviours.
+ *
+ * @package moodlecore
+ * @subpackage questionengine
+ * @copyright 2009 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once(dirname(__FILE__) . '/../lib.php');
+require_once(dirname(__FILE__) . '/helpers.php');
+
+
+/**
+ * These tests use a standard fixture of a {@link question_attempt} with three steps.
+ *
+ * @copyright 2009 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class question_attempt_with_steps_test extends advanced_testcase {
+ private $question;
+ private $qa;
+
+ protected function setUp() {
+ $this->question = test_question_maker::make_question('description');
+ $this->qa = new testable_question_attempt($this->question, 0, null, 2);
+ for ($i = 0; $i < 3; $i++) {
+ $step = new question_attempt_step(array('i' => $i));
+ $this->qa->add_step($step);
+ }
+ }
+
+ protected function tearDown() {
+ $this->qa = null;
+ }
+
+ public function test_get_step_before_start() {
+ $this->setExpectedException('moodle_exception');
+ $step = $this->qa->get_step(-1);
+ }
+
+ public function test_get_step_at_start() {
+ $step = $this->qa->get_step(0);
+ $this->assertEquals(0, $step->get_qt_var('i'));
+ }
+
+ public function test_get_step_at_end() {
+ $step = $this->qa->get_step(2);
+ $this->assertEquals(2, $step->get_qt_var('i'));
+ }
+
+ public function test_get_step_past_end() {
+ $this->setExpectedException('moodle_exception');
+ $step = $this->qa->get_step(3);
+ }
+
+ public function test_get_num_steps() {
+ $this->assertEquals(3, $this->qa->get_num_steps());
+ }
+
+ public function test_get_last_step() {
+ $step = $this->qa->get_last_step();
+ $this->assertEquals(2, $step->get_qt_var('i'));
+ }
+
+ public function test_get_last_qt_var_there1() {
+ $this->assertEquals(2, $this->qa->get_last_qt_var('i'));
+ }
+
+ public function test_get_last_qt_var_there2() {
+ $this->qa->get_step(0)->set_qt_var('_x', 'a value');
+ $this->assertEquals('a value', $this->qa->get_last_qt_var('_x'));
+ }
+
+ public function test_get_last_qt_var_missing() {
+ $this->assertNull($this->qa->get_last_qt_var('notthere'));
+ }
+
+ public function test_get_last_qt_var_missing_default() {
+ $this->assertEquals('default', $this->qa->get_last_qt_var('notthere', 'default'));
+ }
+
+ public function test_get_last_behaviour_var_missing() {
+ $this->assertNull($this->qa->get_last_qt_var('notthere'));
+ }
+
+ public function test_get_last_behaviour_var_there() {
+ $this->qa->get_step(1)->set_behaviour_var('_x', 'a value');
+ $this->assertEquals('a value', '' . $this->qa->get_last_behaviour_var('_x'));
+ }
+
+ public function test_get_state_gets_state_of_last() {
+ $this->qa->get_step(2)->set_state(question_state::$gradedright);
+ $this->qa->get_step(1)->set_state(question_state::$gradedwrong);
+ $this->assertEquals(question_state::$gradedright, $this->qa->get_state());
+ }
+
+ public function test_get_mark_gets_mark_of_last() {
+ $this->assertEquals(2, $this->qa->get_max_mark());
+ $this->qa->get_step(2)->set_fraction(0.5);
+ $this->qa->get_step(1)->set_fraction(0.1);
+ $this->assertEquals(1, $this->qa->get_mark());
+ }
+
+ public function test_get_fraction_gets_fraction_of_last() {
+ $this->qa->get_step(2)->set_fraction(0.5);
+ $this->qa->get_step(1)->set_fraction(0.1);
+ $this->assertEquals(0.5, $this->qa->get_fraction());
+ }
+
+ public function test_get_fraction_returns_null_if_none() {
+ $this->assertNull($this->qa->get_fraction());
+ }
+
+ public function test_format_mark() {
+ $this->qa->get_step(2)->set_fraction(0.5);
+ $this->assertEquals('1.00', $this->qa->format_mark(2));
+ }
+
+ public function test_format_max_mark() {
+ $this->assertEquals('2.0000000', $this->qa->format_max_mark(7));
+ }
+
+ public function test_get_min_fraction() {
+ $this->qa->set_min_fraction(-1);
+ $this->assertEquals(-1, $this->qa->get_min_fraction(0));
+ }
+
+ public function test_cannot_get_min_fraction_before_start() {
+ $qa = new question_attempt($this->question, 0);
+ $this->setExpectedException('moodle_exception');
+ $qa->get_min_fraction();
+ }
+}
View
36 question/engine/tests/unitofwork_test.php
@@ -32,40 +32,6 @@
/**
- * Test subclass to allow access to some protected data so that the correct
- * behaviour can be verified.
- *
- * @copyright 2012 The Open University
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class testable_question_engine_unit_of_work extends question_engine_unit_of_work {
- public function get_modified() {
- return $this->modified;
- }
-
- public function get_attempts_added() {
- return $this->attemptsadded;
- }
-
- public function get_attempts_modified() {
- return $this->attemptsmodified;
- }
-
- public function get_steps_added() {
- return $this->stepsadded;
- }
-
- public function get_steps_modified() {
- return $this->stepsmodified;
- }
-
- public function get_steps_deleted() {
- return $this->stepsdeleted;
- }
-}
-
-
-/**
* Unit tests for the {@link question_engine_unit_of_work} class.
*
* @copyright 2012 The Open University
@@ -98,7 +64,7 @@ protected function setUp() {
$this->setup_initial_test_state($this->get_test_data());
}
- public function testDown() {
+ public function tearDown() {
question_bank::end_unit_test();
}
View
2 question/type/match/tests/walkthrough_test.php
@@ -360,7 +360,7 @@ public function test_match_with_tricky_html_choices() {
'(1, 2] -> 1 < x ≤ 2; [1, 2] -> 1 ≤ x ≤ 2; [1, 2) -> 1 ≤ x < 2';
$this->process_submission($rightresponse);
- $this->process_submission(array('-finish' => 1));
+ $this->finish();
$this->assertEquals($rightresponsesummary, $m->summarise_response($rightresponse));
View
8 question/type/multianswer/tests/walkthrough_test.php
@@ -82,7 +82,7 @@ public function test_deferred_feedback() {
$this->get_does_not_contain_validation_error_expectation());
// Now submit all and finish.
- $this->process_submission(array('-finish' => 1));
+ $this->finish();
// Verify.
$this->check_current_state(question_state::$gradedpartial);
@@ -109,7 +109,7 @@ public function test_deferred_feedback_numericalzero_not_answered() {
$this->get_does_not_contain_validation_error_expectation());
// Now submit all and finish.
- $this->process_submission(array('-finish' => 1));
+ $this->finish();
// Verify.
$this->check_current_state(question_state::$gaveup);
@@ -148,7 +148,7 @@ public function test_deferred_feedback_numericalzero_0_answer() {
$this->get_does_not_contain_validation_error_expectation());
// Now submit all and finish.
- $this->process_submission(array('-finish' => 1));
+ $this->finish();
// Verify.
$this->check_current_state(question_state::$gradedright);
@@ -187,7 +187,7 @@ public function test_deferred_feedback_numericalzero_0_wrong() {
$this->get_does_not_contain_validation_error_expectation());
// Now submit all and finish.
- $this->process_submission(array('-finish' => 1));
+ $this->finish();
// Verify.
$this->check_current_state(question_state::$gradedwrong);
View
4 question/type/numerical/tests/walkthrough_test.php
@@ -162,7 +162,7 @@ public function test_deferredfeedback_currency() {
$this->get_no_hint_visible_expectation());
// Submit all and finish.
- $this->process_submission(array('-finish' => '1'));
+ $this->finish();
// Verify.
$this->check_current_state(question_state::$gradedpartial);
@@ -261,7 +261,7 @@ public function test_deferredfeedback_unit() {
$this->get_no_hint_visible_expectation());
// Submit all and finish.
- $this->process_submission(array('-finish' => '1'));
+ $this->finish();
// Verify.
$this->check_current_state(question_state::$gradedright);
View
26 question/type/shortanswer/tests/helper.php
@@ -88,6 +88,32 @@ public function get_shortanswer_question_data_frogtoad() {
}
/**
+ * Gets the question data for a shortanswer question with with correct
+ * ansewer 'frog', partially correct answer 'toad' and defaultmark 1.
+ * This question also has a '*' match anything answer.
+ * @return stdClass
+ */
+ public function get_shortanswer_question_form_data_frogtoad() {
+ $fromform = new stdClass();
+ test_question_maker::initialise_question_form_data($fromform);
+
+ $fromform->qtype = 'shortanswer';
+ $fromform->name = 'Short answer question';
+ $fromform->questiontext = array('text' => 'Name an amphibian: __________', 'format' => FORMAT_HTML);
+ $fromform->generalfeedback = array('text' => 'Generalfeedback: frog or toad would have been OK.', 'format' => FORMAT_HTML);
+ $fromform->usecase = false;
+ $fromform->answer = array('frog', 'toad', '*');
+ $fromform->fraction = array(1.0, 0.8, 0.0);
+ $fromform->feedback = array(
+ array('text' => 'Frog is a very good answer.', 'format' => FORMAT_HTML),
+ array('text' => 'Toad is an OK good answer.', 'format' => FORMAT_HTML),
+ array('text' => 'That is a bad answer.', 'format' => FORMAT_HTML),
+ );
+
+ return $fromform;
+ }
+
+ /**
* Makes a shortanswer question with just the correct ansewer 'frog', and
* no other answer matching.
* @return qtype_shortanswer_question
View
11 question/type/upgrade.txt
@@ -1,5 +1,16 @@
This files describes API changes for question type plugins.
+=== 2.5 ===
+
+* There have been some tweaks to the helper class that is used to right
+ walkthrough tests. You should not have to change your code, but you might
+ like to take a look at some of the new helper methods available. In particular,
+ if you had any code that did
+ $this->process_submission(array('-finish' => 1));
+ you should change that to
+ $this->finish();
+
+
=== 2.3.5 / 2.4.2 / 2.5 ===
* The special value question_attempt::PARAM_CLEANHTML_FILES that could be used

0 comments on commit eca230b

Please sign in to comment.
Something went wrong with that request. Please try again.