diff --git a/tests/backup_test.php b/tests/backup_test.php new file mode 100644 index 00000000..728d6061 --- /dev/null +++ b/tests/backup_test.php @@ -0,0 +1,223 @@ +. + +namespace mod_studentquiz; + +defined('MOODLE_INTERNAL') || die(); +global $CFG; +require_once($CFG->libdir . "/phpunit/classes/restore_date_testcase.php"); + +/** + * Unit tests for backup/restore process in StudentQuiz. + * + * @package mod_studentquiz + * @copyright 2023 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class backup_test extends \restore_date_testcase { + + /** + * Load required libraries + */ + public static function setUpBeforeClass(): void { + global $CFG; + require_once("{$CFG->dirroot}/backup/util/includes/restore_includes.php"); + } + + /** + * Test backup/restore process in studentquiz. + * + * @covers \restore_studentquiz_activity_task + */ + public function test_backup_restore_course_with_sq() { + global $DB; + $this->resetAfterTest(); + $this->setAdminUser(); + + $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $course = $this->getDataGenerator()->create_course(); + + $activity = $this->getDataGenerator()->create_module('studentquiz', [ + 'course' => $course->id, + 'anonymrank' => true, + 'forcecommenting' => 1, + 'opensubmissionfrom' => 1676912400, + 'closesubmissionfrom' => 1677085200, + 'openansweringfrom' => 1677171600, + 'closeansweringfrom' => 1677344400, + 'publishnewquestion' => 1 + ]); + $context = \context_module::instance($activity->cmid); + $studentquiz = mod_studentquiz_load_studentquiz($activity->cmid, $context->id); + $questionname = 'Test question to be copied'; + $questiongenerator->create_question('essay', null, ['name' => $questionname, 'category' => $studentquiz->categoryid]); + + $newcourseid = $this->backup_and_restore($course); + $this->assertEquals(2, $DB->count_records('question', ['name' => $questionname])); + // Delete the old course. + delete_course($course, false); + + $newstudentquiz = $DB->get_record('studentquiz', ['course' => $newcourseid]); + + $this->assertEquals(1, $DB->count_records('question', ['name' => $questionname])); + $this->assertEquals(1, $newstudentquiz->anonymrank); + $this->assertEquals(1676912400, $newstudentquiz->opensubmissionfrom); + $this->assertEquals(1677085200, $newstudentquiz->closesubmissionfrom); + $this->assertEquals(1677171600, $newstudentquiz->openansweringfrom); + $this->assertEquals(1677344400, $newstudentquiz->closeansweringfrom); + $this->assertEquals(1, $newstudentquiz->publishnewquestion); + } + + /** + * Restore the studentquiz backup file in the fixture folder base on filemame. + * + * @param string $filename Backup file name. + * @param string $coursefullname course full name. + * @param string $courseshortname course short name. + * @return mixed bool|stdClass return the studentquiz object restored. + */ + protected function restore_sq_backup_file_to_course_shortname(string $filename, string $coursefullname, + string $courseshortname) { + global $DB, $USER; + $testfixture = __DIR__ . '/fixtures/' . $filename; + + // Extract our test fixture, ready to be restored. + $backuptempdir = 'studentquiz'; + $backuppath = make_backup_temp_directory($backuptempdir); + get_file_packer('application/vnd.moodle.backup')->extract_to_pathname($testfixture, $backuppath); + // Do the restore to new course with default settings. + $categoryid = $DB->get_field('course_categories', 'MIN(id)', []); + $courseid = \restore_dbops::create_new_course($coursefullname, $courseshortname, $categoryid); + + $controller = new \restore_controller($backuptempdir, $courseid, \backup::INTERACTIVE_NO, \backup::MODE_GENERAL, $USER->id, + \backup::TARGET_NEW_COURSE); + + $controller->execute_precheck(); + $controller->execute_plan(); + $controller->destroy(); + + return $DB->get_record('studentquiz', []); + } + + /** + * Data provider for test_old_sq_backup_data(). + * + * @coversNothing + * @return array + */ + public function old_sq_backup_data_provider(): array { + + return [ + 'aggregated before' => [ + 'filename' => 'backup-moodle2-aggregated-before.mbz', + 'coursefullname' => 'aggregated before', + 'courseshortname' => 'ab', + 'correct_answered_points' => [1, 2], + 'total_points' => [32, 23], + 'questionname' => 'first', + ], + 'during 0' => [ + 'filename' => 'backup-moodle2-aggregated-during-0.mbz', + 'coursefullname' => 'during 0', + 'courseshortname' => 'd0', + 'correct_answered_points' => [2, 1], + 'total_points' => [28, 20], + 'questionname' => 'q1', + ], + 'during 1' => [ + 'filename' => 'backup-moodle2-aggregated-during-1.mbz', + 'coursefullname' => 'during 1', + 'courseshortname' => 'd1', + 'correct_answered_points' => [2, 1], + 'total_points' => [28, 20], + 'questionname' => 'q2', + ], + 'Missing state' => [ + 'filename' => 'backup-moodle2-course-two-moodle_35_sq404_missingstate.mbz', + 'coursefullname' => 'Course Two', + 'courseshortname' => 'C2', + 'correct_answered_points' => [0], + 'total_points' => [10], + 'questionname' => 'False is correct', + ], + 'Correct state' => [ + 'filename' => 'backup-moodle2-course-two-moodle_35_sq404_correctstate.mbz', + 'coursefullname' => 'Course Two', + 'courseshortname' => 'C2', + 'correct_answered_points' => [0], + 'total_points' => [15], + 'questionname' => 'False is correct', + ], + 'SQ in M311' => [ + 'filename' => 'backup-moodle2-course-with-studentquiz-m311.mbz', + 'coursefullname' => 'Course Three', + 'courseshortname' => 'C3', + 'correct_answered_points' => [0, 0], + 'total_points' => [0, 0], + 'questionname' => 'Test T/F Question', + ], + 'SQ in M311 with question data' => [ + 'filename' => 'backup-moodle2-course-2-311-with-questiondata.mbz', + 'coursefullname' => 'Course Two', + 'courseshortname' => 'C2', + 'correct_answered_points' => [2, 0, 0], + 'total_points' => [31, 21, 0], + 'questionname' => 'T/F Student', + ], + 'SQ 4.0' => [ + 'filename' => 'backup-moodle2-course-with-studentquiz-m400.mbz', + 'coursefullname' => 'Course Four', + 'courseshortname' => 'C4', + 'correct_answered_points' => [0, 0], + 'total_points' => [0, 0], + 'questionname' => 'Question T/F for 4.0', + ] + ]; + } + + /** + * Test old sq backup data from earlier version. + * + * @covers \restore_studentquiz_activity_task + * @dataProvider old_sq_backup_data_provider + * @param string $filename file name of the backup file. + * @param string $coursefullname course full name. + * @param string $courseshortname course short name. + * @param array $correctanswerpoints correct answer point for each user in the ranking table. + * @param array $totalpoints total point for each users in the ranking table. + * @param string $questionname question name after we restore. + */ + public function test_old_sq_backup_data(string $filename, string $coursefullname, string $courseshortname, + array $correctanswerpoints, array $totalpoints, string $questionname): void { + global $DB; + $this->resetAfterTest(); + $this->setAdminUser(); + // Check question with question name is not exist before restore. + $this->assertFalse($DB->record_exists('question', ['name' => $questionname])); + $sq = $this->restore_sq_backup_file_to_course_shortname($filename, $coursefullname, $courseshortname); + // Check question with question name exist after restore. + $this->assertTrue($DB->record_exists('question', ['name' => $questionname])); + + $report = new \mod_studentquiz_report($sq->coursemodule); + $count = 0; + // Check ranking page. + foreach ($report->get_user_ranking_table() as $ur) { + $this->assertEquals($totalpoints[$count], $ur->points); + $this->assertEquals($correctanswerpoints[$count], $ur->last_attempt_correct); + $count++; + } + } +} diff --git a/tests/behat/aggregated_changes_import.feature b/tests/behat/aggregated_changes_import.feature deleted file mode 100644 index c800cdb0..00000000 --- a/tests/behat/aggregated_changes_import.feature +++ /dev/null @@ -1,38 +0,0 @@ -@mod @mod_studentquiz -Feature: Restore of studentquizzes in moodle exports contain question answers - In order to reuse my studentquizzes - As a admin - I need to be able to restore the moodles backups from studentquizzes before, during and after aggregated codebase - - Legend: - - before: The StudentQuiz codebase before aggregated was introduced (<= v3.2.0, >= v3.1.0) - - during: The StudentQuiz codebase during aggregated was active (>= v3.2.1, <= v3.3.0), which had a setting aggregated: - - 0: which was the old calculation using the question engine (equals before) - - 1: which is the new calculation using studentquiz_progress table (equals after) - - after: The StudentQuiz codebase where all activities are migrated to the new calculation and the codebase has no code from before except for the restore (>= 3.4.0) - - Background: - Given the following "courses" exist: - | fullname | shortname | category | - | Course 1 | C1 | 0 | - - @javascript @_file_upload - Scenario Outline: Restore moodle backups containing old StudentQuiz activity - When I am on the "Course 1" "restore" page logged in as "admin" - And I press "Manage backup files" - And I upload "mod/studentquiz/tests/fixtures/" file to "Files" filemanager - And I press "Save changes" - And I restore "" backup into a new course using this options: - And I am on the "" "mod_studentquiz > Ranking" page - Then "1" row "Points for latest correct attemps" column of "rankingtable" table should contain "" - And "1" row "Total Points" column of "rankingtable" table should contain "" - And "2" row "Points for latest correct attemps" column of "rankingtable" table should contain "" - And "2" row "Total Points" column of "rankingtable" table should contain "" - - Examples: - | file | course | studentquiz | pos_1_correct_answered_points | pos_1_total_points | pos_2_correct_answered_points | pos_2_total_points | - | backup-moodle2-aggregated-before.mbz | aggregated before | SQbefore | 2 | 32 | 4 | 23 | - | backup-moodle2-aggregated-during-0.mbz | aggregated during 0 | SQduring0 | 4 | 28 | 2 | 20 | - | backup-moodle2-aggregated-during-1.mbz | aggregated during 1 | SQduring1 | 4 | 28 | 2 | 20 | -# after does not yet exist, must be added once aggregated field is removed from tbl_studentquiz - if that ever will happen -# | backup-moodle2-aggregated-after.mbz | Course One | StudentQuiz 1 | 0 | 0 | 0 | 0 | diff --git a/tests/behat/comment_history_backup_restore.feature b/tests/behat/backup.feature similarity index 65% rename from tests/behat/comment_history_backup_restore.feature rename to tests/behat/backup.feature index d28f1ff2..d906e4b1 100644 --- a/tests/behat/comment_history_backup_restore.feature +++ b/tests/behat/backup.feature @@ -1,15 +1,13 @@ @mod @mod_studentquiz -Feature: Restore of studentquizzes in moodle exports with comment histories - In order to reuse my studentquizzes - As a admin - I need to be able to restore the moodles backups from old studentquizzes, and the comment history feature work normally + +Feature: Restore specific studentquiz old backup to test UI feature Background: Given the following "courses" exist: | fullname | shortname | category | | Course 1 | C1 | 0 | - @javascript @_file_upload @_switch_window + @javascript @_file_upload Scenario: Restore moodle backups containing history comments. Given I am on the "Course 1" "restore" page logged in as "admin" And I press "Manage backup files" @@ -29,3 +27,18 @@ Feature: Restore of studentquizzes in moodle exports with comment histories And I press "Expand all comments" And I should see "Reply comment 1" in the ".studentquiz-comment-item:nth-child(1) .studentquiz-comment-replies .studentquiz-comment-item:nth-child(1) .studentquiz-comment-text" "css_element" And I should see "Teacher reply comment 1" in the ".studentquiz-comment-item:nth-child(1) .studentquiz-comment-replies .studentquiz-comment-item:nth-child(2) .studentquiz-comment-text" "css_element" + + @javascript @_file_upload @_switch_window + Scenario: Restore moodle backups containing old StudentQuiz activity without state history table. + Given I am on the "Course 1" "restore" page logged in as "admin" + And I press "Manage backup files" + And I upload "mod/studentquiz/tests/fixtures/backup-moodle2-course-3-sqo-20211011-missing_state_history.mbz" file to "Files" filemanager + And I press "Save changes" + And I restore "backup-moodle2-course-3-sqo-20211011-missing_state_history.mbz" backup into a new course using this options: + And I am on the "StudentQuiz One" "mod_studentquiz > View" page + And I should see "Question Test 1" + And I choose "Preview" action for "Question Test 1" in the question bank + And I switch to "questionpreview" window + When I click on "History" "link" + Then I should see "James Potter" in the "Question saved ('Draft')" "table_row" + And I should see "-" in the "Question set to 'Approved'" "table_row" diff --git a/tests/behat/changes_restorable.feature b/tests/behat/changes_restorable.feature deleted file mode 100644 index 64f02d72..00000000 --- a/tests/behat/changes_restorable.feature +++ /dev/null @@ -1,37 +0,0 @@ -@mod @mod_studentquiz -Feature: Stable restore of moodle course backups - In order to keep the studentquiz repository healthy - As a code contributor - I need to be able to verify my changes are still restorable - - Background: - Given the following "courses" exist: - | fullname | shortname | category | - | Course 1 | C1 | 0 | - And the following "activities" exist: - | activity | name | intro | course | idnumber | publishnewquestion | - | studentquiz | StudentQuiz 1 | Quiz 1 description | C1 | studentquiz1 | 1 | - And the following "questions" exist: - | questioncategory | qtype | name | questiontext | - | Default for StudentQuiz 1 | essay | Test question to be copied | Write about whatever you want | - - @javascript - Scenario: Backup and restore of the current course - When I log in as "admin" - And I backup "Course 1" course using this options: - | Confirmation | Filename | test_backup.mbz | - And I restore "test_backup.mbz" backup into a new course using this options: - | Schema | Course name | Course 2 | - | Schema | Course short name | Course 2 | - Then I should see "Course 2" - - And I go to the courses management page - And I click on "delete" action for "Course 1" in management course listing - And I press "Delete" - And I should see "Deleting C1" - And I should see "C1 has been completely deleted" - - And I am on the "StudentQuiz 1" "mod_studentquiz > View" page - And I should see "Create new question" - And I should see "Test question to be copied" - And "Start Quiz" "button" should exist diff --git a/tests/behat/moodle_backup.feature b/tests/behat/moodle_backup.feature deleted file mode 100644 index 3d54a96a..00000000 --- a/tests/behat/moodle_backup.feature +++ /dev/null @@ -1,45 +0,0 @@ -@mod @mod_studentquiz -Feature: Backup and restore of moodle exports - In order to reuse my studentquizzes - As a admin - I need to be able to use the moodles backup and restore features - - Background: - Given the following "courses" exist: - | fullname | shortname | category | - | Course 1 | C1 | 0 | - And the following "users" exist: - | username | firstname | lastname | email | - | student1 | Sam1 | Student1 | student1@example.com | - | teacher1 | Sam1 | Teacher1 | teacher1@example.com | - - @javascript @_file_upload - Scenario Outline: Restore moodle backups containing old StudentQuiz activity - When I am on the "Course 1" "restore" page logged in as "admin" - And I press "Manage backup files" - And I upload "mod/studentquiz/tests/fixtures/" file to "Files" filemanager - And I press "Save changes" - And I restore "" backup into a new course using this options: - And I log out - And the following "course enrolments" exist: - | user | course | role | - | student1 | | student | - | teacher1 | | teacher | - And I am on the "" "mod_studentquiz > View" page logged in as "" - Then I should see "Create new question" - And "Start Quiz" "button" should exist - And I should see "" - And I am on the "" "mod_studentquiz > Ranking" page - And "1" row "Points for latest correct attemps" column of "rankingtable" table should contain "" - And "1" row "Total Points" column of "rankingtable" table should contain "" - # TODO: These backups have good data selection, we could test for existence and correctness of these - # TODO: A scenario with the new studentquiz so other datas could be tested too - # TODO: We will have more testing after we fix the backup/restore issue. - - Examples: - | file | username | course | studentquiz | questionname | pos_1_correct_answered_points | pos_1_total_points | - | backup-moodle2-course-two-moodle_35_sq404_missingstate.mbz | student1 | Course Two | StudentQuiz 1 | False is correct | 0 | 10 | - | backup-moodle2-course-two-moodle_35_sq404_correctstate.mbz | student1 | Course Two | StudentQuiz 1 | False is correct | 0 | 15 | - | backup-moodle2-course-with-studentquiz-m311.mbz | teacher1 | Course Three | StudentQuiz 1 | Test T/F Question | 0 | 0 | - | backup-moodle2-course-2-311-with-questiondata.mbz | student1 | C2 | StudentQuiz 1 | T/F Student | 4 | 31 | - | backup-moodle2-course-with-studentquiz-m400.mbz | teacher1 | Course Four | StudentQuiz 1 | Question T/F for 4.0 | 0 | 0 | diff --git a/tests/behat/state_history_backup_restore.feature b/tests/behat/state_history_backup_restore.feature deleted file mode 100644 index c2cd9d20..00000000 --- a/tests/behat/state_history_backup_restore.feature +++ /dev/null @@ -1,25 +0,0 @@ -@mod @mod_studentquiz -Feature: Restore of studentquizzes in moodle exports without state history table - In order to reuse my studentquizzes - As a admin - I need to be able to restore the moodles backups from old studentquizzes, and the state history feature work normally - - Background: - Given the following "courses" exist: - | fullname | shortname | category | - | Course 1 | C1 | 0 | - - @javascript @_file_upload @_switch_window - Scenario: Restore moodle backups containing old StudentQuiz activity without state history table - Given I am on the "Course 1" "restore" page logged in as "admin" - And I press "Manage backup files" - And I upload "mod/studentquiz/tests/fixtures/backup-moodle2-course-3-sqo-20211011-missing_state_history.mbz" file to "Files" filemanager - And I press "Save changes" - And I restore "backup-moodle2-course-3-sqo-20211011-missing_state_history.mbz" backup into a new course using this options: - And I am on the "StudentQuiz One" "mod_studentquiz > View" page - And I should see "Question Test 1" - And I choose "Preview" action for "Question Test 1" in the question bank - And I switch to "questionpreview" window - Then I click on "History" "link" - And I should see "James Potter" in the "Question saved ('Draft')" "table_row" - And I should see "-" in the "Question set to 'Approved'" "table_row"