CSC/ECE 517 Fall 2023: E2367. Reimplement participants controller.rb, participants.rb and its child classes: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
(29 intermediate revisions by one other user not shown)
Line 8: Line 8:
[http://expertiza.ncsu.edu/ Expertiza] is a prominent open-source project founded on the Ruby on Rails framework, serving as a collaborative effort between the faculty and students of NC State. This web application facilitates instructors in generating customized assignments, including both new and existing tasks. Additionally, instructors can establish a roster of topics for student enrollment. Within Expertiza, students have the ability to form teams for collaborative work on various projects and assignments. An integral aspect of the platform is the provision for students to conduct peer reviews of their peers' submissions.
[http://expertiza.ncsu.edu/ Expertiza] is a prominent open-source project founded on the Ruby on Rails framework, serving as a collaborative effort between the faculty and students of NC State. This web application facilitates instructors in generating customized assignments, including both new and existing tasks. Additionally, instructors can establish a roster of topics for student enrollment. Within Expertiza, students have the ability to form teams for collaborative work on various projects and assignments. An integral aspect of the platform is the provision for students to conduct peer reviews of their peers' submissions.


Distinguished by its support for a diverse array of document types, Expertiza enables submission of various formats such as URLs and wiki pages. Serving as an open-source learning management system developed using Ruby on Rails, Expertiza embodies an extensive suite of functionalities that empower students to submit and engage in peer review processes encompassing various learning objects like articles, codes, and websites. Instructors wield the capability to oversee and assess the submissions made by students through the platform. Expertiza is instrumental in facilitating instructors and teaching assistants in managing assignments for the courses they administer.
 
== '''Project Objectives''' ==
 
'''Overall Purpose:'''
 
The Expertiza project, built on the Ruby on Rails framework, serves as an open-source learning management system. It facilitates collaborative assignments, peer reviews, and diverse document submissions. The primary aim of this reimplemented project is to strengthen the reliability and functionality of the participant management system within Expertiza.
 




Line 37: Line 43:
The base participant.rb file defines the fundamental structure and behavior for all participants in the system, including shared associations, delegate methods, and validations. The file incorporates methods related to participant handling, user information retrieval, email functionalities, authorization, sorting, and export functionality.
The base participant.rb file defines the fundamental structure and behavior for all participants in the system, including shared associations, delegate methods, and validations. The file incorporates methods related to participant handling, user information retrieval, email functionalities, authorization, sorting, and export functionality.


The project's primary objective revolves around enhancing the reliability and functionality of the participant-related components, thereby fortifying the overall system's capabilities and improving the testing process to ensure robustness and stability within the Expertiza platform.
The reimplementation must make sense; when reviewing the original model, we discovered that certain functions were unnecessary for the controller class and model in question and needed to be implemented in a different model. The majority of the adjustments were made to separate methods with a single capability pertinent to certain classes by deleting, combining, and replacing methods.To improve readability, notes are provided to every technique. The discussion of the reimplementations continues below with further details.




Line 104: Line 107:
== '''Testing Plan''' ==
== '''Testing Plan''' ==


=== assignment_participant_spec.rb: ===


Reimplementation of assignment_participant_spec.rb is as follows:
=== course_participant_spec.rb: ===
 
 
'''Tests'''
 
 
{| class="wikitable" style="margin-left:40px"
|-
! Test No. !! Description
|-
| 1 || Tests if a copy of the participant is created
|-
| 2 || Tests if copy exists then return nil
|-
| 3 || Tests if the record is empty then raise an error
|-
| 4 || Tests if the record does not have enough items then raises error
|-
| 5 || Tests if course with id not found
|-
| 6 || Tests to create course participant form record
|-
| 7 || Tests if csv file is created
|-
| 8 || Tests if option is empty if fields is empty
|-
| 9 || Tests if option is not empty if fields is not empty
|
|}
 
 
'''Test Environment:'''
 
1] Ruby on Rails environment.
 
2] RSpec for testing.
 
3] Factory Bot for test data creation.
 
 
'''Objective:'''
 
Ensure that the new methods (copy, import, export, export_fields) in the CourseParticipant class are functioning correctly.
 
 
'''Test Cases:'''
 
==== Testing #copy method ====
 
 
[[File:Test1-2.png | 800px]]
 
'''Test Case 1: Creating a Copy'''
 
''Assertion:''
 
Calling the copy method on a CourseParticipant object should create a new instance of AssignmentParticipant.
 
''Steps:''
 
1] Mock the AssignmentParticipant.create method to return a new participant.
 
2] Mock the set_handle method.
 
3] Call copy with a valid assignment ID.
 
4] Assert that the returned value is an instance of AssignmentParticipant.
 
''Explanation:''
 
This test case verifies that the copy method successfully creates a new AssignmentParticipant when called on a CourseParticipant object.
 
 
 
'''Test Case 2: Returning Nil if Copy Exists'''
 
