CSC/ECE 517 Fall 2021 - E2167. Testing - Team Related Files: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
Line 672: Line 672:
       end
       end
     end
     end
     #happy flow to create team
     #when all the team name is set correctly, create team
     context "create team" do
     context "create team" do
       it "saves the 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(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(AssignmentTeam).to receive(:new).with(name: 'test', parent_id: 1).and_return(team7)
Line 697: Line 697:
     #when the team name is already in use, it flashes message
     #when the team name is already in use, it flashes message
     context "name already in use" do
     context "name already in use" do
       it "flash notice" 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(AssignmentTeam).to receive(:where).with(name: 'test', parent_id: 1).and_return(team7)
         allow(AssignmentParticipant).to receive(:find).with('1').and_return(student1)
         allow(AssignmentParticipant).to receive(:find).with('1').and_return(student1)

Revision as of 04:55, 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 many files related to teams that don’t have enough tests: teams_controller, teams_users_controller, student_teams_controller, join_team_requests_controller, and advertise_for_partner_controller. They all need essentially the same kind of fixtures or mocks to enable testing: A team that is created, a couple of students that can be added to the team, an invitation that can be sent from one student to another student to join a particular team

Approach Chosen & Why?

In this project we have first identified all the set of scenarios related to team controllers. Each of the scenarios are identified as mentioned above and has been subdivided into a number of ways in which it can be realized. This will ensure that code is robust to any kind of unexpected changes and that the functionality will not be broken when deployed in production. We have chosen to bring about this robustness of test by writing unit test and functional tests using RSpec and Capybara respectively. Unit Tests will ensure that the particular functionality is being tested in a isolated setup which would even include the edge cases whereas the functional tests will ensure that this teams feature is in resonance with the other features and works coherently.

Implementation

teams_shared.rb

  1. This controller can be found in spec/support
  2. 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)}

action_allowed? method shared example tests

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

  1. After checking for the team type and team size, call function to randomize the teams
  2. Print message "Random teams have been successfully created."
  3. 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

  1. Check the team type passed in params to see if it is Assignment or Course type
  2. 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

  1. Check if a team already exists with the same name
  2. If it doesn’t, create a new team with a name
  3. If a team is created, print "The team <team_name> has been successfully created."
  4. Redirect to list team page
  5. 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

  1. Check if a team with new suggested name already exists
  2. If it doesn’t, update and save the new team name
  3. Print "The team <new_team_name> has been successfully updated."
  4. Redirect to list team page
  5. 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

  1. Check if there is a team in waitlist for the topic that the team to be deleted holds
  2. 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.
  3. Delete the team’s records in team, teams_users and sign_up_team tables
  4. 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

  1. Find the course that the assignment belongs to
  2. If a course for the assignment doesn’t exist, give the error message "No course was found for this assignment."
  3. Otherwise fetch all the teams that exist in the course
  4. If no teams exist, give the error message "No teams were found when trying to inherit."
  5. 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

  1. Find the assignment id to which the team belongs
  2. Find the course to which the assignment belongs
  3. If assignment doesn’t belong to a course, give the error message "This assignment is not <assignment_name> with a course."
  4. Otherwise copy team from assignment and assign it the course id
  5. Print success message "The team <team_name> was successfully copied to <course_name>"
  6. 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

  1. 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

  1. Find the parent (Assignment or Course) based on the team type which starts the session
  2. It checks whether a team with the same exists in that category
  3. If team exists, it throws TeamExistsError and redirects to 'new' team form page
  4. If team doesn't exist, it creates a new team
  5. 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

  1. When list icon against a course or assignment team is selected
  2. 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

  1. 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.

  1. Given user is not defined: When given user is defined, link is provided to create the user.
  2. 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.
  3. 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.
  4. Response is redirected to 'http://test.host/teams/list?id=1'.

#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
   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
   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
   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
   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
   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
   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.

  1. 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.

  1. 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.
  2. 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

Scenario 1: Set the variables for view

  1. 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
  2. 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

  1. If team name is empty, flash an error message saying "Team name missing while creating team" and redirect to view_student_teams_path
  2. 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
  3. 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:

  1. Find the team that should be updated.
  2. If there are no matching teams, call team_created_successfully and redirect to view_student_teams_path
  3. If there is exactly one match, then call team_created_successfully and redirect to view_student_teams_path
  4. 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 it updates the name
   context 'update team name when matching name not found' do
     it 'update name' 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' 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 '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

  1. Find the user who has to be removed.
  2. Remove the user from team.
  3. If the team does not have any more participants, remove the team record from database.
  4. 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
  5. 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

  1. If the team id is verified along with user id and assignment id, create a new request and change @join_team_request = 'P' .
  2. 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.

  1. After verifying team_user_id, change @join_team_request.status = 'D' .
  2. 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.

  1. Since this method is private there is no test case written for it.
  2. If team if full. Print error message "This team is full." .
  3. 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


Scenario 1: Creating new advertisement for partners.

  1. 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.
 describe "POST #create" do
   context "when it 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.

  1. We set the comments_for_advertisement[param] when the user wants to set a new advertisement for partners in AssignmentTeam model.
  2. 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.
  3. 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.
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.

  1. 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.
  2. 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.
  3. 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


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)