E1850. Write unit tests for review response map.rb team100: Difference between revisions
No edit summary |
|||
Line 52: | Line 52: | ||
=== Questionnaire === | === Questionnaire === | ||
Test the questionnaire using find_by to get specific questionnaire of map. | Test the questionnaire using find_by to get specific questionnaire of map. | ||
<pre> | |||
def questionnaire(round = nil) | |||
Questionnaire.find_by(id: self.assignment.review_questionnaire_id(round)) | |||
end | |||
</pre> | |||
<pre> | <pre> | ||
it '#questionnaire' do | it '#questionnaire' do | ||
Line 63: | Line 69: | ||
=== Get title === | === Get title === | ||
Test the get_title method. | Test the get_title method. | ||
<pre> | |||
</pre> | |||
def get_title | |||
"Review" | |||
end | |||
<pre> | <pre> | ||
it '#get_title' do | it '#get_title' do | ||
Line 71: | Line 82: | ||
=== Delete === | === Delete === | ||
Test the delete method of review_response_map which contains delete feedback_response_map. | Test the delete method of review_response_map which contains delete feedback_response_map. | ||
<pre> | |||
def delete(_force = nil) | |||
fmaps = FeedbackResponseMap.where(reviewed_object_id: self.response.response_id) | |||
fmaps.each(&:destroy) | |||
maps = MetareviewResponseMap.where(reviewed_object_id: self.id) | |||
maps.each(&:destroy) | |||
self.destroy | |||
end | |||
</pre> | |||
<pre> | <pre> | ||
it '#delete' do | it '#delete' do | ||
Line 81: | Line 101: | ||
=== Export fields === | === Export fields === | ||
<pre> | |||
def self.export(csv, parent_id, _options) | |||
mappings = where(reviewed_object_id: parent_id).to_a | |||
mappings.sort! {|a, b| a.reviewee.name <=> b.reviewee.name } | |||
mappings.each do |map| | |||
csv << [ | |||
map.reviewee.name, | |||
map.reviewer.name | |||
] | |||
end | |||
end | |||
</pre> | |||
Test the export_fields method which show the title of export csv file should be "contributor" and "reviewed by". | Test the export_fields method which show the title of export csv file should be "contributor" and "reviewed by". | ||
<pre> | <pre> | ||
Line 89: | Line 121: | ||
=== Export === | === Export === | ||
<pre> | |||
def self.export_fields(_options) | |||
["contributor", "reviewed by"] | |||
end | |||
</pre> | |||
Test the export method. | Test the export method. | ||
<pre> | <pre> | ||
Line 101: | Line 138: | ||
=== Import === | === Import === | ||
<pre> | |||
def self.import(row_hash, _session, assignment_id) | |||
reviewee_user_name = row_hash[:reviewee].to_s | |||
reviewee_user = User.find_by(name: reviewee_user_name) | |||
raise ArgumentError, "Cannot find reviewee user." unless reviewee_user | |||
reviewee_participant = AssignmentParticipant.find_by(user_id: reviewee_user.id, parent_id: assignment_id) | |||
raise ArgumentError, "Reviewee user is not a participant in this assignment." unless reviewee_participant | |||
reviewee_team = AssignmentTeam.team(reviewee_participant) | |||
if reviewee_team.nil? # lazy team creation: if the reviewee does not have team, create one. | |||
reviewee_team = AssignmentTeam.create(name: 'Team' + '_' + rand(1000).to_s, | |||
parent_id: assignment_id, type: 'AssignmentTeam') | |||
t_user = TeamsUser.create(team_id: reviewee_team.id, user_id: reviewee_user.id) | |||
team_node = TeamNode.create(parent_id: assignment_id, node_object_id: reviewee_team.id) | |||
TeamUserNode.create(parent_id: team_node.id, node_object_id: t_user.id) | |||
end | |||
row_hash[:reviewers].each do |reviewer| | |||
reviewer_user_name = reviewer.to_s | |||
reviewer_user = User.find_by(name: reviewer_user_name) | |||
raise ArgumentError, "Cannot find reviewer user." unless reviewer_user | |||
next if reviewer_user_name.empty? | |||
reviewer_participant = AssignmentParticipant.find_by(user_id: reviewer_user.id, parent_id: assignment_id) | |||
raise ArgumentError, "Reviewer user is not a participant in this assignment." unless reviewer_participant | |||
ReviewResponseMap.find_or_create_by(reviewed_object_id: assignment_id, | |||
reviewer_id: reviewer_participant.id, | |||
reviewee_id: reviewee_team.id, | |||
calibrate_to: false) | |||
end | |||
end | |||
</pre> | |||
Test the import method which includes errors casued by various reasons. | Test the import method which includes errors casued by various reasons. | ||
<pre> | <pre> | ||
Line 128: | Line 194: | ||
=== Show feedback === | === Show feedback === | ||
<pre> | |||
def show_feedback(response) | |||
return unless self.response.any? and response | |||
map = FeedbackResponseMap.find_by(reviewed_object_id: response.id) | |||
return map.response.last.display_as_html if map and map.response.any? | |||
end | |||
</pre> | |||
Test show_feedback method. | Test show_feedback method. | ||
<pre> | <pre> | ||
Line 144: | Line 217: | ||
=== Metareview response maps === | === Metareview response maps === | ||
<pre> | |||
def metareview_response_maps | |||
responses = Response.where(map_id: self.id) | |||
metareview_list = [] | |||
responses.each do |response| | |||
metareview_response_maps = MetareviewResponseMap.where(reviewed_object_id: response.id) | |||
metareview_response_maps.each {|metareview_response_map| metareview_list << metareview_response_map } | |||
end | |||
metareview_list | |||
end | |||
</pre> | |||
Test metareview_response_maps method. | Test metareview_response_maps method. | ||
<pre> | <pre> | ||
Line 154: | Line 238: | ||
=== Get responses for team round === | === Get responses for team round === | ||
<pre> | |||
def self.get_responses_for_team_round(team, round) | |||
responses = [] | |||
if team.id | |||
maps = ResponseMap.where(reviewee_id: team.id, type: "ReviewResponseMap") | |||
maps.each do |map| | |||
if map.response.any? and map.response.reject {|r| (r.round != round || !r.is_submitted) }.any? | |||
responses << map.response.reject {|r| (r.round != round || !r.is_submitted) }.last | |||
end | |||
end | |||
responses.sort! {|a, b| a.map.reviewer.fullname <=> b.map.reviewer.fullname } | |||
end | |||
responses | |||
end | |||
</pre> | |||
Test get_responses_for_team_round method. | Test get_responses_for_team_round method. | ||
<pre> | <pre> | ||
Line 166: | Line 265: | ||
=== Final versions from reviewer === | === Final versions from reviewer === | ||
<pre> | |||
def self.final_versions_from_reviewer(reviewer_id) | |||
maps = ReviewResponseMap.where(reviewer_id: reviewer_id) | |||
assignment = Assignment.find(Participant.find(reviewer_id).parent_id) | |||
prepare_final_review_versions(assignment, maps) | |||
end | |||
</pre> | |||
Test final_versions_from_reviewer method. | Test final_versions_from_reviewer method. | ||
<pre> | <pre> | ||
Line 183: | Line 289: | ||
=== Review response report === | === Review response report === | ||
<pre> | |||
def self.review_response_report(id, assignment, type, review_user) | |||
if review_user.nil? | |||
# This is not a search, so find all reviewers for this assignment | |||
response_maps_with_distinct_participant_id = | |||
ResponseMap.select("DISTINCT reviewer_id").where('reviewed_object_id = ? and type = ? and calibrate_to = ?', id, type, 0) | |||
@reviewers = [] | |||
response_maps_with_distinct_participant_id.each do |reviewer_id_from_response_map| | |||
@reviewers << AssignmentParticipant.find(reviewer_id_from_response_map.reviewer_id) | |||
end | |||
@reviewers = Participant.sort_by_name(@reviewers) | |||
else | |||
# This is a search, so find reviewers by user's full name | |||
user_ids = User.select("DISTINCT id").where('fullname LIKE ?', '%' + review_user[:fullname] + '%') | |||
@reviewers = AssignmentParticipant.where('user_id IN (?) and parent_id = ?', user_ids, assignment.id) | |||
end | |||
# @review_scores[reveiwer_id][reviewee_id] = score for assignments not using vary_rubric_by_rounds feature | |||
# @review_scores[reviewer_id][round][reviewee_id] = score for assignments using vary_rubric_by_rounds feature | |||
end | |||
</pre> | |||
Test review_response_report method. | Test review_response_report method. | ||
<pre> | <pre> | ||
Line 206: | Line 332: | ||
=== Email === | === Email === | ||
<pre> | |||
def email(defn, _participant, assignment) | |||
defn[:body][:type] = "Peer Review" | |||
AssignmentTeam.find(reviewee_id).users.each do |user| | |||
defn[:body][:obj_name] = assignment.name | |||
defn[:body][:first_name] = User.find(user.id).fullname | |||
defn[:to] = User.find(user.id).email | |||
Mailer.sync_message(defn).deliver_now | |||
end | |||
end | |||
</pre> | |||
Test email method which can successfully send an email. | Test email method which can successfully send an email. | ||
<pre> | <pre> | ||
Line 222: | Line 359: | ||
=== Prepare final review versions === | === Prepare final review versions === | ||
<pre> | |||
def self.prepare_final_review_versions(assignment, maps) | |||
review_final_versions = {} | |||
rounds_num = assignment.rounds_of_reviews | |||
if rounds_num and rounds_num > 1 | |||
(1..rounds_num).each do |round| | |||
prepare_review_response(assignment, maps, review_final_versions, round) | |||
end | |||
else | |||
prepare_review_response(assignment, maps, review_final_versions, nil) | |||
end | |||
review_final_versions | |||
end | |||
</pre> | |||
Test the prepare_final_review_versions method. | Test the prepare_final_review_versions method. | ||
<pre> | <pre> | ||
Line 247: | Line 398: | ||
=== Prepare review response === | === Prepare review response === | ||
<pre> | |||
def self.prepare_review_response(assignment, maps, review_final_versions, round) | |||
symbol = if round.nil? | |||
:review | |||
else | |||
("review round" + round.to_s).to_sym | |||
end | |||
review_final_versions[symbol] = {} | |||
review_final_versions[symbol][:questionnaire_id] = assignment.review_questionnaire_id(round) | |||
response_ids = [] | |||
maps.each do |map| | |||
where_map = {map_id: map.id} | |||
where_map[:round] = round unless round.nil? | |||
responses = Response.where(where_map) | |||
response_ids << responses.last.id unless responses.empty? | |||
end | |||
review_final_versions[symbol][:response_ids] = response_ids | |||
end | |||
</pre> | |||
Test prepare_review_response method. | Test prepare_review_response method. | ||
<pre> | <pre> |
Revision as of 16:17, 6 November 2018
This wiki page is for the description of unit test for E1850 OSS assignment for Fall 2018, CSC/ECE 517.
Background
Expertiza is an open source web based peer review system developed and maintained by students and faculty members at North Carolina State University. It enables students enrolled in a particular course to form online teams, complete assignments, review other's work and receive feedbacks of your work.
Problem
Review_response_map.rb is used to prepare data for peer review. But there are no unit tests for it.
Work to be done
- Create a new file named review_response_map_spec.rb under spec/models folder
- Write RSpec unit tests to make the path coverage above 90%.
- Coverage as many edge cases as we can.
- Achieve as high branch coverage as we can. Use the mutant-rspec gem to measure test thoroughness and fault-finding capability of our tests.
Files Created
- spec/models/review_response_map_spec.rb
Test Plan
mock instance
We mock the necessary instances for the test in the beginning of test file.
let(:team) { build(:assignment_team, id: 1, name: 'team no name', assignment: assignment, users: [student], parent_id: 1) } let(:team1) { build(:assignment_team, id: 2, name: 'team has name', assignment: assignment, users: [student]) } let(:review_response_map) { build(:review_response_map, id: 1, assignment: assignment, reviewer: participant, reviewee: team, reviewed_object_id: 1) } let(:review_response_map1) { build(:review_response_map, id: 2, assignment: assignment, reviewer: participant1, reviewee: team1, reviewed_object_id: 1) } let(:feed_back_response_map) { double('feed_back_response_map', reviewed_object_id: 1) } let(:feedback) { FeedbackResponseMap.new(id: 1, reviewed_object_id: 1, reviewer_id: 1, reviewee_id: 1) } let(:participant) { build(:participant, id: 1, parent_id: 1, user: build(:student, parent_id: 1, name: 'no name', fullname: 'no one')) } let(:participant1) { build(:participant, id: 2, parent_id: 2, user: build(:student, parent_id: 1, name: 'has name', fullname: 'has one')) } let(:questionnaire) { ReviewQuestionnaire.new(id: 1, questions: [question], max_question_score: 5) } let(:questionnaire1) { Questionnaire.new(id: 1, type: 'ReviewQuestionnaire') } let(:assignment) { build(:assignment, id: 1, name: 'Test Assgt', rounds_of_reviews: 2 ) } let(:assignment1) { build(:assignment, id: 2, name: 'Test Assgt', rounds_of_reviews: 1 ) } let(:response) { build(:response, id: 1, map_id: 1, round: 1, response_map: review_response_map, scores: [answer], is_submitted: true) } let(:response1) { build(:response, id: 2, map_id: 1, round: 2, response_map: review_response_map, scores: [answer]) } let(:response2) { build(:response, id: 3, map_id: 1, round: nil, response_map: review_response_map, scores: [answer], is_submitted: true) } let(:answer) { Answer.new(answer: 1, comments: 'Answer text', question_id: 1) } let(:question) { Criterion.new(id: 1, weight: 2, break_before: true) } let(:metareview_response_map) { double('metareviewmap')} let(:metareview_response_map1) { MetareviewResponseMap.new(reviewed_object_id: 1)} let(:student) {build(:student, id: 1, fullname: 'no one', email: 'expertiza@mailinator.com') } let(:assignment_questionnaire){ AssignmentQuestionnaire.new(assignment_id: 1, used_in_round: 1, questionnaire_id: 1) } let(:assignment_questionnaire1){ AssignmentQuestionnaire.new(assignment_id: 1, used_in_round: 2, questionnaire_id: 1) } let(:response_map) { ResponseMap.new(id: 1, reviewed_object_id: 1, reviewee_id: 1, reviewer_id: 1, type: "ReviewResponseMap", response: [response], calibrate_to: 0) } let(:user) {User.new(id:1 , name: "name", fullname: 'fullname') } let(:user1) { User.new(id: 2, name: "name1", fullname: 'fullname') } let(:assignment_participant) { AssignmentParticipant.new(user_id: 1, parent_id: 1) } let(:assignment_participant1) { AssignmentParticipant.new(id: 1, user_id: 2, parent_id: 1) } let(:teams_users) {TeamsUser.new(user_id: 1, team_id: 1)}
Questionnaire
Test the questionnaire using find_by to get specific questionnaire of map.
def questionnaire(round = nil) Questionnaire.find_by(id: self.assignment.review_questionnaire_id(round)) end
it '#questionnaire' do round = 1 allow(assignment).to receive(:review_questionnaire_id).with(1).and_return(1) allow(Questionnaire).to receive(:find_by).with(id: 1).and_return(questionnaire1) expect(review_response_map.questionnaire(1)).to eq(questionnaire1) end
Get title
Test the get_title method.
def get_title "Review" end
it '#get_title' do expect(review_response_map.get_title).to eq("Review") end
Delete
Test the delete method of review_response_map which contains delete feedback_response_map.
def delete(_force = nil) fmaps = FeedbackResponseMap.where(reviewed_object_id: self.response.response_id) fmaps.each(&:destroy) maps = MetareviewResponseMap.where(reviewed_object_id: self.id) maps.each(&:destroy) self.destroy end
it '#delete' do allow(Response).to receive(:find).and_return(response) allow(FeedbackResponseMap).to receive(:where).with(reviewed_object_id: 1).and_return([feedback]) allow(MetareviewResponseMap).to receive(:where).and_return([metareview_response_map1]) expect(review_response_map.delete).to equal(review_response_map) end
Export fields
def self.export(csv, parent_id, _options) mappings = where(reviewed_object_id: parent_id).to_a mappings.sort! {|a, b| a.reviewee.name <=> b.reviewee.name } mappings.each do |map| csv << [ map.reviewee.name, map.reviewer.name ] end end
Test the export_fields method which show the title of export csv file should be "contributor" and "reviewed by".
it '#export_fields' do expect(ReviewResponseMap.export_fields('Missing "_options"')).to eq(["contributor", "reviewed by"]) end
Export
def self.export_fields(_options) ["contributor", "reviewed by"] end
Test the export method.
it '#export' do csv = [] parent_id = 1 _options = _options allow(ReviewResponseMap).to receive(:where).with(reviewed_object_id: 1).and_return([review_response_map, review_response_map1]) expect(ReviewResponseMap.export(csv, parent_id, _options)).to eq([review_response_map1, review_response_map]) end
Import
def self.import(row_hash, _session, assignment_id) reviewee_user_name = row_hash[:reviewee].to_s reviewee_user = User.find_by(name: reviewee_user_name) raise ArgumentError, "Cannot find reviewee user." unless reviewee_user reviewee_participant = AssignmentParticipant.find_by(user_id: reviewee_user.id, parent_id: assignment_id) raise ArgumentError, "Reviewee user is not a participant in this assignment." unless reviewee_participant reviewee_team = AssignmentTeam.team(reviewee_participant) if reviewee_team.nil? # lazy team creation: if the reviewee does not have team, create one. reviewee_team = AssignmentTeam.create(name: 'Team' + '_' + rand(1000).to_s, parent_id: assignment_id, type: 'AssignmentTeam') t_user = TeamsUser.create(team_id: reviewee_team.id, user_id: reviewee_user.id) team_node = TeamNode.create(parent_id: assignment_id, node_object_id: reviewee_team.id) TeamUserNode.create(parent_id: team_node.id, node_object_id: t_user.id) end row_hash[:reviewers].each do |reviewer| reviewer_user_name = reviewer.to_s reviewer_user = User.find_by(name: reviewer_user_name) raise ArgumentError, "Cannot find reviewer user." unless reviewer_user next if reviewer_user_name.empty? reviewer_participant = AssignmentParticipant.find_by(user_id: reviewer_user.id, parent_id: assignment_id) raise ArgumentError, "Reviewer user is not a participant in this assignment." unless reviewer_participant ReviewResponseMap.find_or_create_by(reviewed_object_id: assignment_id, reviewer_id: reviewer_participant.id, reviewee_id: reviewee_team.id, calibrate_to: false) end end
Test the import method which includes errors casued by various reasons.
it '#import' do row_hash={reviewee: "name", reviewers: ["name1"]} _session = nil assignment_id = 1 allow(User).to receive(:find_by).with(name: "name").and_return(user) allow(AssignmentParticipant).to receive(:find_by).with(user_id: 1, parent_id: 1).and_return(assignment_participant) allow(AssignmentTeam).to receive(:team).with(assignment_participant).and_return(team) allow(User).to receive(:find_by).with(name: "name1").and_return(user1) allow(AssignmentParticipant).to receive(:find_by).with(user_id: 2, parent_id: 1).and_return(assignment_participant1) allow(ReviewResponseMap).to receive(:find_or_create_by).with(reviewed_object_id: 1, reviewer_id: 1, reviewee_id: 1, calibrate_to: false).and_return(review_response_map) expect(ReviewResponseMap.import(row_hash, _session, 1)).to eq(["name1"]) # when reviewee_team = nil allow(AssignmentTeam).to receive(:team).with(assignment_participant).and_return(nil) allow(AssignmentTeam).to receive(:create).and_return(double('team', id: 1)) allow(TeamsUser).to receive(:create).with(team_id: 1, user_id: 1).and_return(double('teams_users', id: 1, team_id: 1, user_id: 1)) allow(TeamNode).to receive(:create).with(parent_id: assignment_id, node_object_id: 1).and_return(double('team_node', id: 1, parent_id: 1, node_object_id: 1)) allow(TeamUserNode).to receive(:create).with(parent_id: 1, node_object_id: 1).and_return(double('team_user_node', id: 1, parent_id: 1, node_object_id: 1)) allow(User).to receive(:find_by).with(name: "name1").and_return(user1) allow(AssignmentParticipant).to receive(:find_by).with(user_id: 2, parent_id: 1).and_return(assignment_participant1) allow(ReviewResponseMap).to receive(:find_or_create_by).with(reviewed_object_id: 1, reviewer_id: 1, reviewee_id: 1, calibrate_to: false).and_return(review_response_map) expect(ReviewResponseMap.import(row_hash, _session, 1)).to eq(["name1"]) end
Show feedback
def show_feedback(response) return unless self.response.any? and response map = FeedbackResponseMap.find_by(reviewed_object_id: response.id) return map.response.last.display_as_html if map and map.response.any? end
Test show_feedback method.
it '#show_feedback' do allow(review_response_map).to receive(:response).and_return([response]) allow(Response).to receive(:find).and_return(response) allow(FeedbackResponseMap).to receive(:find_by).with(reviewed_object_id: 1).and_return(feedback) allow(feedback).to receive(:response).and_return([response]) expect(review_response_map.show_feedback(response)).to eq("<table width=\"100%\"><tr><td align=\"left\" width=\"70%\"><b>Review </b>"\ " <a href=\"#\" name= \"review_1Link\" onClick=\"toggleElement('review_1','review');return false;\">"\ "show review</a></td><td align=\"left\"><b>Last Reviewed:</b><span>Not available</span></td></tr></table><table id=\"review_1\""\ " style=\"display: none;\" class=\"table table-bordered\"><tr><td><b>"\ "Additional Comment: </b></td></tr></table>") end
Metareview response maps
def metareview_response_maps responses = Response.where(map_id: self.id) metareview_list = [] responses.each do |response| metareview_response_maps = MetareviewResponseMap.where(reviewed_object_id: response.id) metareview_response_maps.each {|metareview_response_map| metareview_list << metareview_response_map } end metareview_list end
Test metareview_response_maps method.
it '#metareview_response_maps' do allow(Response).to receive(:where).with(map_id: 1).and_return([response]) allow(MetareviewResponseMap).to receive(:where).with(reviewed_object_id: 1).and_return([metareview_response_map1]) expect(review_response_map.metareview_response_maps).to eq([metareview_response_map1]) end
Get responses for team round
def self.get_responses_for_team_round(team, round) responses = [] if team.id maps = ResponseMap.where(reviewee_id: team.id, type: "ReviewResponseMap") maps.each do |map| if map.response.any? and map.response.reject {|r| (r.round != round || !r.is_submitted) }.any? responses << map.response.reject {|r| (r.round != round || !r.is_submitted) }.last end end responses.sort! {|a, b| a.map.reviewer.fullname <=> b.map.reviewer.fullname } end responses end
Test get_responses_for_team_round method.
it '#get_responses_for_team_round' do allow(Team).to receive(:find).and_return(team) allow(team).to receive(:id).and_return(1) round = 1 allow(ResponseMap).to receive(:where).with(reviewee_id: team.id, type: "ReviewResponseMap").and_return([response_map]) expect(ReviewResponseMap.get_responses_for_team_round(team, 1)).to eq([response]) end
Final versions from reviewer
def self.final_versions_from_reviewer(reviewer_id) maps = ReviewResponseMap.where(reviewer_id: reviewer_id) assignment = Assignment.find(Participant.find(reviewer_id).parent_id) prepare_final_review_versions(assignment, maps) end
Test final_versions_from_reviewer method.
it '#final_versions_from_reviewer' do reviewer_id = 1 allow(ReviewResponseMap).to receive(:where).with(reviewer_id: 1).and_return([review_response_map]) allow(Participant).to receive(:find).with(1).and_return(participant) allow(participant).to receive(:parent_id).and_return(1) allow(Assignment).to receive(:find).with(1).and_return(assignment) allow(Response).to receive(:where).with(map_id: 1, round: 1).and_return([response]) allow(assignment).to receive(:review_questionnaire_id).with(1).and_return(1) allow(Response).to receive(:where).with(map_id: 1, round: 2).and_return([response1]) allow(assignment).to receive(:review_questionnaire_id).with(2).and_return(1) expect(ReviewResponseMap.final_versions_from_reviewer(1)).to eq({"review round1":{questionnaire_id: 1, response_ids:[1]}, "review round2":{questionnaire_id: 1, response_ids:[2] }}) end
Review response report
def self.review_response_report(id, assignment, type, review_user) if review_user.nil? # This is not a search, so find all reviewers for this assignment response_maps_with_distinct_participant_id = ResponseMap.select("DISTINCT reviewer_id").where('reviewed_object_id = ? and type = ? and calibrate_to = ?', id, type, 0) @reviewers = [] response_maps_with_distinct_participant_id.each do |reviewer_id_from_response_map| @reviewers << AssignmentParticipant.find(reviewer_id_from_response_map.reviewer_id) end @reviewers = Participant.sort_by_name(@reviewers) else # This is a search, so find reviewers by user's full name user_ids = User.select("DISTINCT id").where('fullname LIKE ?', '%' + review_user[:fullname] + '%') @reviewers = AssignmentParticipant.where('user_id IN (?) and parent_id = ?', user_ids, assignment.id) end # @review_scores[reveiwer_id][reviewee_id] = score for assignments not using vary_rubric_by_rounds feature # @review_scores[reviewer_id][round][reviewee_id] = score for assignments using vary_rubric_by_rounds feature end
Test review_response_report method.
it '#review_response_report' do id = 1 type = "MetareviewResponseMap" reviewer_id = 1 user_ids = [] review_user = user allow(Participant).to receive(:find).with(1).and_return(participant) allow(Assignment).to receive(:find).with(1).and_return(assignment) allow(User).to receive_message_chain(:select, :where).and_return([user]) allow(AssignmentParticipant).to receive(:where).and_return([assignment_participant]) expect(ReviewResponseMap.review_response_report(id, Assignment.find(Participant.find(reviewer_id).parent_id), type, review_user)).to eq( [assignment_participant] ) review_user = nil allow(ResponseMap).to receive_message_chain(:select, :where).and_return([response_map]) allow([response_map]).to receive(:reviewer_id).and_return(1) allow(AssignmentParticipant).to receive(:find).with(1).and_return([assignment_participant]) allow(Participant).to receive(:sort_by_name).and_return([assignment_participant]) expect(ReviewResponseMap.review_response_report(id, Assignment.find(Participant.find(reviewer_id).parent_id), type, review_user)).to eq( [assignment_participant] ) end
def email(defn, _participant, assignment) defn[:body][:type] = "Peer Review" AssignmentTeam.find(reviewee_id).users.each do |user| defn[:body][:obj_name] = assignment.name defn[:body][:first_name] = User.find(user.id).fullname defn[:to] = User.find(user.id).email Mailer.sync_message(defn).deliver_now end end
Test email method which can successfully send an email.
it '#email' do reviewer_id = 1 allow(Participant).to receive(:find).with(1).and_return(participant) allow(Assignment).to receive(:find).with(1).and_return(assignment) allow(AssignmentTeam).to receive(:find).with(1).and_return(team) allow(AssignmentTeam).to receive(:users).and_return(student) allow(User).to receive(:find).with(1).and_return(student) review_response_map.reviewee_id = 1 defn = {body: {type: "Peer Review", obj_name: "Test Assgt", first_name: "no one", partial_name: "new_submission"}, to: "expertiza@mailinator.com"} expect{review_response_map.email(defn, participant, Assignment.find(Participant.find(reviewer_id).parent_id)) }.to change { ActionMailer::Base.deliveries.count }.by (1) end
Prepare final review versions
def self.prepare_final_review_versions(assignment, maps) review_final_versions = {} rounds_num = assignment.rounds_of_reviews if rounds_num and rounds_num > 1 (1..rounds_num).each do |round| prepare_review_response(assignment, maps, review_final_versions, round) end else prepare_review_response(assignment, maps, review_final_versions, nil) end review_final_versions end
Test the prepare_final_review_versions method.
it '#prepare_final_review_versions' do review_final_versions = {} reviewer_id = 1 allow(metareview_response_map1).to receive(:id).and_return(1) allow(Participant).to receive(:find).with(1).and_return(participant) allow(Assignment).to receive(:find).with(1).and_return(assignment) allow(MetareviewResponseMap).to receive(:where).with(reviewed_object_id:1).and_return([metareview_response_map1]) allow(Response).to receive(:where).with(map_id: 1, round: 1).and_return([response]) allow(assignment).to receive(:review_questionnaire_id).with(1).and_return(1) allow(Response).to receive(:where).with(map_id: 1, round: 2).and_return([response1]) allow(assignment).to receive(:review_questionnaire_id).with(2).and_return(1) expect(ReviewResponseMap.prepare_final_review_versions(Assignment.find(Participant.find(reviewer_id).parent_id), MetareviewResponseMap.where(reviewed_object_id: 1))).to eq({"review round1":{questionnaire_id: 1, response_ids:[1]}, "review round2":{questionnaire_id: 1, response_ids:[2] }}) reviewer_id = 2 allow(Participant).to receive(:find).with(2).and_return(participant1) allow(Assignment).to receive(:find).with(2).and_return(assignment1) allow(MetareviewResponseMap).to receive(:where).with(reviewed_object_id:1).and_return([metareview_response_map1]) allow(assignment).to receive(:review_questionnaire_id).with(nil).and_return(1) allow(Response).to receive(:where).with(map_id: 1).and_return([response2]) expect(ReviewResponseMap.prepare_final_review_versions(Assignment.find(Participant.find(reviewer_id).parent_id), MetareviewResponseMap.where(reviewed_object_id: 1))).to eq({ review:{questionnaire_id: nil, response_ids:[3]}}) end
Prepare review response
def self.prepare_review_response(assignment, maps, review_final_versions, round) symbol = if round.nil? :review else ("review round" + round.to_s).to_sym end review_final_versions[symbol] = {} review_final_versions[symbol][:questionnaire_id] = assignment.review_questionnaire_id(round) response_ids = [] maps.each do |map| where_map = {map_id: map.id} where_map[:round] = round unless round.nil? responses = Response.where(where_map) response_ids << responses.last.id unless responses.empty? end review_final_versions[symbol][:response_ids] = response_ids end
Test prepare_review_response method.
it '#prepare_review_response' do review_final_versions = {} review_response_map.id = 1 round = 1 maps = [review_response_map] allow(Assignment).to receive(:find).with(1).and_return(assignment) allow(Response).to receive(:where).with(map_id: 1, round: 1).and_return([response]) allow(assignment).to receive(:review_questionnaire_id).with(1).and_return(1) expect(ReviewResponseMap.prepare_review_response(assignment, maps, review_final_versions, round)).to eq([1]) round = nil allow(Assignment).to receive(:find).with(1).and_return(assignment) allow(assignment).to receive(:review_questionnaire_id).with(nil).and_return(1) allow(Response).to receive(:where).with(map_id: 1).and_return([response2]) expect(ReviewResponseMap.prepare_review_response(assignment, maps, review_final_versions, round)).to eq([3]) end
Running Rspec
The tests can be run on the terminal from inside the expertiza folder using following commands:
rspec spec/models/review_response_map_spec.rb
Unit Test Result
app/models/review_response_map.rb
100.0 % covered
102 relevant lines. 102 lines covered and 0 lines missed.
Full video for this test can be found at https://drive.google.com/file/d/18vr3q2dCyh3_tsFLH8w9y6Y9uhdz0Ljj/view?usp=sharing