''Assertion:''
 
The copy method should return nil if a copy already exists, simulating a scenario where the participant has already been copied.
 
''Steps:''
 
1] Mock the AssignmentParticipant.where and AssignmentParticipant.first methods to simulate an existing participant.
 
2] Call copy with an assignment ID.
 
3] Assert that the returned value is nil.
 
''Explanation:''
 
This test case ensures that the copy method correctly handles the case where a copy of the participant already exists, returning nil in such situations.
 
==== Testing #import method:  =====
 
 
[[File:Test3-6.png | 800px]]
 
 
'''Test Case 1: Handling Empty Record'''
 
''Assertion:''
 
An error should be raised when trying to import a course participant with an empty record.
 
''Steps:''
 
1] Call import with an empty record.
 
2] Assert that an error is raised with the message "No user id has been specified."
 
''Explanation:''
 
This test case checks that the import method correctly identifies and handles attempts to import a course participant with insufficient data.
 
 
'''Test Case 2: Raises error if record does not have enough items'''
 
''Assertion:''
 
An error should be raised if the record doesn't have enough items for importing a course participant.
 
''Steps:''
 
1] Prepare a record with insufficient items (e.g., missing required attributes).
 
2] Call the import method with the prepared record.
 
3] Assert that an error is raised with the message "The record containing #{row[:name]} does not have enough items."
 
''Explanation:''
 
This test case ensures that the system correctly identifies and handles records that lack the necessary information to create a course participant.
 
 
'''Test Case 3: Raises error if course with id not found'''
 
''Assertion:''
 
An error should be raised when attempting to import a course participant with a non-existing course ID.
 
''Steps:''
 
1] Set up a scenario where the Course.find method returns nil to simulate a non-existing course.
 
2] Call the import method with a valid record and a non-existing course ID.
 
3] Assert that an error is raised with the message "The course with the id "2" was not found."
 
''Explanation:''
 
This test case ensures that the system handles cases where an attempt is made to import a course participant into a non-existing course.
 
 
'''Test Case 4: Creating Course Participant from Record'''
 
''Assertion:''
 
The import method should create a new CourseParticipant from the provided record.
 
''Steps:''
 
1] Mock the necessary methods for finding a course and getting the user ID.
 
2] Call import with a valid record.
 
3] Assert that the returned value is an instance of CourseParticipant.
 
''Explanation:''
This test case verifies that the import method successfully creates a new CourseParticipant from the provided record.
 
 
==== Testing #export method:====
 
[[File:Test7.png | 800px]]
 
'''Test Case: Checking CSV File Creation'''
 
''Assertion:''
 
Calling the export method on a CourseParticipant instance should generate a CSV file.
 
''Steps:''
 
1] Create a mock CSV file.
 
2] Call export with options and the mock CSV file.
 
3] Assert that the CSV file is created and contains the expected data.
 
''Explanation:''
 
This test case ensures that the export method functions correctly by generating a CSV file as expected.


1) In the #dir_path method, test doubles are introduced for the assignment object to isolate the test from the actual implementation. This allows you to set expectations on method calls and control the behavior of the test double.


2) Expectations are set using expect and receive to ensure that the directory_path method is called on the test double (assignment) with the expected return values. This is a way to explicitly specify the behavior of the test double in the context of the test.
==== Testing #export_fields method: ====


3) The #assign_quiz method now includes detailed testing scenarios (Test scenario 1 to Test scenario 5) with clear given-when-then comments. Each scenario outlines specific expectations for the method call and the expected outcomes. This provides clarity on the expected behavior of the method under different conditions.


4) The #review_score method is tested in different contexts, including cases where there are no assessments, one assessment, multiple assessments, different maximum possible scores, and the computation of scores as a percentage. This comprehensive testing ensures that the method behaves correctly under various conditions.
[[File:Test8-9.png | 800px]]


5) The #fullname and #name methods are tested in scenarios where the user has or doesn't have the corresponding attribute. This ensures that the methods handle different user attribute states correctly.
'''Test Case 1: Handling Empty Options'''


6) The #scores method is tested in various contexts, including cases where the participant has completed questionnaires, quiz questionnaires, is part of a microtask, has a grade, and when the total score exceeds 100. This testing provides coverage for the different aspects of score calculation and handling.


7) The new code includes several new test scenarios for the existing #submit_hyperlink method. These scenarios cover cases where the hyperlink is empty or not a valid URL, and they ensure that the method behaves correctly in these situations.
''Assertion:''


8) A new method grant_publishing_rights has been added. This method appears to handle the granting of publishing rights based on a private key and participant digital signatures.
If options are empty, the export_fields method should return an empty array.
Multiple test scenarios are provided to cover different cases, such as valid private key, empty participant list, and invalid digital signatures.


9) A new method verify_digital_signature has been added, which seems to validate whether the public key matches the private key.
''Steps:''
Two test scenarios are provided to cover cases where the keys match or do not match.


