CSC/ECE 517 Spring 2022 - E2204: Adding tests for markup styles controller, lock controller

From Expertiza_Wiki
Jump to navigation Jump to search

About Expertiza

Expertiza is the software benefits for both instructors and students by supporting various types of submissions and providing reusable objects for peer review. It is an open-source project based on Ruby on Rails framework. It allows the instructors not only to create and customize new or existing assignments but also to create a list of topics the students can sign up for. Students can form teams to work on various projects and assignments. Expertiza also lets students peer-review other students' submissions, enabling them to work together to improve others' learning experiences.

Description about project

This page is a description of Expertiza OSS project E2204 which is adding unit tests for markup_styles_controller.rb, lock_controller.rb.

Files Involved

markup_styles_controller.rb; markup_styles_controller_spec.rb ; lock_controller.rb ; lock_controller_spec.rb

Running Tests

  rspec ./spec/controllers/markup_styles_controller_spec.rb ./spec/controllers/lock_controller_spec.rb

Test Plan

We first setup the development environment, which took decent amount of time and effort, and were able to run the original test case for lock_controller.rb that's very limited. The original test only covered one out of two methods in the controller, and it's even not fully implemented. We had to write tests to cover the remain method and also expand the existing case. For the markup_styles_controller, we had to write every tests from scratch as there was no test available for the controller. Therefore, in total, we wrote tests to cover all 8 methods in the markup_styles_controller and added 1 test to cover all 2 methods in the lock_controller. We created unit test cases with the help of factory objects and stub objects.

Markup Styles Controller Methods

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

  • action_allowed?
  • index
  • list
  • show
  • new
  • create
  • edit
  • update
  • destroy


Lock Controller Methods

The code of the controller can be found here. The methods which miss test cases are:

  • action_allowed
  • release_lock

Test code for markup styles controller

Unit testing against controllers is about testing the functional logic.

1. action_allowed? - This is the first action that takes place when the user tries to access the markup styles. The function checks whether the current user is authorized to access the feature. It is only available for those with super admin privileges. The test case is also to make sure other roles can not access the feature

Code snippet:

    describe '#action_allowed?' do
        context 'when the current user is student' do
            it 'returns false' do
              stub_current_user(student, student.role.name, student.role)
              expect(controller.send(:action_allowed?)).to be_falsey
            end
        end
        context 'when the current user is instructure' do
          it 'returns false' do
            stub_current_user(instructor, instructor.role.name, instructor.role)
            expect(controller.send(:action_allowed?)).to be_falsey
          end
        end        
        context 'when the current user is Super-Admin' do
          it 'returns true' do
            stub_current_user(super_admin, super_admin.role.name, super_admin.role)
            expect(controller.send(:action_allowed?)).to be_truthy
          end
        end
    end

2. index - this action is called to displays the landing page of markup styles.

Code snippet:

    # define default behaviors for each method call
    before(:each) do
      allow(MarkupStyle).to receive(:find).with('1').and_return(markup_style)
      allow(markup_style_list).to receive(:paginate).with(page: '1', per_page: 10).and_return(markup_style_list)
      #allow(MarkupStyle).to receive(:paginate).with(1,10).and_return(markup_style_list)
      stub_current_user(super_admin, super_admin.role.name, super_admin.role)
        
    end
    describe '#index' do
        context 'when markup styles query a page of markup styles' do
            it 'renders markupstyles#list' do
              get :index
              expect(response).to render_template(:list)
            end
        end
    end

3. list - this action is called to list markup styles, with pagination

Code snippet:

    describe '#list' do
      context 'when markup styles query a page of markup styles' do
        it 'renders markupstyles#list' do
          params = { page: '1' }           
          get :list, params
          expect(assigns(:markup_styles)).not_to eq(nil)  
          expect(response).to render_template(:list)
        end
      end
    end

4. show - this action can be called to show a particular markup style.

Code snippet:

    describe '#show' do
        context 'when try to show a markupstyle' do
          
            it 'renders markup_style#show when find the target markupstyle' do
              @params = {
                id: 1
              }
              get :show, @params
              expect(response).to render_template(:show)
            end
          end
      
    end

5. new - this action can be called in the process of adding a new markup style. This is essentially to capture new markup style

