CSC/ECE 517 Fall 2016 E1669 Test Various Kinds Of Response Map Hierarchies

From Expertiza_Wiki
Jump to navigation Jump to search

Template:Dashboard.wikiedu.org sandbox

CSC/ECE 517 Fall 2016/oss E1669

Introduction

Expertiza is a web based application which can be used by instructors to assign tasks to students. Expertiza also allows students to form teams among each other, perform peer reviews on assignments and projects. It gives flexibility to instructor to allow students to see other student's work with intended limitations and impose required restrictions on student access. Expertiza has been developed as an Open Source Software (OSS) on Ruby on Rails framework.

Motivation

Expertiza open source development program has fetched many contributions from faculties and students of different universities and thus, it incorporates a wide variety of Ruby coding styles, and this has been a reason why Expertiza project is kept as CSC/ECE 517 OSS project. The students have been given guidelines on Ruby coding styles and many problem statement includes tasks like refactoring and writing tests which can improve uniformity in coding style. The opportunity to work on an OSS project like Expertiza is also expected to provide student an introductory experience of understanding larger programs and making required contributions to them. The writing assignment along with programming assignment is expected to provide project documentation experience to students.

Description of Project

The project numbered E1669 and titled 'Test various kinds of response map hierarchies' is intended to make contributors or students understand the working of response-map. Response-maps are implemented as classes in models as a convention in MVC architecture of Rails framework and they serve the purpose of mapping reviews among reviewers who is reviewing an assignment or project and reviewee whose work is being reviewed. The work which is being reviewed can be submission of an assignment, feedback to a submission, response to a feedback and whatever form which requires one participant to review a work of another participant. The response-maps exploits a number of relations which includes relations among assignments, quizzes, teammates who are participants and can be reviewer and reviewee at different times. The major key of differentiation among reviewer and reviewee as participants id is assigned to reviewer and reviewee. The code works perfectly fine but lacks unit tests for its methods.

Project Implementation

The project requires contributors to write specification based unit tests. There are more than one ways to write unit tests in Ruby on Rails which includes writing test methods under test directory which requires writing fixtures and makes use of 'test_helper'. It is Rails' default way to prepare and use test data. This type of approach is not recommended for programs like Expertiza because of tedious maintenance of complex records and excessive dependencies of classes among each other. The work around is creating factories which creates data for tests whenever it is needed to create.

Factories

Factories generate data which is used to test the functionality of code. The code is typically either a model or controller. Factory Girl for rails is a gem for creating factories and it is also supported by open source development. For this project, factories were created using Factory Girl. One of the examples of factory girl being used in the project is shown in the following piece of code.

 FactoryGirl.define do
   factory :response_take, class: Response do
     review_response_map { ReviewResponseMap.first || association(:review_response_map) }
     response_map { ResponseMap.first || association(:response_map) }
     additional_comment nil
     version_num nil
     round nil
     is_submitted true
   end
 end

The above factory is a contribution through the project. The factories create the instances for testing whenever required with the flag which indicates that the response is submitted.

Specifications

Writing specifications is a way of behavior driven development approach to program which means that the specifications describes the behavior of the code. The specifications acts as tests and there are a number of tools, such as TestUnit and RSpec with cucumber, present to support this approach of development. For this project, RSpec was used and a part of reason for using RSpec is that it is included in the CSC/ECE517 coursework.

Contribution

Apart from the examples given above, a number of test cases were written as unit tests for classes which inherits from ResponseMap class, namely ReviewResponseMap, TeammateReviewResponseMap, FeedbackResponseMap, QuizResponseMap, BookmarkRatingResponseMap, MetareviewResponseMap and  SelfReviewResponseMap. Though all the methods were not tested in the test cases but the basic methods like object creation, object id and their respective titles were tested to be as assigned in the instance. Example of test cases implemented for basic methods are shown below.

require 'rails_helper'
 describe 'ReviewResponseMap' do
  before(:each) do
   @participant=create(:participant)
   @assignment_questionnaire= create(:assignment_questionnaire)
   @review_response=create(:review_response_map)
 end
 describe "#new" do
   it "Validate response instance creation with valid parameters" do
     expect(@review_response.class).to be(ReviewResponseMap)
   end
   it "Validate response instance creation with valid parameters" do
     response=create(:response_take)
     expect(response.class).to be(Response)
   end
   it "Validate response instance creation with valid parameters" do
     expect(@participant.class).to be(Participant)
   end
 end
 describe "id" do
   #test all the id are stored correctly
 let(:reviewresponsemap) {ReviewResponseMap.new id: 66, reviewee_id: 1, reviewed_object_id: 8}
 let(:response) {Response.new id: 4, map_id: 4}
 let(:participant) {Participant.new id: 1}
   it "should be our exact reviewer's id" do
     reviewresponsemap = build(:review_response_map)
     expect(reviewresponsemap.reviewer_id).to eq(1)
   end
   it "should be our exact reviewee's id" do
     reviewresponsemap = build(:review_response_map)
     expect(reviewresponsemap.reviewee_id).to eq(1)
   end
   it "should be the response map_id" do
     expect(response.map_id).to eq(4)
   end
 end