10) The #set_handle method has been retained with rephrased comments and test descriptions.
1] Call export_fields with an empty options hash.
Test scenarios, particularly for when the user handle is not nil or empty, have been clarified.


11) The #path method has been retained with comments and test descriptions adjusted.
2] Assert that the returned value is an empty array.
Test scenarios for different combinations of assignment path and team directory number have been maintained.


12) A new method review_file_path has been introduced. It appears to generate file paths for review-related information based on response map details.
''Explanation:''
Test scenarios cover cases with valid and invalid response map IDs, as well as cases with valid and invalid reviewee or participant details.


13) The #update_resubmit_times method has been retained, and the comments and test descriptions have been updated.
This test case checks that the export_fields method behaves as expected when no options are provided.


14) The #current_stage method has been maintained with rephrased comments and test descriptions.
Test scenarios for different cases, such as a valid topic_id with and without a current stage, as well as cases with an invalid topic_id, have been updated.


Each test scenario is documented with clear comments outlining the given conditions, the method invocation, and the expected outcomes. This documentation enhances the readability and understanding of the test cases.The new test cases maintain consistency with the existing test structure and naming conventions. This consistency is essential for readability and maintainability.
'''Test Case 2: Returning Non-empty Fields for Provided Options'''


Overall, the changes introduce more explicit control over the test environment using test doubles and provide detailed scenarios for the #assign_quiz method. These changes can improve the clarity of the tests and make them more robust by isolating them from the actual implementations and focusing on specific behaviors. In summary, the new code enhances the test coverage for the AssignmentParticipant class by introducing tests for additional methods. The detailed scenarios cover various aspects of the methods, ensuring their correctness and robustness under different conditions.
''Assertion:''


If options are provided, the export_fields method should return a non-empty array of export fields.


=== course_participant_spec.rb: ===


The new code uses the describe and it syntax extensively for specifying behavior, whereas the old code uses RSpec.describe and context for the same purpose. Both are valid ways of structuring RSpec tests, but the new code seems to follow a slightly different convention.
''Steps:''


1)The test case names in the new code are more descriptive and follow a consistent pattern using underscores, making them easier to understand.
1] Call export_fields with a hash of options.


2)The new code uses FactoryBot's build method for creating instances of various models, such as build(:assignment), build(:course_participant), etc. This is a good practice for creating test data.
2] Assert that the returned array is not empty.


3)The #copy method in the new code uses the allow and expect syntax to set up and verify expectations on method calls. It also explicitly checks if the copy exists and returns nil in one of the test cases.
''Explanation:''
This test case validates that the export_fields method correctly generates non-empty export fields when specific options are provided.


4)The #import method in the new code now raises specific errors for different scenarios, providing more detailed information about what went wrong. It also explicitly checks for the existence of a course with a given ID.


5)The #export method in the new code writes to a CSV file using CSV.open and checks if the file is created. This is a more explicit way of testing file creation.
'''Conclusion:'''


6)The #export_fields method in the new code explicitly checks if the fields are empty or not based on the provided options.
1] Ensure that all test cases pass successfully.


7)In the previous code, there are variables like user, course, and assignment that are defined but not used in the relevant test cases.
2] Verify that the assertions in the code are met during the testing process.


8)The new code has consistent indentation and formatting, making it more readable. Additionally, the new code has removed unnecessary comments and placeholders present in the old code.


9)The new code does not use type: :model as metadata for RSpec tests. This metadata is often used to specify the type of test (e.g., model, controller, feature).
=== assignment_participant_spec.rb: ===


'''Tests'''


=== Tests for course_participant_spec.rb: ===


{| class="wikitable" style="margin-left:40px"
{| class="wikitable" style="margin-left:40px"
Line 176: Line 358:
! Test No. !! Description  
! Test No. !! Description  
|-
|-
| 1 || Tests if a copy of the participant is created
| 1 || Tests if it returns the directory path of the assignment
|-
| 2 || Tests if it returns nil if assignment does not have a directory path
|-
|-
| 2 || Tests if copy exists then return nil
| 3 || Tests if it returns Team as Reviewer when the Assignment is Reviewed by the Team
|-
|-
| 3 || Tests if the record is empty then raise an error
| 4 || Tests if it returns Path Name of Associated Assignment Submission for the Team
|-
|-
| 4 || Tests if the record does not have enough items then raises error
| 5 || Tests if it returns Corresponding Author Feedback Responses Given by the Current Participant
|-
|-
| 5 || Tests if course with id not found
| 6 || Tests if it returns Corresponding Peer Review Responses Given by the Current Team
|-
|-
| 6 || Tests to create course participant form record
| 7 || Tests if it returns Corresponding Quiz Responses Given by the Current Participant
|-
|-
| 7 || Tests if csv file is created
| 8 || Tests if it returns Corresponding Metareview Responses Given by the Current Participant
|-
|-
| 8 || Tests if option is empty if fields is empty
| 9 || Tests if it returns Corresponding Teammate Review Responses Given by the Current Participant
|-
|-
| 9 || Tests if option is not empty if fields is not empty
| 10|| Tests if it returns Corresponding Bookmark Review Responses Given by the Current Participant
|}
|}




