CSC/ECE 517 Fall 2021 - E2167. Testing - Team Related Files: Difference between revisions
(12 intermediate revisions by the same user not shown) | |||
Line 443: | Line 443: | ||
</font> | </font> | ||
[[File:user_create.png|600px]] | [[File:user_create.png|600px]] <br> | ||
<font size = '2'> | |||
<br>Create context scenario 1: <br> | |||
#User that is not defined is added to assignment or course team. | |||
#Page throws 'user not defined' error. | |||
#Response is redirected to teams list page. | |||
</font> | |||
<font size = 1> | <font size = 1> | ||
#Test adding new user to assignment or course team | #Test adding new user to assignment or course team | ||
Line 461: | Line 466: | ||
end | end | ||
end | end | ||
</font> | |||
<font size = '2'> | |||
<br>Create context scenario 2: <br> | |||
#User that is not participant of an assignment team is added to an assignment team. | |||
#Page throws 'user not participant of the current assignment' error. | |||
#Response is redirected to teams list page. | |||
</font> | |||
<font size = 1> | |||
context 'when user is added to assignment team' do | context 'when user is added to assignment team' do | ||
it 'it throws error when user added is not a participant of the current assignment' do | it 'it throws error when user added is not a participant of the current assignment' do | ||
Line 478: | Line 490: | ||
end | end | ||
end | end | ||
</font> | |||
<font size = '2'> | |||
<br>Create context scenario 3: <br> | |||
#User is added to an assignment which already has maximum number of participants. | |||
#Page throws 'team already has the maximum number of members' error. | |||
#Response is redirected to teams list page. | |||
</font> | |||
<font size = 1> | |||
context 'when user is added to assignment team' do | context 'when user is added to assignment team' do | ||
it 'it throws error when assignmentTeam has maximum number of participants' do | it 'it throws error when assignmentTeam has maximum number of participants' do | ||
Line 496: | Line 515: | ||
end | end | ||
end | end | ||
</font> | |||
<font size = '2'> | |||
<br>Create context scenario 4: <br> | |||
#Valid user that is participant of an assignment team is added to the assignment team with members less than maximum numbers. | |||
#The user gets successfully added to the team. | |||
#Response is redirected to teams list page. | |||
</font> | |||
<font size = 1> | |||
context 'when user is added to assignment team' do | context 'when user is added to assignment team' do | ||
it 'new user gets successfully added to the assignment' do | it 'new user gets successfully added to the assignment' do | ||
Line 514: | Line 540: | ||
end | end | ||
end | end | ||
</font> | |||
<font size = '2'> | |||
<br>Create context scenario 5: <br> | |||
#User that is not participant of a course team is added to the course team. | |||
#Page throws 'user not participant of the current course' error. | |||
#Response is redirected to teams list page. | |||
</font> | |||
<font size = 1> | |||
context 'when user is added to course team' do | context 'when user is added to course team' do | ||
it 'it throws error when user added to course Team is not defined' do | it 'it throws error when user added to course Team is not defined' do | ||
Line 531: | Line 564: | ||
end | end | ||
end | end | ||
</font> | |||
<font size = '2'> | |||
<br>Create context scenario 6: <br> | |||
#User is added to course which already has maximum number of participants. | |||
#Page throws 'team already has the maximum number of members' error. | |||
#Response is redirected to teams list page. | |||
</font> | |||
<font size = 1> | |||
context 'when user is added to course team' do | context 'when user is added to course team' do | ||
it 'it throws error when courseTeam has maximum number of participants' do | it 'it throws error when courseTeam has maximum number of participants' do | ||
Line 549: | Line 589: | ||
end | end | ||
end | end | ||
</font> | |||
<font size = '2'> | |||
<br>Create context scenario 7: <br> | |||
#Valid user that is participant of a course team is added to the course team with members less than the maximum numbers. | |||
#The user gets successfully added to the team. | |||
#Response is redirected to teams list page. | |||
</font> | |||
<font size = 1> | |||
context 'when user is added to course team' do | context 'when user is added to course team' do | ||
it 'new user gets successfully added to course' do | it 'new user gets successfully added to course' do | ||
Line 1,104: | Line 1,151: | ||
====<font size = '3'> Coverage </font>==== | ====<font size = '3'> Coverage </font>==== | ||
[[File:E2127 Advertise run file.PNG]] | [[File:E2127 Advertise run file.PNG]] | ||
= Github Issues = | |||
<font size = '2'> | |||
We have created github issue for each non working test. <br> | |||
Link to the issues: <br> | |||
https://github.com/expertiza/expertiza/issues/2170 <br> | |||
https://github.com/expertiza/expertiza/issues/2168 <br> | |||
https://github.com/expertiza/expertiza/issues/2167 | |||
</font> | |||
= Old Page Link = | = Old Page Link = |
Latest revision as of 18:18, 9 December 2021
Relevant links
Github Repo : Repository
About Expertiza
Expertiza is an open source project based on Ruby on Rails framework. It is a web based program that allows instructors to create and update/edit assignments/tasks, and then assigns them to students. Students then can submit, edit, and update their assignments, as well as peer review other student's assignments.
Problem statement and background
There are a total of 5 controllers related to team: teams_controller, teams_users_controller, student_teams_controller, join_team_requests_controller, and advertise_for_partner_controller. They don't have any tests written for them. They all need essentially the same kind of fixtures or mocks to enable testing, mainly: a couple of students that can be added to the team, teams on Assignment and Course levels, some join team requests that can be sent from one student to another student to join a particular team.
Approach Chosen & Why?
We have chosen to approach this by subdividing each controller in terms of scenarios which relate to different methods that the controller has. We have made a shared context file in the support folder of the spec directory to hold the file that has the stubbed objects that are being used across the different controllers. It also has the tests that are same across all controllers. We have chosen to bring about robustness of test by writing unit tests and functional tests using RSpec and Capybara respectively. Unit Tests ensured that the particular functionality is being tested in an isolated setup and various cases are being considered for all methods. The tests are written so that they check the functionality of the controller without causing any collaboration issues with other controller files.
Implementation
- This controller can be found in spec/support
- It has all shared methods to be included in Teams related files.
Why this file? - There are a lot of methods common in the Teams Related Files, they basically use similar / same stubbed objects and methods. Implementing the teams_shared.rb file keeps the code DRY and makes use of good design principles.
Declared common stubbed objects
This creates single instances of superadmin, admin, instructor, teaching assistant, course and assignment. There are 2 instances of students, 5 instances of assignment teams, 2 instances of course teams, 4 instances of team join requests, and single instances of participant, node and team user.
shared_context 'object initializations' do let(:superadmin) { build_stubbed(:superadmin) } let(:admin) { build_stubbed(:admin) } let(:instructor) { build_stubbed(:instructor, id: 1) } let(:ta) { build_stubbed(:teaching_assistant) } let(:student1) { build_stubbed(:student, id: 1, name: 'student2065') } let(:student2) { build_stubbed(:student, id: 2) } let(:course1) { build_stubbed(:course, name: 'TestCourse', id:1, instructor_id: instructor.id) } let(:assignment1) { build_stubbed(:assignment, name: 'TestAssignment', id: 1) } let(:team1) { build_stubbed(:assignment_team, id: 1, name: 'wolfers',parent_id: assignment1.id) } let(:team2) { build_stubbed(:assignment_team, id: 2, parent_id: assignment1.id) } let(:team3) { build_stubbed(:assignment_team, id: 3, parent_id: assignment1.id) } let(:team4) { build_stubbed(:assignment_team, id: 4, parent_id: assignment1.id) } let(:team5) { build_stubbed(:course_team, id: 5, parent_id: course1.id) } let(:team6) { build_stubbed(:course_team, id: 6, parent_id: course1.id) } let(:team7) { build_stubbed(:assignment_team, name: 'test', parent_id: course1.id) } let(:join_team_request1) { build_stubbed(:join_team_request, id: 1, team_id: team1.id, status: 'P') } let(:join_team_request2) { build_stubbed(:join_team_request, id: 2, team_id: team2.id, status: 'P',comments: "Any comment") } let(:join_team_request3) { build_stubbed(:join_team_request, id: 3, team_id: team2.id, status: 'D',comments: "Updated") } let(:invalidrequest) { build_stubbed(:join_team_request) } let(:participant) { build_stubbed(:participant, id: 1) } let(:node1) { build_stubbed(:assignment_node, node_object_id: 1) } let(:team_user1) { build_stubbed(:team_user, team_id:1, user_id:1)}
The action_allowed method is there in all controllers, so a shared example was created which allows the tests to run in scope of different controllers. It contains tests for access checks for superadmin, admin, instructor and ta users. Only the authorization of student changes between the team related files so that test was not included in here.
shared_context 'authorization check', :shared_context => :metadata do # Testing to check Super Admin access it 'superadmin credentials' do stub_current_user(superadmin, superadmin.role.name, superadmin.role) expect(controller.send(:action_allowed?)).to be true end # Testing to check Admin access it 'admin credentials' do stub_current_user(admin, admin.role.name, admin.role) expect(controller.send(:action_allowed?)).to be true end # Testing to check TA access it 'ta credentials' do stub_current_user(ta, ta.role.name, ta.role) expect(controller.send(:action_allowed?)).to be true end # Testing to check Instructor access it 'instructor credentials' do stub_current_user(instructor, instructor.role.name, instructor.role) expect(controller.send(:action_allowed?)).to be true end
How to use this shared file? Add a require statement:
require './spec/support/teams_shared.rb'
Add include_context statements in the controller.
include_context "object initializations" include_context 'authorization check'
teams_controller.rb
How to run the test?
rspec spec/controllers/teams_controller_spec.rb
Scenario 1: Create teams with random names
- After checking for the team type and team size, call function to randomize the teams
- Print message "Random teams have been successfully created."
- Redirect to list of teams
describe 'create teams method' do context 'when correct parameters are passed' do it 'creates teams with random names' do allow(Object).to receive_message_chain(:const_get, :find).with(any_args).and_return(assignment1) allow(Version).to receive_message_chain(:where, :last).with(any_args).and_return(0.1) para = {id: assignment1.id, team_size: 2} session = {user: instructor, team_type: "Assignment"} result = get :create_teams, para, session expect(result.status).to eq 302 expect(result).to redirect_to(:action => 'list', :id => assignment1.id) end end end
Scenario 2: List the teams assignment wise or course wise
- Check the team type passed in params to see if it is Assignment or Course type
- Get the teams belonging to that Assignment or Course and list them all
describe 'list method' do before(:each) { allow(Assignment).to receive(:find_by).and_return(assignment1) } context 'when type is Assignment' do it 'lists the teams for that Assignment' do params = {id: assignment1.id, type: 'Assignment'} session = {user: instructor} result = get :list, params, session expect(result.status).to eq 200 expect(controller.instance_variable_get(:@assignment)).to eq assignment1 end end context 'when type is Course' do it 'lists the teams for that Course' do params = {id: course1.id, type: 'Course'} session = {user: instructor} result = get :list, params, session expect(result.status).to eq 200 expect(controller.instance_variable_get(:@assignment)).to eq nil end end context 'when type is not Assignment or Course' do it 'throws error' do params = {id: 52, type: 'Subject'} session = {user: instructor} result = get :list, params, session expect(result.status).to eq 200 expect(controller.instance_variable_get(:@assignment)).to eq nil end end end
Scenario 3: Create a new empty team
- Check if a team already exists with the same name
- If it doesn’t, create a new team with a name
- If a team is created, print "The team <team_name> has been successfully created."
- Redirect to list team page
- If error is there, fail to create a new team and redirect to new team form page
describe 'new method' do it 'creates a new team successfully when all parameters are provided correctly' do allow(Object).to receive_message_chain(:const_get, :find).with(any_args).and_return(assignment1) para = {id: assignment1.id} session = {user: ta, team_type: 'Assignment'} result = get :new, para, session expect(result.status).to eq 200 expect(controller.instance_variable_get(:@parent)).to eq assignment1 end end
Scenario 4: Update an existing team
- Check if a team with new suggested name already exists
- If it doesn’t, update and save the new team name
- Print "The team <new_team_name> has been successfully updated."
- Redirect to list team page
- If error is there, fail to update team and redirect to edit team form page
describe 'update method' do it 'updates the team name' do allow(Team).to receive(:find).and_return(team1) allow(Assignment).to receive(:find).and_return(assignment1) para = { id: team1.id, team: {name: 'rando team'}} session = {user: ta, team_type: 'Assignment'} result = get :update, para, session expect(result.status).to eq 302 expect(result).to redirect_to(:action => 'list', :id => assignment1.id) end # this test will fail even though it should normally pass, that's because it runs into an error at @team.save # RumtimeError: stubbed models are not allowed to access the database - AssignmentTeam#save() end
Scenario 5: Delete a team
- Check if there is a team in waitlist for the topic that the team to be deleted holds
- If there is a team on the waitlist, assign the topic to that team. If multiple teams are there, assign the topic to the first team in the waitlist.
- Delete the team’s records in team, teams_users and sign_up_team tables
- Print “"The team <team_name> has been successfully deleted."
describe 'delete method' do before(:each) { request.env['HTTP_REFERER'] = root_url } context 'when called and team is nil' do it 'simply redirects back to the earlier page' do allow(Team).to receive(:find_by).and_return(nil) para = {id: 5} session = {user: instructor} result = get :delete, para, session expect(result.status).to eq 302 expect(result).to redirect_to :back expect(controller.instance_variable_get(:@team)).to eq nil end end context 'when called and team is not nil and it does not hold a topic' do it 'deletes the team' do allow(Team).to receive(:find_by).and_return(team5) allow(Object).to receive_message_chain(:const_get, :find).and_return(course1) allow(team5).to receive(:destroy).and_return(nil) para = {id: 5} session = {user: instructor, team_type: 'CourseTeam'} result = get :delete, para, session expect(result.status).to eq 302 expect(controller.instance_variable_get(:@team)).to eq team5 end end end
Scenario 6: Copy existing teams from a course down to an assignment
- Find the course that the assignment belongs to
- If a course for the assignment doesn’t exist, give the error message "No course was found for this assignment."
- Otherwise fetch all the teams that exist in the course
- If no teams exist, give the error message "No teams were found when trying to inherit."
- Else copy all teams and assign them the new assignment id
describe 'inherit method' do context 'called when assignment belongs to course and team is not empty' do it 'copies teams from course to the assignment' do allow(Assignment).to receive(:find).and_return(assignment1) allow(Course).to receive(:find).and_return(course1) allow(course1).to receive(:get_teams).and_return([team5, team6]) para = {id: team5.id} session = {user: ta} result = get :inherit, para, session expect(result.status).to eq 302 expect(result).to redirect_to(:controller => 'teams', :action => 'list', :id => assignment1.id) end end context 'called when assignment belongs to course but team is empty' do it 'flashes note' do allow(Assignment).to receive(:find).and_return(assignment1) allow(Course).to receive(:find).and_return(course1) para = {id: team5.id} session = {user: ta} result = get :inherit, para, session expect(result.status).to eq 302 expect(result).to redirect_to(:controller => 'teams', :action => 'list', :id => assignment1.id) end end context 'called when assignment belongs to no course' do let(:fasg) { build_stubbed(:assignment, id: 1074, course_id: -2) } # a temporary assigment object is created with an abnormal course_id so that we can check the fail condition of the method it 'flashes error' do allow(Assignment).to receive(:find).and_return(fasg) allow(Course).to receive(:find).and_return(course1) para = {id: team5.id} session = {user: ta} result = get :inherit, para, session expect(result.status).to eq 302 expect(result).to redirect_to(:controller => 'teams', :action => 'list', :id => fasg.id) end end end
Scenario 7: Copy existing team from assignment to course
- Find the assignment id to which the team belongs
- Find the course to which the assignment belongs
- If assignment doesn’t belong to a course, give the error message "This assignment is not <assignment_name> with a course."
- Otherwise copy team from assignment and assign it the course id
- Print success message "The team <team_name> was successfully copied to <course_name>"
- Redirect to list page
describe 'bequeath method' do context 'called when assignment has a course' do it 'copies the teams from assignment to the course' do allow(AssignmentTeam).to receive(:find).and_return(team2) allow(Assignment).to receive(:find).and_return(assignment1) allow(Course).to receive(:find).and_return(course1) para = {id: team2.id} session = {user: ta} result = get :bequeath, para, session expect(result.status).to eq 302 expect(result).to redirect_to(:controller => 'teams', :action => 'list', :id => assignment1.id) end end context 'called when assignment does not have a course' do let(:fasg) { build_stubbed(:assignment, id: 1074, course_id: -2) } # a temporary assigment object is created with an abnormal course_id so that we can check the fail condition of the method it 'throws an error and fails to copy the teams' do allow(AssignmentTeam).to receive(:find).and_return(team2) allow(Assignment).to receive(:find).and_return(fasg) para = {id: team2.id} session = {user: ta} result = get :bequeath, para, session expect(result.status).to eq 302 expect(result).to redirect_to(:controller => 'teams', :action => 'list', :id => fasg.id) end end end
Scenario 8: Edit method
- Find the team with the 'id' present in params
describe 'edit method' do it 'successfully returns the team with the given team id' do allow(Team).to receive(:find).and_return(team1) para = {id: team1.id} session = {user: ta} result = get :edit, para, session expect(result.status).to eq 200 expect(controller.instance_variable_get(:@team)).to eq team1 end # this method has only 1 line which is just to look up a team with the id present in the params end
Scenario 9: Create an empty team
- Find the parent (Assignment or Course) based on the team type which starts the session
- It checks whether a team with the same exists in that category
- If team exists, it throws TeamExistsError and redirects to 'new' team form page
- If team doesn't exist, it creates a new team
- Successful message is displayed and user is redirected to 'list' teams page
describe 'create method' do context 'when invoked with a team which does not exist' do it 'creates it' do allow(Assignment).to receive(:find).and_return(assignment1) para = { id: assignment1.id, team: {name: 'rando team'}} session = {user: ta, team_type: 'Assignment'} result = get :create, para, session expect(result.status).to eq 302 expect(result).to redirect_to(:action => 'list', :id => assignment1.id) end end end
Test Pass/ Fail
Coverage
teams_users_controller.rb
Code correction in teams_users_controller.rb in list method: Team users list users page was not displaying users as expected and showed error for accessing @team.assignment_id. The error is rectified and corrected.
def list @team = Team.find(params[:id]) @assignment = Assignment.find(@team.parent_id) @teams_users = TeamsUser.page(params[:page]).per_page(10).where(["team_id = ?", params[:id]]) end
The above code is corrected to following:
def list @team = Team.find(params[:id]) @assignment = Assignment.find(@team.parent_id) @teams_users = TeamsUser.page(params[:page]).per_page(10).where(["team_id = ?", params[:id]]) end
How to run the test?
rspec spec/controllers/teams_users_controller_spec.rb
Scenario 1: List users under the team
- When list icon against a course or assignment team is selected
- Render list of users under selected team.
#Test team users list functionality describe '#list' do context 'when list is clicked' do it 'renders list of users under Assignment team teams#users' do allow(Team).to receive(:find).with('1').and_return(team1) allow(Assignment).to receive(:find).with(1).and_return(assignment1) @params = {id:1} session = {user: instructor} get :list, @params, session expect(response).to render_template(:list) end end end
Scenario 2: New user under the course or assignment team
- Sets the instance variable to team object
#Test team users controller new method describe '#new' do it ' sets the instance variable to team object' do allow(Team).to receive(:find).with('1').and_return(team1) params = {id: 1} session = {user: instructor} get :new, params, session expect(controller.instance_variable_get(:@team)).to eq(team1) end end
Scenario 3: Create: Add new user to the selected team.
- Given user is not defined: When given user is defined, link is provided to create the user.
- Selected team to which user is being added belongs to an assignment: When user is not a participant of the assignment, link is provided to add the user to the assignment. When the assignment team already has maximum number of users, "Maximum users reached" notification is flashed.
- Selected team to which user is being added belongs to a course: When user is not a participant of the course, link is provided to add the user to the course. When the course team already has maximum number of users, "Maximum users reached" notification is flashed.
- Response is redirected to 'http://test.host/teams/list?id=1'.
- User that is not defined is added to assignment or course team.
- Page throws 'user not defined' error.
- Response is redirected to teams list page.
#Test adding new user to assignment or course team describe '#create' do context 'when user is added to assignment or course team' do it 'it throws error when user is not defined' do allow(User).to receive(:find_by).with(name: 'instructor6').and_return(nil) allow(Team).to receive(:find).with('1').and_return(team1) session = {user: admin} params = { user: {name: 'instructor6'}, id: 1 } post :create, params, session expect(flash[:error]).to eq "\"instructor6\" is not defined. Please <a href=\"http://test.host/users/new\">create</a> this user before continuing." expect(response).to redirect_to('http://test.host/teams/list?id=1') end end
Create context scenario 2:
- User that is not participant of an assignment team is added to an assignment team.
- Page throws 'user not participant of the current assignment' error.
- Response is redirected to teams list page.
context 'when user is added to assignment team' do it 'it throws error when user added is not a participant of the current assignment' do allow(User).to receive(:find_by).with(name: student1.name).and_return(student1) allow(Team).to receive(:find).with('1').and_return(team1) allow(AssignmentTeam).to receive(:find).with('1').and_return(team1) allow(Assignment).to receive(:find).with(1).and_return(assignment1) allow(AssignmentParticipant).to receive(:find_by).with(user_id: 1, parent_id: 1).and_return(nil) session = {user: admin} params = { user: {name: 'student2065'}, id: 1 } post :create, params, session expect(flash[:error]).to eq "\"student2065\" is not a participant of the current assignment. Please <a href=\"http://test.host/participants/list?authorization=participant&id=1&model=Assignment\">add</a> this user before continuing." expect(response).to redirect_to('http://test.host/teams/list?id=1') end end
Create context scenario 3:
- User is added to an assignment which already has maximum number of participants.
- Page throws 'team already has the maximum number of members' error.
- Response is redirected to teams list page.
context 'when user is added to assignment team' do it 'it throws error when assignmentTeam has maximum number of participants' do allow(User).to receive(:find_by).with(name: student1.name).and_return(student1) allow(Team).to receive(:find).with('1').and_return(team1) allow(AssignmentTeam).to receive(:find).with('1').and_return(team1) allow(Assignment).to receive(:find).with(1).and_return(assignment1) allow(AssignmentParticipant).to receive(:find_by).with(user_id: 1, parent_id: 1).and_return(participant) allow_any_instance_of(Team).to receive(:add_member).with(any_args).and_return(false) session = {user: admin} params = { user: {name: 'student2065'}, id: 1 } post :create, params, session expect(flash[:error]).to eq "This team already has the maximum number of members." expect(response).to redirect_to('http://test.host/teams/list?id=1') end end
Create context scenario 4:
- Valid user that is participant of an assignment team is added to the assignment team with members less than maximum numbers.
- The user gets successfully added to the team.
- Response is redirected to teams list page.
context 'when user is added to assignment team' do it 'new user gets successfully added to the assignment' do allow(User).to receive(:find_by).with(name: student1.name).and_return(student1) allow(Team).to receive(:find).with(any_args).and_return(team1) allow(AssignmentTeam).to receive(:find).with('1').and_return(team1) allow(Assignment).to receive(:find).with(1).and_return(assignment1) allow(AssignmentParticipant).to receive(:find_by).with(user_id: 1, parent_id: 1).and_return(participant) allow_any_instance_of(Team).to receive(:add_member).with(any_args).and_return(true) allow(TeamsUser).to receive(:last).with(any_args).and_return(student1) session = {user: admin} params = { user: {name: 'student2065'}, id: 1 } post :create, params, session expect(response).to redirect_to('http://test.host/teams/list?id=1') end end
Create context scenario 5:
- User that is not participant of a course team is added to the course team.
- Page throws 'user not participant of the current course' error.
- Response is redirected to teams list page.
context 'when user is added to course team' do it 'it throws error when user added to course Team is not defined' do allow(User).to receive(:find_by).with(name: student1.name).and_return(student1) allow(Team).to receive(:find).with('5').and_return(team5) allow(CourseTeam).to receive(:find).with('5').and_return(team5) allow(Course).to receive(:find).with(1).and_return(course1) allow(CourseParticipant).to receive(:find_by).with(user_id: 1, parent_id: 1).and_return(nil) session = {user: admin} params = { user: {name: 'student2065'}, id: 5 } post :create, params, session expect(flash[:error]).to eq "\"student2065\" is not a participant of the current course. Please <a href=\"http://test.host/participants/list?authorization=participant&id=1&model=Course\">add</a> this user before continuing." expect(response).to redirect_to('http://test.host/teams/list?id=1') end end
Create context scenario 6:
- User is added to course which already has maximum number of participants.
- Page throws 'team already has the maximum number of members' error.
- Response is redirected to teams list page.
context 'when user is added to course team' do it 'it throws error when courseTeam has maximum number of participants' do allow(User).to receive(:find_by).with(name: student1.name).and_return(student1) allow(Team).to receive(:find).with('5').and_return(team5) allow(CourseTeam).to receive(:find).with('5').and_return(team5) allow(Course).to receive(:find).with(1).and_return(course1) allow(CourseParticipant).to receive(:find_by).with(user_id: 1, parent_id: 1).and_return(participant) allow_any_instance_of(CourseTeam).to receive(:add_member).with(any_args).and_return(false) session = {user: admin} params = { user: {name: 'student2065'}, id: 5 } post :create, params, session expect(flash[:error]).to eq "This team already has the maximum number of members." expect(response).to redirect_to('http://test.host/teams/list?id=1') end end
Create context scenario 7:
- Valid user that is participant of a course team is added to the course team with members less than the maximum numbers.
- The user gets successfully added to the team.
- Response is redirected to teams list page.
context 'when user is added to course team' do it 'new user gets successfully added to course' do allow(User).to receive(:find_by).with(name: student1.name).and_return(student1) allow(Team).to receive(:find).with('5').and_return(team5) allow(CourseTeam).to receive(:find).with('5').and_return(team5) allow(TeamsUser).to receive(:create).with(user_id: 1, team_id: 5).and_return(double('TeamsUser', id: 1)) allow(TeamNode).to receive(:find_by).with(node_object_id: 5).and_return(double('TeamNode', id: 1)) allow(TeamUserNode).to receive(:create).with(parent_id: 1, node_object_id: 1).and_return(double('TeamUserNode', id: 1)) allow(Course).to receive(:find).with(1).and_return(course1) allow(CourseParticipant).to receive(:find_by).with(user_id: 1, parent_id: 1).and_return(participant) allow_any_instance_of(CourseTeam).to receive(:add_member).with(any_args).and_return(true) session = {user: admin} params = { user: {name: 'student2065'}, id: 5 } post :create, params, session expect(response).to redirect_to('http://test.host/teams/list?id=1') end end end
Scenario 4: Delete user from the selected team.
- User under assignment or course team is deleted: user association to the respective team is deleted and hence user is no longer part of the team.
#Test delete user from team describe '#delete' do context 'when user is deleted' do it 'it deletes the user and redirects to Teams#list page' do allow(TeamsUser).to receive(:find).with("1").and_return(teamUser) allow(Team).to receive(:find).with(teamUser.team_id).and_return(team1) allow(User).to receive(:find).with(teamUser.user_id).and_return(student1) @params = {id:1} session = {user: instructor} post :delete, @params, session expect(response).to redirect_to('http://test.host/teams/list?id=1') end end end
Scenario 5: Delete selected users from the selected team.
- Selected users under assignment or course team is deleted: for each user in the selected users, association to the respective team is deleted and hence user is no longer part of the team.
- Response is redirected to 'http://test.host/teams/list'.
#Test delete selected users from team describe '#delete_selected' do context 'when selected users are deleted' do it 'it deletes the selected users and redirects to Teams#list page' do allow(TeamsUser).to receive(:find).with("1").and_return([teamUser]) allow(TeamsUser).to receive(:find).with("2").and_return([teamUser2]) @params = {item:[1,2]} session = {user: instructor} post :delete_selected, @params, session expect(response).to redirect_to('http://test.host/teams_users/list') end end end
Test Pass/ Fail
Coverage
student_teams_controller.rb
The student teams controller is used to create teams, remove participants from teams and update team name. The following test cases are written to test the student_teams_controller.rb.
How to run the test?
rspec spec/controllers/student_teams_controller_spec.rb
Scenario 1: Set the variables for view
- If the current user is student and their User Ids match, then the following values are set: @send_invs, @received_invs, @current_due_date, @users_on_waiting_list, @teammate_review_allowed
- If the current user is not student or the User Ids do not match, then the return from method.
describe '#view' do it 'sets the student' do allow(AssignmentParticipant).to receive(:find).with('12345').and_return student allow(student_teams_controller).to receive(:current_user_id?) allow(student_teams_controller).to receive(:params).and_return(student_id: '12345') allow(student).to receive(:user_id) student_teams_controller.view end end
Scenario 2: Create Student teams
- If team name is empty, flash an error message saying "Team name missing while creating team" and redirect to view_student_teams_path
- If team name is not empty and team name already in use, "Team name being created was already in use" and redirect to view_student_teams_path
- If team name is not empty and team name not in use, save team data, add logged in student to team and redirect to view_student_teams_path.
describe 'POST #create' do #before(:each) do # @student = AssignmentParticipant.new #end # When assignment team is empty it flashes a notice context 'when create Assignment team' do it 'flash notice when team is empty' do allow(AssignmentTeam).to receive(:where).with(name: , parent_id: 1).and_return([]) allow(AssignmentParticipant).to receive(:find).with('1').and_return(student1) allow(AuthorizationHelper).to receive(:current_user_has_id).with(any_args).and_return(true) allow(student1).to receive(:user_id).with(any_args).and_return(1) session = {user:student1} params = { student_id:1, team:{ name: }, action: 'create' } result= post :create, params, session expect(result.status).to eq 302 end end #when all the team name is set correctly, create team context "create team" do it "saves the team when all the team name is set correctly" do allow(AssignmentNode).to receive(:find_by).with(node_object_id: 1).and_return(node1) allow(AssignmentTeam).to receive(:new).with(name: 'test', parent_id: 1).and_return(team7) allow(AssignmentParticipant).to receive(:find).with('1').and_return(student1) allow(AuthorizationHelper).to receive(:current_user_has_id).with(any_args).and_return(true) allow(User).to receive(:find).with(1).and_return(team_user1) allow_any_instance_of(Team).to receive(:add_member).with(any_args).and_return(true) allow(student1).to receive(:user_id).with(any_args).and_return(1) allow(team7).to receive(:save).and_return(true) session = {user:student1} params = { student_id:1, team:{ name:'test' }, action: 'create' } result= post :create, params, session expect(result.status).to eq(302) end end #when the team name is already in use, it flashes message context "name already in use" do it "flash notice when the team name is already in use" do allow(AssignmentTeam).to receive(:where).with(name: 'test', parent_id: 1).and_return(team7) allow(AssignmentParticipant).to receive(:find).with('1').and_return(student1) allow(AuthorizationHelper).to receive(:current_user_has_id).with(any_args).and_return(true) allow(student1).to receive(:user_id).with(any_args).and_return(1) allow(team7).to receive(:empty?).and_return(false) session = {user:student1} params = { student_id:1, team:{ name:'test' }, action: 'create' } result= post :create, params, session expect(result.status).to eq 302 end end end
Scenario 3: Update team name:
- Find the team that should be updated.
- If there are no matching teams, call team_created_successfully and redirect to view_student_teams_path
- If there is exactly one match, then call team_created_successfully and redirect to view_student_teams_path
- If there are more than one team, then show the following error message "Team name being updated to was already in use" and redirect to edit_student_teams_path.
describe '#update' do #When the name is not already present in the database, it updates the name context 'update team name when matching name not found' do it 'update name when the name is not already present in the database' do allow(AssignmentTeam).to receive(:where).with(name: 'test', parent_id: 1).and_return([]) allow(Team).to receive(:find).with("1").and_return(team7) allow(AssignmentParticipant).to receive(:find).with('1').and_return(student1) allow(AuthorizationHelper).to receive(:current_user_has_id).with(any_args).and_return(true) allow(student1).to receive(:user_id).with(any_args).and_return(1) allow(team7).to receive(:user_id).with(any_args).and_return(1) allow(team7).to receive(:update_attribute).and_return(true) session = {user:student1} params = { student_id:1, team_id:1, team:{ name:'test' }, action: 'update' } result= post :update, params, session expect(result.status).to eq(302) end end #When no team has name and only one matching team is found,update the name context 'update name when name is found' do it 'update name when no team has name and only one matching team is found' do allow(AssignmentTeam).to receive(:where).with(name: 'test', parent_id: 1).and_return(team1) allow(Team).to receive(:find).with("1").and_return(team8) allow(AssignmentParticipant).to receive(:find).with('1').and_return(student1) allow(AuthorizationHelper).to receive(:current_user_has_id).with(any_args).and_return(true) allow(student1).to receive(:user_id).with(any_args).and_return(1) allow(team8).to receive(:user_id).with(any_args).and_return(1) allow(team8).to receive(:update_attribute).and_return(true) allow(team1).to receive(:length).and_return(1) allow(team1).to receive(:name).and_return("test") allow(team8).to receive(:name).and_return("test") session = {user:student1} params = { student_id:1, team_id:1, team:{ name:'test' }, action: 'update' } result= post :update, params, session expect(result.status).to eq(302) end end #when the team name is already in use, then flash the error message context 'name is already in use' do it 'when the team name is already in use flash notice' do allow(AssignmentTeam).to receive(:where).with(name: 'test', parent_id: 1).and_return(team1) allow(Team).to receive(:find).with("1").and_return(team8) allow(AssignmentParticipant).to receive(:find).with('1').and_return(student1) allow(AuthorizationHelper).to receive(:current_user_has_id).with(any_args).and_return(true) allow(student1).to receive(:user_id).with(any_args).and_return(1) allow(team8).to receive(:user_id).with(any_args).and_return(1) allow(team1).to receive(:length).and_return(2) session = {user:student1} params = { student_id:1, team_id:1, team:{ name:'test' }, action: 'update' } result= post :update, params, session expect(result.status).to eq(302) end end end
Scenario 4: Remove team participants
- Find the user who has to be removed.
- Remove the user from team.
- If the team does not have any more participants, remove the team record from database.
- If the assignment has sign up sheet, then add the topic back to topics pool or assign the topic to a new team from waitlist
- Remove all the invitations sent and redirect to view_student_teams_path.
describe '#remove_participant' do #remove participant from team and remove team if he was the only particilant context 'remove team user' do it 'remove user' do allow(AssignmentParticipant).to receive(:find).and_return(participant) allow(TeamsUser).to receive(:where).and_return(team_user1) allow(team_user1).to receive(:destroy_all) allow(team_user1).to receive_message_chain(:where,:empty?).and_return(false) allow_any_instance_of(AssignmentParticipant).to receive(:save).and_return(false) session = {user:student1} params = { team_id:1, user_id:1, student_id:1, team:{ name:'test' } } result = post :remove_participant, params, session expect(result.status).to eq 302 # expect(result).to redirect_to(view_student_teams_path(:student_id => 1)) end end end
Test Pass/ Fail
Coverage
join_team_requests_controller.rb
P = Pending status, D = Denied status, A = Accepted status. To test the controller, run the line:
rspec spec/controllers/join_team_request_controller_spec.rb
Scenario 1: Creating a team request
- If the team id is verified along with user id and assignment id, create a new request and change @join_team_request = 'P' .
- If error occurs, flash error message.
describe "POST #create" do before(:each) do # Stubbing participant to receive an object with id = 1 allow(Participant).to receive(:find).with("1").and_return(participant) end context "when resource is not saved!" do it "renders new page" do allow(JoinTeamRequest).to receive(:new).and_return(invalidrequest) params = {participant_id: participant.id, team_id: -2} session = {user: student1} get :new, params, session expect(response).to render_template("new") end end # Testing when the object is being saved to the database context "when resource is saved" do before(:each) do allow(JoinTeamRequest).to receive(:new).and_return(join_team_request2) allow(Team).to receive(:find).with("1").and_return(team1) allow(Assignment).to receive(:find).with(1).and_return(assignment1) allow(Participant).to receive(:where).with(user_id: 1,parent_id: '1').and_return([participant]) allow(join_team_request2).to receive(:save).and_return(true) end it "valid response" do allow(join_team_request2).to receive(:save).and_return(true) params = { id: 2, join_team_request2: { status: 'P' }, team_id: 1, assignment_id: 1 } session = {user: student1} post :create, params, session expect(response.status).to eq 302 expect(join_team_request2.status).to eq('P') end end context "when it is not created" do it "will page for new " do allow(join_team_request2).to receive(:save).and_return(false) params = {action: 'new'} session = {user: student1} get :new, params, session expect(response.status).to eq 200 end end end
Scenario 2: Decline a team request.
- After verifying team_user_id, change @join_team_request.status = 'D' .
- Redirect to view_student_teams_path
describe "#decline" do context "when join team request is declined" do before(:each) do allow(JoinTeamRequest).to receive(:find).and_return(join_team_request2) allow(join_team_request2).to receive(:save).and_return(true) end it "will change status to 'D'" do params = {action: 'decline'} session = {user: ta} result = get :decline, params, session expect(result.status).to eq 302 end it "will redirect to view student teams path" do params = {action: 'decline'} session = {user: ta} result = get :decline, params, session expect(result).to redirect_to(view_student_teams_path) end end end
Scenario 3: Check team status.
- Since this method is private there is no test case written for it.
- If team if full. Print error message "This team is full." .
- If team is not empty, print message "You are already a member of this team."
Test Pass/ Fail
All tests, except 1 pass. The test that fails is for the "get index" method. We have identified that there is no route the view/index is going to.
def respond_after(request) respond_to do |format| format.html format.xml { render xml: request } end end
Coverage
advertise_partner_controller.rb
The controller is used to create, update and remove advertisements for partner. The following test cases are written to test the functionality of advertise_partner_controller.rb.
How to run the test?
rspec spec/controllers/advertise_partner_controller_spec.rb
Scenario 1: Creating new advertisement for partners.
- We set the advertise_for_partner : True, comments_for_advertisement[param] when the user wants to set a new advertisement for partners in AssignmentTeam mode.
#create advertisement by passing team and participant details describe "POST #create" do context "when advertisement request is valid" do it "will create an advertisement" do allow(AssignmentTeam).to receive(:find_by).and_return(team1) allow(AssignmentParticipant).to receive(:exists?).and_return(true) allow(team1).to receive(:assignment).and_return(assignment1) allow(team1).to receive(:update_attributes).and_return(true) allow(AssignmentParticipant).to receive(:find_by).and_return(participant) params = { id: team1.id, team_id: team1.id, } session = {user: ta} result = get :create, params, session expect(result.status).to eq 302 expect(result).to redirect_to(view_student_teams_path(:student_id => 1)) end end end
Scenario 2: Updating the advertisement.
- We set the comments_for_advertisement[param] when the user wants to set a new advertisement for partners in AssignmentTeam model.
- Update Unsuccessful: If there is an error during update then the following error message is thrown "An error occurred, and your advertisement was not updated." and edit page is rendered.
- Update Successful: If the advertisement is successfully updated in the database, then the "Your advertisement was successfully updated!" message is prompted and the user is redirected to the view_student_teams_path.
# Update advertisement by passing team and paticipant details describe "POST #update" do context "when advertisement is updated" do it "the advertisement is updated" do allow(AssignmentTeam).to receive(:find_by).and_return(team1) allow(AssignmentParticipant).to receive(:exists?).and_return(true) allow(team1).to receive(:assignment).and_return(assignment1) allow(team1).to receive(:update_attributes).and_return(true) allow(AssignmentParticipant).to receive(:find_by).and_return(participant) params = { id: team1.id, team_id: team1.id, } session = {user: ta} result = get :update, params, session expect(result.status).to eq 302 expect(result).to redirect_to(view_student_teams_path(:student_id => 1)) end it "the advertisement is not updated due to error" do allow(AssignmentTeam).to receive(:find_by).and_return(team1) allow(AssignmentParticipant).to receive(:exists?).and_return(true) allow(team1).to receive(:assignment).and_return(assignment1) allow(AssignmentParticipant).to receive(:find_by).and_return(participant) allow(team1).to receive(:update_attributes).and_raise(StandardError) params = { id: team1.id, team_id: team1.id, } session = {user: ta} result = get :update, params, session expect(flash[:error]).to eq "An error occurred and your advertisement was not updated!" expect(result.status).to eq 200 end end end
Scenario 3: Remove the advertisement.
- We set the advertise_for_partner : False , comments_for_advertisement : nil when the user wants to set a new advertisement for partners in AssignmentTeam model.
- Remove Unsuccessful : If there is an error during removing the advertisement then the following error message is thrown "An error occurred and your advertisement was not removed." and the previous page is rendered.
- Remove Successful : If the advertisement is successfully removed in the database then the "Your advertisement was successfully removed!" message is prompted and the user is redirected to the view_student_teams_path.
describe "POST #remove" do context "when advertisement is removed" do it "the advertisement is removed" do allow(AssignmentTeam).to receive(:find_by).and_return(team1) allow(AssignmentParticipant).to receive(:exists?).and_return(true) allow(team1).to receive(:assignment).and_return(assignment1) allow(team1).to receive(:update_attributes).and_return(true) allow(AssignmentParticipant).to receive(:find_by).and_return(participant) params = { id: team1.id, team_id: team1.id, } session = {user: ta} result = get :remove, params, session expect(result.status).to eq 302 expect(result).to redirect_to(view_student_teams_path(:student_id => 1)) end it "the advertisement is not removed due to error" do allow(AssignmentTeam).to receive(:find_by).and_return(team1) allow(AssignmentParticipant).to receive(:exists?).and_return(true) allow(team1).to receive(:assignment).and_return(assignment1) allow(AssignmentParticipant).to receive(:find_by).and_return(participant) allow(team1).to receive(:update_attributes).and_raise(StandardError) params = { id: team1.id, team_id: team1.id, } session = {user: ta} result = get :remove, params, session expect(flash[:error]).to eq "An error occurred and your advertisement was not removed!" expect(result).to redirect_to(request.env['HTTP_REFERER'] ? :back : (:root)) end end end
Test Pass/Fail
Coverage
Github Issues
We have created github issue for each non working test.
Link to the issues:
https://github.com/expertiza/expertiza/issues/2170
https://github.com/expertiza/expertiza/issues/2168
https://github.com/expertiza/expertiza/issues/2167
Old Page Link
We have created a new page due to a title error at the new one. Link to the old page: https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2021_-_E2126._Testing_-_Team_Related_Files#Description_about_project
Github Coverage
Our Team
Yi Qiu (mentor)
Aaron Mathew (asmathew@ncsu.edu)
Priya Jakhar (pjakhar@ncsu.edu)
Supriya Krishna (sbkrishn@ncsu.edu)
Snehapriyaa Mathiyalaghan (smathiy@ncsu.edu)