CSC/ECE 517 Spring 2022 - E2204: Adding tests for markup styles controller, lock controller
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