==== Test 1 and 2 ====


[[File:Test1-2.png | 800px]]
==== TestCase 1: #dir_path ====
 
[[File:Test1-2a.png | 800px]]
 
 
'''Test Case 1: Returns the directory path of the assignment'''
 
 
''Assertion:''
 
The dir_path method should return the correct directory path when the assignment has a directory path.
 
''Steps:''
 
1] Create a test double for the assignment object.
 
2] Set up the test double to return a known directory path.
 
3] Call the dir_path method on the test double.
 
4] Assert that the returned value is equal to the expected directory path.
 
''Explanation:''
This test case verifies that the dir_path method correctly retrieves and returns the directory path of the assignment when it exists.
 
 
'''Test Case 2: Returns nil if assignment does not have a directory path'''
 
''Assertion:''
The dir_path method should return nil when the assignment does not have a directory path.
 
''Steps:''
 
1] Create a test double for the assignment object.
 
2] Set up the test double to return nil for the directory path.
 
3] Call the dir_path method on the test double.
 
4] Assert that the returned value is nil.
 
''Explanation:''
 
This test case ensures that the dir_path method gracefully handles the scenario where the assignment does not have a directory path, returning nil as expected.
 
 
==== Test Case 2: #get_reviewer ====
 
[[File:Test_7a.png | 800px]]
 
 
''Assertion:''
 
The get_reviewer method should return the team when the associated assignment has team reviewing enabled.
 
''Steps:''
 
1] Mock the team_reviewing_enabled method of the assignment to return true.
 
2] Mock the team method of the participant to return a specific team.
 
3] Call get_reviewer on the participant.
 
4] Assert that the returned value is equal to the expected team.
 
''Explanation:''
 
This test case ensures that the get_reviewer method correctly returns the team when the assignment has team reviewing enabled.
 
==== Test Case 3: #path ====
 
[[File:Test_8a.png | 800px]]
 
''Assertion:''
 
The path method should return the path name of the associated assignment submission for the team.
 
''Steps:''
 
1] Stub the path method of the assignment to return 'assignment780'.
 
2] Stub the team method of the participant to return a specific team.
 
3] Stub the directory_num method of the team to return 780.
 
4] Call path on the participant.
 
5] Assert that the returned value is equal to 'assignment780/780'.
 
''Explanation:''
This test case ensures that the path method correctly generates the path name for the associated assignment submission for the team.
 
==== Test Case 4: #feedback ====
 
[[File:Test_9a.png | 800px]]
 
 
''Assertion:''
 
The feedback method should return corresponding author feedback responses given by the current participant.
 
''Steps:''
 
1] Stub the assessments_for method of FeedbackResponseMap to return a single response for the participant.
 
2] Call feedback on the participant.
 
3] Assert that the returned value is an array containing the response.
 
''Explanation:''
 
This test case verifies that the feedback method correctly retrieves and returns author feedback responses given by the current participant.
 
==== Test Case 5: #reviews ====
 
[[File:Test_2a.png | 800px]]
 
 
''Assertion:''
 
The reviews method should return corresponding peer review responses given by the current team.
 
''Steps:''
 
1] Stub the team method of the participant to return a specific team.
 
2] Stub the assessments_for method of ReviewResponseMap to return a specific response associated with the team.
 
3] Call reviews on the participant.
 
4] Assert that the returned value is an array containing the specified response.
 
''Explanation:''
 
This test case ensures that the reviews method correctly retrieves and returns peer review responses given by the current team.
 
==== Test Case 6: #quizzes_taken ====
 
[[File:Test_3a.png | 800px]]
 
 
''Assertion:''
 
The quizzes_taken method should return corresponding quiz responses given by the current participant.
 
''Steps:''
 
1] Stub the assessments_for method of QuizResponseMap to return an array containing a mock response for the participant.
 
2] Call quizzes_taken on the participant.
 
3] Assert that the returned value is an array containing the mock response.
 
''Explanation:''
 
This test case ensures that the quizzes_taken method correctly retrieves and returns quiz responses given by the current participant.
 
==== Test Case 7: #metareviews ====
 
[[File:Test_4a.png | 800px]]
 


'''Test Case 1: Creates a copy of participant:'''
''Assertion:''


This test case ensures that calling the copy method on a CourseParticipant object creates a new instance of AssignmentParticipant.
The metareviews method should return corresponding metareview responses given by the current participant.


''Steps:''


'''Test Case 2: Returns nil if copy exists:'''
1] Stub the assessments_for method of MetareviewResponseMap with a participant and return a mocked response.


