diff --git a/question.php b/question.php index 9a5f6112..bc16818e 100644 --- a/question.php +++ b/question.php @@ -104,9 +104,9 @@ class qtype_formulas_question extends question_graded_automatically_with_countba * @return question_behaviour */ public function make_behaviour(question_attempt $qa, $preferredbehaviour) { - // If the requested behaviour is 'adaptive' or 'adaptiveopenpenalty', we have to change it + // If the requested behaviour is 'adaptive' or 'adaptivenopenalty', we have to change it // to 'adaptivemultipart'. - if (in_array($preferredbehaviour, ['adaptive', 'adaptiveopenpenalty'])) { + if (in_array($preferredbehaviour, ['adaptive', 'adaptivenopenalty'])) { return question_engine::make_behaviour('adaptivemultipart', $qa, $preferredbehaviour); } diff --git a/tests/walkthrough_adaptive_test.php b/tests/walkthrough_adaptive_test.php index e2d3fc5c..c166c40c 100644 --- a/tests/walkthrough_adaptive_test.php +++ b/tests/walkthrough_adaptive_test.php @@ -475,6 +475,95 @@ public function test_adaptive_partially_answered(): void { $this->check_output_contains('Well done!'); } + public function test_adaptive_nopenalty_partially_answered(): void { + // Create a multipart Formulas question. + $q = $this->get_test_formulas_question('testthreeparts'); + $this->start_attempt_at_question($q, 'adaptivenopenalty', 3); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->render(); + $this->check_output_contains_text_input('0_0'); + $this->check_output_contains_text_input('1_0'); + $this->check_output_contains_text_input('2_0'); + $this->check_current_output( + $this->get_contains_marked_out_of_summary(), + $this->get_contains_submit_button_expectation(), + $this->get_does_not_contain_feedback_expectation(), + ); + + // Submit the empty form. The question should be counted as "invalid" with no grade. + // An error message should be visible. + $this->process_submission(['-submit' => '1']); + $this->check_current_state(question_state::$invalid); + $this->check_current_mark(null); + $this->render(); + $this->check_output_contains('All input fields are empty.'); + $this->check_output_contains_text_input('0_0', ''); + $this->check_output_contains_text_input('1_0', ''); + $this->check_output_contains_text_input('2_0', ''); + + // Submit a partial answer, answering only the first part. The question should remain + // in "todo" state, but the student should have 1 point. The student's response should + // be shown in the text field. All text fields should be enabled. + $this->start_attempt_at_question($q, 'adaptivenopenalty', 3); + $this->check_current_state(question_state::$todo); + $this->process_submission(['0_0' => '5', '-submit' => '1']); + $this->check_current_state(question_state::$todo); + $this->check_current_mark(1); + $this->render(); + $this->check_output_contains_text_input('0_0', '5'); + $this->check_output_contains_text_input('1_0', ''); + $this->check_output_contains_text_input('2_0', ''); + $this->check_output_contains('Parts, but only parts, of your response are correct.'); + + // Submit a partial answer, not answering the first part. The question should remain + // in "todo" state, but the student should have 2 points. The student's response should + // be shown in the text fields. All text fields should be enabled. + $this->start_attempt_at_question($q, 'adaptivenopenalty', 3); + $this->check_current_state(question_state::$todo); + $this->process_submission(['1_0' => '6', '2_0' => '7', '-submit' => 1]); + $this->check_current_state(question_state::$todo); + $this->check_current_mark(2); + $this->render(); + $this->check_output_contains_text_input('0_0', ''); + $this->check_output_contains_text_input('1_0', '6'); + $this->check_output_contains_text_input('2_0', '7'); + $this->check_output_contains('Parts, but only parts, of your response are correct.'); + + // Submit a partial answer, answering only the second part, but wrong. The question + // should remain in "todo" state, but the student should have 0 points. The student's + // response should be shown in the text field. All text fields should be enabled. + $this->start_attempt_at_question($q, 'adaptivenopenalty', 3); + $this->check_current_state(question_state::$todo); + $this->process_submission(['1_0' => '5', '-submit' => '1']); + $this->check_current_state(question_state::$todo); + $this->check_current_mark(0); + $this->render(); + $this->check_output_contains_text_input('0_0', ''); + $this->check_output_contains_text_input('1_0', '5'); + $this->check_output_contains_text_input('2_0', ''); + $this->check_current_output( + $this->get_contains_mark_summary(0), + $this->get_contains_incorrect_expectation(), + ); + + // Finally, submit a full and correct answer. The question should be marked "complete". + // The student's response should be shown in the text fields. All text fields should + // be enabled. The student should have 3 points. + $this->start_attempt_at_question($q, 'adaptivenopenalty', 3); + $this->check_current_state(question_state::$todo); + $this->process_submission(['0_0' => '5', '1_0' => '6', '2_0' => '7', '-submit' => 1]); + $this->check_current_state(question_state::$complete); + $this->check_current_mark(3); + $this->render(); + $this->check_output_contains_text_input('0_0', '5'); + $this->check_output_contains_text_input('1_0', '6'); + $this->check_output_contains_text_input('2_0', '7'); + $this->check_output_contains('Well done!'); + } + public function test_submit_empty_then_right_with_combined_unit(): void { // Create the formulas question 'testsinglenumunit'. $q = $this->get_test_formulas_question('testsinglenumunit'); @@ -604,8 +693,8 @@ public function test_submit_empty_then_right_with_separate_unit(): void { ); } - public function test_test0_submit_right_first_time(): void { - // Create the formulas question 'test0'. + public function test_submit_right_first_time(): void { + // Create the formulas question 'testsinglenum'. $q = $this->get_test_formulas_question('testsinglenum'); $this->start_attempt_at_question($q, 'adaptive', 1); @@ -655,8 +744,50 @@ public function test_test0_submit_right_first_time(): void { ); } - public function test_test0_submit_wrong_submit_right(): void { - // Create the formulas question 'test0'. + public function test_submit_wrong_submit_right_no_penalty(): void { + // Create the formulas question 'testsinglenum'. + $q = $this->get_test_formulas_question('testsinglenum'); + $this->start_attempt_at_question($q, 'adaptivenopenalty', 1); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + self::assertEquals( + 'adaptivemultipart', + $this->quba->get_question_attempt($this->slot)->get_behaviour_name(), + ); + $this->render(); + $this->check_output_contains_text_input('0_0'); + $this->check_current_output( + $this->get_contains_marked_out_of_summary(), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_feedback_expectation() + ); + + // Submit an incorrect answer. + $this->process_submission(['0_0' => 'dont know', '-submit' => 1]); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(0); + $this->check_current_output( + $this->get_contains_mark_summary(0), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_validation_error_expectation() + ); + + // Submit a correct answer. + $this->process_submission(['0_0' => '5', '-submit' => 1]); + + // Verify. + $this->check_current_state(question_state::$complete); + $this->check_current_mark(1); + $this->render(); + $this->check_output_contains_text_input('0_0', '5', true); + $this->check_output_does_not_contain_stray_placeholders(); + } + + public function test_submit_wrong_submit_right(): void { + // Create the formulas question 'testsinglenum'. $q = $this->get_test_formulas_question('testsinglenum'); $this->start_attempt_at_question($q, 'adaptive', 1); @@ -697,7 +828,7 @@ public function test_test0_submit_wrong_submit_right(): void { $this->check_output_does_not_contain_stray_placeholders(); } - public function test_test0_submit_wrong_unit_then_right(): void { + public function test_submit_wrong_unit_then_right(): void { // Create and configure a question with an "odd" unit penalty in order to not // get the final grade right by chance. Adding two hints to allow a total of // three tries. @@ -743,8 +874,7 @@ public function test_test0_submit_wrong_unit_then_right(): void { $this->check_current_mark(1 - 2 * $q->penalty); } - public function test_test0_submit_wrong_unit_then_right_with_hints(): void { - return; + public function test_submit_wrong_unit_then_right_with_hints(): void { // Create and configure a question with an "odd" unit penalty in order to not // get the final grade right by chance. Adding two hints to allow a total of // three tries. @@ -794,9 +924,9 @@ public function test_test0_submit_wrong_unit_then_right_with_hints(): void { $this->check_current_mark(1 - 2 * 0.3); } - public function test_test0_submit_wrong_wrong_right(): void { + public function test_submit_wrong_wrong_right(): void { // Here we test that the student is not penalized twice for the same error. - // Create the formulas question 'test0'. + // Create the formulas question 'testsinglenum'. $q = $this->get_test_formulas_question('testsinglenum'); $this->start_attempt_at_question($q, 'adaptive', 1); @@ -849,9 +979,9 @@ public function test_test0_submit_wrong_wrong_right(): void { $this->check_output_does_not_contain_stray_placeholders(); } - public function test_test0_submit_wrong_same_wrong_right(): void { + public function test_submit_wrong_same_wrong_right(): void { // Here we test that the student is not penalized twice for the same error. - // Create the formulas question 'test0'. + // Create the formulas question 'testsinglenum'. $q = $this->get_test_formulas_question('testsinglenum'); $this->start_attempt_at_question($q, 'adaptive', 1);