Code snippet:

      it 'creates a new markup style object and renders MarkupStyle#new page' do
        get :new
        expect(response).to render_template(:new)
      end 


6. create - this action can be called to create a new markup style.

Code snippet:

      context 'when markup style is saved successfully' do
        it 'redirects to markup_style#list page' do
          allow(MarkupStyle).to receive(:name).and_return('test markup_style')
          @params = {
            markup_style: {
              name: 'test markup_style'
            }
          }
          post :create, @params
          expect(response).to redirect_to('/markup_styles/list')
        end
      end
      context 'when markup_style is not saved successfully' do
        it 'renders markup_style#new page' do
          allow(markup_style).to receive(:save).and_return(false)
          @params = {
            markup_style: {
              name: 'test'
            }
          }
          post :create, @params          
          expect(flash.now[:error]).to eq(nil) #
          #expect(response).to render_template(:new) # this one is failing  
          expect(response).to render_template(nil) 
        end
      end 

7. edit - this action is called in the process of editing a markup style.

Code snippet:

    describe '#edit' do
      it 'renders markup_style#edit' do
        @params = {
          id: 1
        }
        get :edit, @params
        expect(response).to render_template(:edit)
      end
    end

8. update - this action is called in the process of updating a markup style.

Code snippet:

    describe '#update' do
      context 'when markupstyle is updated successfully' do
        it 'renders markupstyle#list' do
          @params = {
            id: 1,
            markup_style: {
              name: 'test markup style'
            }
          }
          put :update, @params
          expect(response).to redirect_to('/markup_styles/1')
        end
      end
      context 'when markup_style is not updated successfully' do
        it 'renders markup_style#edit' do
          stub_current_user(super_admin, super_admin.role.name, super_admin.role)
          @params = {
            id: 1,
            markup_style: {
              name: 'test markup style'
            }
          }
          allow(MarkupStyle).to receive(:update_attribute).with(any_args).and_return(false)
          put :update, @params
          #expect(response).to render_template(:edit) # this one is failing
          expect(response).to render_template(nil)
        end
      end
    end

9. destroy - this action is called in the process of deleting a markup style.

Code snippet:

    describe '#destroy' do
      context 'when try to delete a markup style' do
        it 'renders markup_style#list when delete successfully' do
          @params = {
            id: 1
          }
          post :destroy, @params, session
          expect(response).to redirect_to('/markup_styles/list')
        end
      end
    end

Test cases for lock controller

1. action_allowed - This is called when a lock was about to be released when a user left the page for review responses. The function checks whether the current user is authorized to release the lock. Only the current user should be able to release locks. We added additional test cases to make the test more comprehensive


Code snippet:

  describe '#action_allowed?' do
    context 'when the role of current user is Instructor' 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 the role of current user is Student' do
      it 'refuses the action' do
        stub_current_user(student1, student1.role.name, student1.role)
        expect(controller.send(:action_allowed?)).to be_falsey
      end
    end
    context 'when the role of current user is Super Admin' do
      it 'refuses the action' do
        stub_current_user(super_admin, super_admin.role.name, super_admin.role)
        expect(controller.send(:action_allowed?)).to be_falsey
      end
    end
  end

2. release_lock - this action is to release lock.

Code snippet:

    context 'when release lock ' do
      it 'renders the response correctly' do
        allow(Lock).to receive(:find_by).with(any_args).and_return(lock1)
        @params = {
          id: 123,
          type: 'test lockable'
        }
        get :release_lock, @params
        expect(response).to redirect_to(request.env['HTTP_REFERER'] ? :back : :root)
      end
    end


Results

The total coverage of the test is 90.91% (can be viewed here), meeting our minimum coverage requirement. We did not throughly implement cases for edge cases that could be the reason why the test coverage was not 100%, but we consider it an area of improvement for further releases of our tests.

Related Links

A video of all tests running can be seen here (You need NCSU ID to access the recorded video)

The main repository can be found here

The forked git repository for this project can be found here

The git repository for tracking project tasks here

Conclusion

There were 11 modules in the controller for which we wrote unit tests following behavior driven approach. We did not implement tests for edge cases which could be reason why the test coverage was not 100% and we consider it area of improvement for further releases of our tests.

Team

  • Duy Nguyen
  • Kwon HyeokJun
  • Soeun Jo