This test case checks whether the copy method returns nil if a copy already exists, simulating a scenario where the participant has already been copied.
2] Call metareviews on the participant.


3] Assert that the returned value is an array containing the mocked response.


==== Test 3, 4, 5 and 6 ====
''Explanation:''


[[File:Test3-6.png | 800px]]
This test case ensures that the metareviews method correctly retrieves and returns metareview responses given by the current participant.


'''Test Case 3: Raises error if record is empty:'''
==== Test Case 8: #teammate_reviews ====


Verifies that an error is raised when trying to import a course participant with an empty record.
[[File:Test_5a.png | 800px]]




'''Test Case 4: Raises error if record does not have enough items:'''  
''Assertion:''


Ensures an error is raised if the record doesn't have enough items for importing a course participant.
The teammate_reviews method should return corresponding teammate review responses given by the current participant.


''Steps:''


'''Test Case 5: Raises error if course with id not found:'''
1] Stub the assessments_for method of TeammateReviewResponseMap to return a specific response for the participant.


Checks if an error is raised when attempting to import a course participant with a non-existing course ID.
2] Call teammate_reviews on the participant.


3] Assert that the returned value is an array containing the specified response.


'''Test Case 6: Creates course participant from record:'''
''Explanation:''


Verifies that the import method creates a CourseParticipant instance from a given record.
This test case ensures that the teammate_reviews method correctly retrieves and returns teammate review responses given by the current participant.


==== Test Case 9: #bookmark_reviews ====


==== Test 7 ====
[[File:Test_6a.png | 800px]]


[[File:Test7.png | 800px]]


'''Test Case 7: Checks if CSV file is created:'''
''Assertion:''


This test case ensures that calling the export method on a CourseParticipant instance generates a CSV file.
The bookmark_reviews method should return corresponding bookmark review responses given by the current participant.


''Steps:''


==== Test 8 and 9 ====
1] Stub/mock the behavior of BookmarkRatingResponseMap.assessments_for to return a specific response for a participant.


[[File:Test8-9.png | 800px]]
2] Call bookmark_reviews on the participant.


'''Test Case 8: Option is empty, fields is empty:'''
3] Assert that the returned value is an array containing the mocked response.


Checks if the export fields are empty when no options are provided.
''Explanation:''


This test case ensures that the bookmark_reviews method correctly retrieves and returns bookmark review responses given by the current participant.


'''Test Case 9: Option is not empty, fields is not empty:'''


Verifies that export fields are not empty when specific options are provided.
Overall, the changes introduce more explicit control over the test environment using test doubles and provide detailed scenarios for the #assign_quiz method. These changes can improve the clarity of the tests and make them more robust by isolating them from the actual implementations and focusing on specific behaviors. In summary, the new code enhances the test coverage for the AssignmentParticipant class by introducing tests for additional methods. The detailed scenarios cover various aspects of the methods, ensuring their correctness and robustness under different conditions.


== Relevant Links ==
== Relevant Links ==
Line 261: Line 609:


'''Pull request:''' https://github.com/expertiza/reimplementation-back-end/pull/49
'''Pull request:''' https://github.com/expertiza/reimplementation-back-end/pull/49
'''Youtube Video Link:''' https://youtu.be/2lbE8IFZrJE





Latest revision as of 03:59, 5 December 2023

This wiki page is for the description of changes made under E2367 OSS assignment for Fall 2023, CSC/ECE 517

Introduction

Expertiza is a prominent open-source project founded on the Ruby on Rails framework, serving as a collaborative effort between the faculty and students of NC State. This web application facilitates instructors in generating customized assignments, including both new and existing tasks. Additionally, instructors can establish a roster of topics for student enrollment. Within Expertiza, students have the ability to form teams for collaborative work on various projects and assignments. An integral aspect of the platform is the provision for students to conduct peer reviews of their peers' submissions.


Project Objectives

Overall Purpose:

The Expertiza project, built on the Ruby on Rails framework, serves as an open-source learning management system. It facilitates collaborative assignments, peer reviews, and diverse document submissions. The primary aim of this reimplemented project is to strengthen the reliability and functionality of the participant management system within Expertiza.


Overview of the Classes

participants_controller.rb:

The ParticipantsController is responsible for managing participants in an application. Participants can be associated with either "Course" or "Assignment" models. It handles actions related to creating, updating, retrieving, and deleting participants. Inherit copies existing participants from a course down to its assignment while bequeath copies existing participants from an assignment up to its course. It has two private methods namely copy_participants_from_source_to_target which copies participants from source to target and participant_params.

assignment_participant.rb:

The assignment_participant.rb is a model class that has many associations including ‘assignment’. This association signifies that an AssignmentParticipant belongs to a specific assignment. The AssignmentParticipant class includes several attributes such as avg_vol_per_round, overall_avg_vol and handle that are vital for its functionality. There are many methods present which collectively facilitate various actions and operations related to managing participants in assignments, including reviewing, copying, importing, and handling file paths and deadlines. They include review_file_path, current_stage, stage_deadline, current_user_is_reviewer, reviews, dir_path, etc. There are also a couple of methods that use digital signatures such as assign_copyright and verify_digital_signature.

