CSC/ECE 517 Fall 2016 E1669 Test Various Kinds Of Response Map Hierarchies: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
 
(20 intermediate revisions by 2 users not shown)
Line 10: Line 10:


== Description of Project ==
== 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 is id assigned to reviewer and reviewee. The code works perfectly fine but lacks unit tests for its methods.  
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 ==
== Project Implementation ==
Line 18: Line 18:
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.
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
FactoryGirl.define do
    factory :response_take, class: Response do
  factory :response, class: Response do
      review_response_map { ReviewResponseMap.first || association(:review_response_map) }
    review_response_map { ReviewResponseMap.first || association(:review_response_map) }
      response_map { ResponseMap.first || association(:response_map) }
    response_map { ResponseMap.first || association(:response_map) }
      additional_comment nil
    additional_comment nil
      version_num nil
    version_num nil
      round nil
    round nil
      is_submitted true
     is_submitted false
     end
   end
   end
  factory :response_map, class: ResponseMap do |f|
    f.map_id { 100 }
    f.reviewer_id { 200 }
    f.Participant {'participant'}
  end
end
----


The above factory was already present in the files whereas the second one is a contribution through the project. Both factories create the instances for testing whenever required.
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 ===
=== 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 [https://github.com/rspec/rspec-rails TestUnit] and [[RSpec]] with [[Cucumber (software)|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.
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 [https://github.com/rspec/rspec-rails TestUnit] and [https://en.wikipedia.org/wiki/RSpec RSpec] with [https://en.wikipedia.org/wiki/Cucumber_(software) 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 ==
== Contribution ==
Line 45: Line 38:


  require 'rails_helper'
  require 'rails_helper'
   describe ReviewResponseMap do
   describe 'ReviewResponseMap' do
     let(:reviewresponsemap) {ReviewResponseMap.new id: 6, reviewee_id: 1, reviewer_id: 2, reviewed_object_id: 8}
  before(:each) do
    let(:response) {Response.new id: 4, map_id: 4}
    @participant=create(:participant)
    let(:participant) {Participant.new id: 1}
    @assignment_questionnaire= create(:assignment_questionnaire)
     describe "#new" do
    @review_response=create(:review_response_map)
       it "Validate response instance creation with valid parameters" do
  end
        expect(reviewresponsemap.class).to be(ReviewResponseMap)
 
      end
  describe "#new" do
      it "Validate response instance creation with valid parameters" do
     it "Validate response instance creation with valid parameters" do
        expect(response.class).to be(Response)
      expect(@review_response.class).to be(ReviewResponseMap)
      end
    end
      it "Validate response instance creation with valid parameters" do
    it "Validate response instance creation with valid parameters" do
        expect(participant.class).to be(Participant)
      response=create(:response_take)
      end
      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
    describe "id" do
  end
      it "should be our exact reviewresponsemap's id" do
end
        expect(reviewresponsemap.id).to eq(6)
 
      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.
       it "should be our exact reviewer's id" do
 
         expect(reviewresponsemap.reviewer_id).to eq(2)
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.
      end
 
      it "should be our exact reviewee's id" do
  describe "#final_versions_from_reviewer method" do
         expect(reviewresponsemap.reviewee_id).to eq(1)
       it "should return final version of review when assignment has non varying rubric" do
      end
         create(:response_take)
      it "should not be any other reviewee's id" do
        map=ReviewResponseMap.final_versions_from_reviewer(1)
         expect(reviewresponsemap.reviewee_id).not_to eq(2)
         expect(map[:review][:questionnaire_id]).to be(1)
         expect(map[:review][:response_ids][0]).to be(1)
       end
       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
     end
     describe "title" do
     it "raise error when assignment is nil" do
       it "should be Review" do
       assignment = build(:assignment)
        expect(reviewresponsemap.get_title).to eq('Review')
      allow(Assignment).to receive(:find).and_return(nil)
       end
       row = ["user_name","reviewer_name", "reviewee_name"]
      it "should not be teamReview" do
      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?")
        expect(reviewresponsemap.get_title).not_to eq('Team Review')
      end
      it "should be feedbackReview" do
        expect(reviewresponsemap.get_title).not_to eq('Feedback Review')
      end
     end
     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 but actual changes can be found on the submitted git push request.
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.


Apart from basic methods, some important methods were tested for classes which inherits more from ResponseMap as compared to other classes, example being FeedbackResponseMap and QuizResponseMap classes. Some examples are given below as snippets of code.
 
   describe '#get_mappings_for_reviewer' do
   describe '#get_mappings_for_reviewer' do
  it "gives out the relation of reviewer and participant" 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)
      expect(QuizResponseMap.get_mappings_for_reviewer(participant.id).class).to eq(QuizResponseMap::ActiveRecord_Relation)
  end
    end
   end
   end
   describe '#quiz_score' do
   describe '#quiz_score' do
Line 101: Line 116:
     end
     end
   end
   end
  describe "#show_review without response" do
 
    it "should show a review" do
The above two methods are part of QuizResponseMap and thus by Rails convention, the files containing above code is quiz_response_map_spec.rb.
      expect(feedbackresponsemap.show_review).to eq("No review was performed")
    end
  end
  describe "#contributor" do
    let(:feedbackresponsemap) {FeedbackResponseMap.new(:id => 1, :reviewee_id => 2, :reviewer_id => 3, :reviewed_object_id => 4, :review => Response.new(), :reviewee => Participant.new(), :reviewer => AssignmentParticipant.new())} 
    it "should return the object of same class" do
      expect(feedbackresponsemap.contributor).to be(2)
    end
  end
  describe "#export_field" do
    it "should be xx" do
      expect(ReviewResponseMap.export_fields(6)).to eq(["contributor", "reviewed by"])
    end


=== Outcomes ===
=== Outcomes ===
Currently, all the test cases which have been implemented are working without an error, however, the tests hasn't been written for most of the methods which call functions from inherited and related classes.
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.


==== Running 'rspec' ====
rspec spec/models/review_response_map.rb
RSpec can be run on a local setup of Expertiza. The steps to setup 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/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


Commands:
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.
[[File:Quizresponsemap.jpg]]


<SNIPPETS>
===== 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 ==
== 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.
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.
After getting enough coverage on ResponseMap and child classes, the closely related models like Participant and Assignment can be considered for unit testing.


== References ==
== References ==
# [https://expertiza.ncsu.edu/ Expertiza]
# [https://github.com/expertiza/expertiza Github Expertiza]
# [https://github.com/qizhongzhi/expertiza Local Contribution Github Fork]
# [https://relishapp.com/rspec RSpec]

Latest revision as of 01:18, 21 November 2016

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