end

The first line of above code block is specifying the 'rails_helper' which is needed to write the specifications here. The test has been written for ReviewResponseMap class and 'reviewresponsemap', 'response' and 'participant' are instances of ReviewResponseMap, Response and Participant. The 'new' specification test block is just making sure that the created instances are of respective class types and is not a much required test. Similarly, 'id' and 'title' attribute can be verified if the correct values of 'id' and 'title' have been stored. The above code block doesn't exactly show the actual changes made in the code block to keep the explanation to the point, the actual changes can be found on the submitted git push request.

Apart from basic methods, some important methods were tested for classes which inherits more from ResponseMap as compared to other classes, example being ReviewResponseMap, FeedbackResponseMap and QuizResponseMap classes. Some examples are given below as pieces of code.

 describe "#final_versions_from_reviewer method" do
     it "should return final version of review when assignment has non varying rubric" do
       create(:response_take)
       map=ReviewResponseMap.final_versions_from_reviewer(1)
       expect(map[:review][:questionnaire_id]).to be(1)
       expect(map[:review][:response_ids][0]).to be(1)
     end
   .
   .
   .
 describe "#import" do
   it "raise error when not enough items" do
     row = []
     expect {ReviewResponseMap.import(row,nil,nil)}.to raise_error("Not enough items.")
   end
   it "raise error when assignment is nil" do
     assignment = build(:assignment)
     allow(Assignment).to receive(:find).and_return(nil)
     row = ["user_name","reviewer_name", "reviewee_name"]
     expect {ReviewResponseMap.import(row,nil,2)}.to raise_error("The assignment with id \"2\" was not found. <a href='/assignment/new'>Create</a> this assignment?")
   end
 end

The above method is part of ReviewResponseMap and thus by Rails convention, the files containing above code is review_response_map_spec.rb. Similarly, for QuizResponseMap class, the sample of test is as below.

 describe '#get_mappings_for_reviewer' do
   it "gives out the relation of reviewer and participant" do
     expect(QuizResponseMap.get_mappings_for_reviewer(participant.id).class).to eq(QuizResponseMap::ActiveRecord_Relation)
   end
 end
 describe '#quiz_score' do
   it "gives out the relation of reviewer and participant" do
     expect(quizresponsemap.quiz_score).to eq('N/A')
   end
 end

The above two methods are part of QuizResponseMap and thus by Rails convention, the files containing above code is quiz_response_map_spec.rb.

Outcomes

All the test cases which have been implemented are working without an error, however, the tests hasn't been written for the some of the methods which call functions from inherited and related classes and the method chain calls a number of classes across the project which adds up to the complexity. For example, 'contributor' method from ReviewResponseMap class is a single line function but it calls method from ResponseMap which calls method from RevieResponseMap and then Participant and so on and it creates a complexity of creating instances of all these classes interlinking with each other with correct 'id'. The project is concluded with all the simple test cases and some complex test cases in the classes which are close to the ResponseMap hierarchy.

Running 'rspec'

RSpec can be run on a local setup of Expertiza. The steps to set up Expertiza locally has been documented well on the Github of Expertiza. After setting up expertiza, following RSpec commands can be used to invoke method testing.

rspec spec/models/review_response_map.rb
rspec spec/models/feedback_response_map.rb
rspec spec/models/teammate_review_response_map.rb
rspec spec/models/quiz_review_response_map.rb
rspec spec/models/bookmark_rating_response_map.rb
rspec spec/models/metareview_response_map.rb
rspec spec/models/self_review_response_map.rb

The submission includes a small video showing the test-runs. The following snippet shows the result of running 'rspec spec/models/quiz_review_response_map.rb' on command line where Expertiza has been set up.

Deplyment testing

The project didn't make any changes in the development or production domain and only contributed to the testing domain. Also, RSpec tests are not tested with the running application in production or development, it's a part of testing which can be tested on console. So, no need of deployment was found for this project.

Future Work

All the methods have not been covered which leaves the scope of writing more tests to increase coverage on ResponseMap class and it's child classes. After getting enough coverage on ResponseMap and child classes, the closely related models like Participant and Assignment can be considered for unit testing.

References

  1. Expertiza
  2. Github Expertiza
  3. Local Contribution Github Fork
  4. RSpec