course_participant.rb:

The course_participant model has a class named CourseParticipant that inherits from a class called Participant. It is used to manage participants in courses, allowing for copying participants to assignments and importing new participants into a course. It consists of three methods namely copy, import and path. Copy creates a copy of a course participant for an assignment. Path method returns the path of the course participant while self.import method is used for importing course participants by taking row_hash, session, and id as parameters.


Background of the Project

The Expertiza project involves the reimplementing of the participants_controller.rb and participants.rb files, along with their respective child classes. The previous iteration of the participant model and controller underwent reimplementations in prior semesters, resulting in tests that relied extensively on mocks and stubs due to missing components.

The participants_controller.rb file encapsulates various methods and functionalities vital to managing participants within the system. This includes actions like adding, updating, and deleting participants, inheriting participants from courses to assignments, bequeathing participants from assignments to courses, changing participant handles, viewing copyright grants, and more. The controller makes use of helper functions, associations, and delegate methods to streamline participant operations.

Meanwhile, the course_participants.rb file extends the functionality of the base participant class, focusing on operations specific to course participants. This includes copying participants to assignments, importing course participants, and defining paths for course participants within the project.

The base participant.rb file defines the fundamental structure and behavior for all participants in the system, including shared associations, delegate methods, and validations. The file incorporates methods related to participant handling, user information retrieval, email functionalities, authorization, sorting, and export functionality.


Design Decisions

participants_controller.rb:

We have reimplemented participants_controller.rb by making following changes:

1) Changed function name: The function name 'copy_participants_from_source_to_target' has been renamed to 'copy_participants' as original name was too long.

2) Improved Code Comments: The code has detailed comments for each action method, the purpose of the method and the expected parameters. The parameters for each action method are explicitly defined in comments, making it clear which parameters are expected.

3) Improved Error Handling: Exceptions are caught more specifically (e.g., StandardError) to provide better error messages.

4) Refactored delete Method: The destroy method has been refactored to use participant.delete(false) to avoid accidental deletion and provides better error handling.

5) Consistent Status Codes: The code uses consistent HTTP status codes for responses, for example, using status: :not_found for a resource not found.

6) Consistent JSON Response Format: The JSON responses are structured consistently, with keys like "model_object" and "participants," making it easier for clients to consume the API.

assignment_participant.rb:

This is the reimplemented AssignmentParticipant class. It is a subclass of the Participant class and includes additional functionalities and methods specific to participants assigned to an assignment in the system.

In the `assignment_participant.rb` class, several changes and improvements have been made to enhance the readability and maintainability of the code. Here are the specific modifications made:


1. Removed certain comments and obsolete code for better readability and clarity.

2. Introduced the safe navigation operator (`&.`) in several places to avoid nil errors, particularly in cases where object references may be nil.

3. Simplified certain methods, such as `reviewers` and `feedback`, for cleaner and more readable code.

4. Improved string formatting for directory paths and file paths to enhance readability.

5. Enhanced error handling in the `import` method to provide more informative error messages and handle exceptional cases more gracefully.

These changes aim to make the code more maintainable and concise while ensuring that the functionality and integrity of the `AssignmentParticipant` class remain intact.

course_participant.rb:

The following changes were reimplemented in the course_participant.rb

In the CourseParticipant class, several changes and improvements have been made to enhance the readability and maintainability of the code. Here are the specific modifications made:

1] The copy method has been simplified using the find_or_create_by method, which helps to find an existing record or create a new one if it doesn't exist.

2] In the import method, the find_or_create_by method has been used to both find or create a user and find or create a course participant. This helps to streamline the process and handle the cases where the records may or may not exist.

3] The path method has been refactored to use the safe navigation operator (&.) to avoid potential nil errors during the construction of the path. This ensures that the code is more robust and handles potential null references gracefully.

These changes aim to make the code more concise and readable, without compromising the functionality or integrity of the CourseParticipant class.


Testing Plan

course_participant_spec.rb:

Tests


Test No. Description
1 Tests if a copy of the participant is created
2 Tests if copy exists then return nil
3 Tests if the record is empty then raise an error
4 Tests if the record does not have enough items then raises error
5 Tests if course with id not found
6 Tests to create course participant form record
7 Tests if csv file is created
8 Tests if option is empty if fields is empty
9 Tests if option is not empty if fields is not empty


Test Environment:

1] Ruby on Rails environment.

2] RSpec for testing.

3] Factory Bot for test data creation.


Objective:

Ensure that the new methods (copy, import, export, export_fields) in the CourseParticipant class are functioning correctly.


Test Cases:

Testing #copy method

Test Case 1: Creating a Copy

