CSC/ECE 517 Spring 2022 - E2203: Testing for submission records controller, profile controller

From Expertiza_Wiki
Jump to navigation Jump to search

About Expertiza

Expertiza is an open source Ruby on Rails framework which can be used by instructors and students. It can be used for submissions and for peer reviews by students. Students can form teams and work with other people on the assignments. It can be used to create assignments and topics by the instructor. Students can form teams to work on various projects and assignments.

Description about project

This Expertiza OSS project E2208 is adding unit tests for submission_records_controller.rb, profile_controller.rb

Files Involved

submission_records_controller.rb, submission_records_controller_spec.rb, profile_controller.rb, profile_controller_spec.rb

Running Tests

Run the redis server and then use the commands below to run test cases for each of the controllers:

 rspec ./spec/controllers/submission_records_controller_spec.rb 
 rspec ./spec/controllers/profile_controller_spec.rb 

Test Plan

We started by setting up the Expertiza development environment and running the limited test cases already available for profile_controller. We wrote test cases to cover all the required methods under submission_records_controller and profile_controller.

Submission Records Controller Methods

The code of the controller can be found [href=https://github.com/rachanasrib/expertiza/blob/controller-testcases/app/controllers/submission_records_controller.rb here]. The methods are:

  • action_allowed?
  • index

Profile Controller Methods

The code of the controller can be found here. The methods are:

  • action_allowed?
  • edit
  • update
  • user_params (But this is a private method. And private methods are not tested directly. They are considered an implementation detail.)

Test Frame for submission records controller

In the case of controllers, unit testing is about testing the functional logic. 1. index - This action fetches all the submission records of a particular team id coming in the request.

Code snippet:

describe '#index' do
    it 'call index method' do
      params = { team_id: 27158 }
      allow(AssignmentTeam).to receive(:find).with(any_args).and_return(team)
      allow(Assignment).to receive(:find).with(any_args).and_return(assignment)
      allow(SubmissionRecord).to receive(:where).with(any_args).and_return([submission_record])
      result = get :index, params
      expect(result.status).to eq 302
    end
end

2. action_allowed? - This action check is invoked before any of the actions in the submission records controller. It checks whether to allow/ refuse the action for the current user. Action is allowed for the current user if the user is admin/ instructor who instructs the current assignment/ TA of the course which current assignment belongs to.

Code snippet:

describe '#action_allowed?' do
    before(:each) do
      controller.params = { team_id: '27158' }
      allow(AssignmentTeam).to receive(:find).with('27158').and_return(team)
      allow(Assignment).to receive(:find).with(team.parent_id).and_return(assignment)
    end

    context 'when superadmin is logged in' do
      it 'allows certain action' do
        stub_current_user(super_admin, super_admin.role.name, super_admin.role)
        expect(controller.send(:action_allowed?)).to be_truthy
      end
    end

    context 'when current user is instructor who instructs the current assignment' do
      it 'allows certain action' do
        stub_current_user(instructor1, instructor1.role.name, instructor1.role)
        expect(controller.send(:action_allowed?)).to be_truthy
      end
    end

    context 'when current user is instructor but NOT the instructor who instructs the current assignment' do
      it 'refuses certain action' do
        stub_current_user(instructor2, instructor2.role.name, instructor2.role)
        expect(controller.send(:action_allowed?)).to be_falsey
      end
    end

    context 'when current user is TA of the course which current assignment belongs to' do
      it 'allows certain action' do
        stub_current_user(ta, ta.role.name, ta.role)
        allow(TaMapping).to receive(:exists?).with(ta_id: 8, course_id: 1).and_return(true)
        expect(controller.send(:action_allowed?)).to be true
      end
    end

    context 'when current user is a TA but NOT the TA of course which current assignment belongs to' do
      it 'refuses certain action' do
        stub_current_user(ta, ta.role.name, ta.role)
        allow(TaMapping).to receive(:exists?).with(ta_id: 8, course_id: 1).and_return(false )
        expect(controller.send(:action_allowed?)).to be false
      end
    end

    context 'when current user is a student' do
      it 'refuses certain action' do
        stub_current_user(student, student.role.name, student.role)
        expect(controller.send(:action_allowed?)).to be false
      end
    end
end

= Test Frame for profile controller

1. action_allowed? - It checks if a user is logged in or not.

Code snippet:

describe '#action_allowed?' do
    context 'when someone is logged in' do
      it 'allows certain action' do
        stub_current_user(instructor1, instructor1.role.name, instructor1.role)
        expect(controller.send(:action_allowed?)).to be_truthy
      end
    end

    context 'when no one is logged in' do
      it 'refuses certain action' do
        expect(controller.send(:action_allowed?)).to be_falsey
      end
    end
end

2. edit - This action is called in the process of editing a profile. It renders the corresponding edit view.

Code snippet:

describe '#edit' do
    it 'renders edit page' do
      stub_current_user(instructor1, instructor1.role.name, instructor1.role)
      allow(AssignmentQuestionnaire).to receive(:where).with(any_args)
                                                       .and_return([assignment_questionnaire])

      get :edit
      expect(response).to render_template(:edit)
    end
end

3. update - This action is called in the process of updating a profile. A success or error message is flashed depending on the case that a profile is successfully updated or not. And finally there is a redirect to the edit page.

Code snippet:

describe '#update' do
    context 'when profile is saved successfully' do
      it 'shows a success flash message and redirects to profile#edit page' do
        stub_current_user(instructor1, instructor1.role.name, instructor1.role)
        allow(instructor1).to receive(:update_attributes).with(any_args).and_return(true)
        allow(instructor1).to receive(:save!).and_return(true)
        params = {
          id: 1,
          no_show_action: 'not_show_actions'
        }
        post :update, params
        expect(flash[:success]).to eq('Your profile was successfully updated.')
        expect(response).to redirect_to('/profile/1/edit')
      end
    end

    context 'when profile is saved successfully and assignment_questionnaire is not nil' do
      it 'shows a success flash message and redirects to profile#edit page' do
        stub_current_user(instructor1, instructor1.role.name, instructor1.role)
        allow(instructor1).to receive(:update_attributes).with(any_args).and_return(true)
        allow(instructor1).to receive(:save!).and_return(true)
        allow(AssignmentQuestionnaire).to receive(:where).with(any_args).and_return([assignment_questionnaire])

        params = {
          id: 1,
          no_show_action: 'not_show_actions',
          assignment_questionnaire: { 'assignment_id' => '1', 'questionnaire_id' => '666', 'dropdown' => 'true',
                                      'questionnaire_weight' => '0', 'notification_limit' => '15', 'used_in_round' => '1' }
        }
        post :update, params
        expect(flash[:success]).to eq('Your profile was successfully updated.')
        expect(response).to redirect_to('/profile/1/edit')
      end
    end

    context 'when profile is not saved successfully' do
      it 'displays an error flash message and redirects to profile#edit page' do
        stub_current_user(instructor1, instructor1.role.name, instructor1.role)
        allow(instructor1).to receive(:update_attributes).with(any_args).and_return(false)
        params = {
          id: 1
        }
        post :update, params
        expect(flash[:error]).to eq('An error occurred and your profile could not updated.')
        expect(response).to redirect_to('/profile/1/edit')
      end
    end

end

Results

We covered 2 methods under submission records controller and 3 methods under profile controller, we covered all edge cases under these methods. The coverage for submission records controller is 91.67% and the coverage for profile controller is 95.83%

Related Links

A video of all tests running can be seen here

The main repository can be found here

The forked git repository for this project can be found here

The pull request can be found here