Assertion:

Calling the copy method on a CourseParticipant object should create a new instance of AssignmentParticipant.

Steps:

1] Mock the AssignmentParticipant.create method to return a new participant.

2] Mock the set_handle method.

3] Call copy with a valid assignment ID.

4] Assert that the returned value is an instance of AssignmentParticipant.

Explanation:

This test case verifies that the copy method successfully creates a new AssignmentParticipant when called on a CourseParticipant object.


Test Case 2: Returning Nil if Copy Exists

Assertion:

The copy method should return nil if a copy already exists, simulating a scenario where the participant has already been copied.

Steps:

1] Mock the AssignmentParticipant.where and AssignmentParticipant.first methods to simulate an existing participant.

2] Call copy with an assignment ID.

3] Assert that the returned value is nil.

Explanation:

This test case ensures that the copy method correctly handles the case where a copy of the participant already exists, returning nil in such situations.

Testing #import method: =


Test Case 1: Handling Empty Record

Assertion:

An error should be raised when trying to import a course participant with an empty record.

Steps:

1] Call import with an empty record.

2] Assert that an error is raised with the message "No user id has been specified."

Explanation:

This test case checks that the import method correctly identifies and handles attempts to import a course participant with insufficient data.


Test Case 2: Raises error if record does not have enough items

Assertion:

An error should be raised if the record doesn't have enough items for importing a course participant.

Steps:

1] Prepare a record with insufficient items (e.g., missing required attributes).

2] Call the import method with the prepared record.

3] Assert that an error is raised with the message "The record containing #{row[:name]} does not have enough items."

Explanation:

This test case ensures that the system correctly identifies and handles records that lack the necessary information to create a course participant.


Test Case 3: Raises error if course with id not found

Assertion:

An error should be raised when attempting to import a course participant with a non-existing course ID.

Steps:

1] Set up a scenario where the Course.find method returns nil to simulate a non-existing course.

2] Call the import method with a valid record and a non-existing course ID.

3] Assert that an error is raised with the message "The course with the id "2" was not found."

Explanation:

This test case ensures that the system handles cases where an attempt is made to import a course participant into a non-existing course.


Test Case 4: Creating Course Participant from Record

Assertion:

The import method should create a new CourseParticipant from the provided record.

Steps:

1] Mock the necessary methods for finding a course and getting the user ID.

2] Call import with a valid record.

3] Assert that the returned value is an instance of CourseParticipant.

Explanation: This test case verifies that the import method successfully creates a new CourseParticipant from the provided record.


Testing #export method:

Test Case: Checking CSV File Creation

Assertion:

Calling the export method on a CourseParticipant instance should generate a CSV file.

Steps:

1] Create a mock CSV file.

2] Call export with options and the mock CSV file.

3] Assert that the CSV file is created and contains the expected data.

Explanation:

This test case ensures that the export method functions correctly by generating a CSV file as expected.


Testing #export_fields method:

Test Case 1: Handling Empty Options


Assertion:

If options are empty, the export_fields method should return an empty array.

Steps:

1] Call export_fields with an empty options hash.

2] Assert that the returned value is an empty array.

Explanation:

This test case checks that the export_fields method behaves as expected when no options are provided.


Test Case 2: Returning Non-empty Fields for Provided Options

Assertion:

If options are provided, the export_fields method should return a non-empty array of export fields.


Steps:

1] Call export_fields with a hash of options.

2] Assert that the returned array is not empty.

Explanation: This test case validates that the export_fields method correctly generates non-empty export fields when specific options are provided.


Conclusion:

1] Ensure that all test cases pass successfully.

2] Verify that the assertions in the code are met during the testing process.


assignment_participant_spec.rb:

Tests


Test No. Description
1 Tests if it returns the directory path of the assignment
2 Tests if it returns nil if assignment does not have a directory path
3 Tests if it returns Team as Reviewer when the Assignment is Reviewed by the Team
4 Tests if it returns Path Name of Associated Assignment Submission for the Team
5 Tests if it returns Corresponding Author Feedback Responses Given by the Current Participant
6 Tests if it returns Corresponding Peer Review Responses Given by the Current Team
7 Tests if it returns Corresponding Quiz Responses Given by the Current Participant
8 Tests if it returns Corresponding Metareview Responses Given by the Current Participant
9 Tests if it returns Corresponding Teammate Review Responses Given by the Current Participant
10 Tests if it returns Corresponding Bookmark Review Responses Given by the Current Participant


TestCase 1: #dir_path


Test Case 1: Returns the directory path of the assignment


Assertion:

The dir_path method should return the correct directory path when the assignment has a directory path.

Steps:

1] Create a test double for the assignment object.

2] Set up the test double to return a known directory path.

3] Call the dir_path method on the test double.

4] Assert that the returned value is equal to the expected directory path.

Explanation: This test case verifies that the dir_path method correctly retrieves and returns the directory path of the assignment when it exists.


Test Case 2: Returns nil if assignment does not have a directory path

Assertion: The dir_path method should return nil when the assignment does not have a directory path.

Steps:

1] Create a test double for the assignment object.

2] Set up the test double to return nil for the directory path.

3] Call the dir_path method on the test double.

4] Assert that the returned value is nil.

Explanation:

This test case ensures that the dir_path method gracefully handles the scenario where the assignment does not have a directory path, returning nil as expected.


Test Case 2: #get_reviewer


Assertion:

The get_reviewer method should return the team when the associated assignment has team reviewing enabled.

Steps:

1] Mock the team_reviewing_enabled method of the assignment to return true.

2] Mock the team method of the participant to return a specific team.

3] Call get_reviewer on the participant.

4] Assert that the returned value is equal to the expected team.

Explanation:

This test case ensures that the get_reviewer method correctly returns the team when the assignment has team reviewing enabled.

Test Case 3: #path

Assertion:

The path method should return the path name of the associated assignment submission for the team.

Steps:

1] Stub the path method of the assignment to return 'assignment780'.

2] Stub the team method of the participant to return a specific team.

3] Stub the directory_num method of the team to return 780.

4] Call path on the participant.

5] Assert that the returned value is equal to 'assignment780/780'.

Explanation: This test case ensures that the path method correctly generates the path name for the associated assignment submission for the team.

Test Case 4: #feedback


Assertion:

The feedback method should return corresponding author feedback responses given by the current participant.

Steps:

1] Stub the assessments_for method of FeedbackResponseMap to return a single response for the participant.

2] Call feedback on the participant.

3] Assert that the returned value is an array containing the response.

Explanation:

This test case verifies that the feedback method correctly retrieves and returns author feedback responses given by the current participant.

Test Case 5: #reviews


Assertion:

The reviews method should return corresponding peer review responses given by the current team.

Steps:

1] Stub the team method of the participant to return a specific team.

2] Stub the assessments_for method of ReviewResponseMap to return a specific response associated with the team.

3] Call reviews on the participant.

4] Assert that the returned value is an array containing the specified response.

Explanation:

This test case ensures that the reviews method correctly retrieves and returns peer review responses given by the current team.

Test Case 6: #quizzes_taken


Assertion:

The quizzes_taken method should return corresponding quiz responses given by the current participant.

Steps:

1] Stub the assessments_for method of QuizResponseMap to return an array containing a mock response for the participant.

2] Call quizzes_taken on the participant.

3] Assert that the returned value is an array containing the mock response.

Explanation:

This test case ensures that the quizzes_taken method correctly retrieves and returns quiz responses given by the current participant.

Test Case 7: #metareviews


Assertion:

The metareviews method should return corresponding metareview responses given by the current participant.

Steps:

1] Stub the assessments_for method of MetareviewResponseMap with a participant and return a mocked response.

2] Call metareviews on the participant.

3] Assert that the returned value is an array containing the mocked response.

Explanation:

This test case ensures that the metareviews method correctly retrieves and returns metareview responses given by the current participant.

Test Case 8: #teammate_reviews


Assertion:

The teammate_reviews method should return corresponding teammate review responses given by the current participant.

Steps:

1] Stub the assessments_for method of TeammateReviewResponseMap to return a specific response for the participant.

2] Call teammate_reviews on the participant.

3] Assert that the returned value is an array containing the specified response.

Explanation:

This test case ensures that the teammate_reviews method correctly retrieves and returns teammate review responses given by the current participant.

Test Case 9: #bookmark_reviews


Assertion:

The bookmark_reviews method should return corresponding bookmark review responses given by the current participant.

Steps:

1] Stub/mock the behavior of BookmarkRatingResponseMap.assessments_for to return a specific response for a participant.

2] Call bookmark_reviews on the participant.

3] Assert that the returned value is an array containing the mocked response.

Explanation:

This test case ensures that the bookmark_reviews method correctly retrieves and returns bookmark review responses given by the current participant.


Overall, the changes introduce more explicit control over the test environment using test doubles and provide detailed scenarios for the #assign_quiz method. These changes can improve the clarity of the tests and make them more robust by isolating them from the actual implementations and focusing on specific behaviors. In summary, the new code enhances the test coverage for the AssignmentParticipant class by introducing tests for additional methods. The detailed scenarios cover various aspects of the methods, ensuring their correctness and robustness under different conditions.

Relevant Links

Github repository: https://github.com/krishna5701/reimplementation-back-end

Pull request: https://github.com/expertiza/reimplementation-back-end/pull/49

Youtube Video Link: https://youtu.be/2lbE8IFZrJE


Team

Mentor

Devashish Vachhani

Student Team

1] Krishna Patel (kpatel43@ncsu.edu)

2] Janhavi Pendse (jspendse@ncsu.edu)

3] Payal Mehta (pmehta5@ncsu.edu)