E1848 Write unit tests for assignment team: Difference between revisions
No edit summary |
No edit summary |
||
(23 intermediate revisions by 2 users not shown) | |||
Line 2: | Line 2: | ||
==Project Introduction== | ==Project Introduction== | ||
assignment_team.rb is the child class of team.rb. It is used to | ====Background==== | ||
assignment_team.rb is the child class of team.rb. It is used to handle multiple problems relates to team in the assignment. Its responsibilities can mainly fall in three categories: participant of the team, reviews of the team, and the operation for the whole team. For the participant, it can be used to decide if a participant is in a given team and view the members of the team or remove a member. For reviews, it deals with the problem that getting the reviews for the team, assign reviewer for the team and get if the team has been reviewed by a specific reviewers. For the whole team, we can delete the team or view the scores, etc. by using this class. | |||
====Motivation==== | |||
Make sure assignment_team.rb provides all functions as expected is important for the whole system. It requires enough tests for all the functions and the edge cases may occur. However, there are not enough unit tests for this model in expertiza. The following tests are added to assignment_team.rb in this project. | |||
To make sure we can cover as many conditions as we can(the objective for this project is getting at least 90% coverage rate), we first design test cases. The following factors are taking into considerations: the expected functions for each method, the possible edge cases and the pre-conditions for each cases. Then we get the unit test plan and complete the test following test steps. | |||
==Memebers of Project== | |||
Jianshu Zhang | |||
Wanjing Kuang | |||
Wei Wu | |||
==Mentor== | |||
Zhewei Hu | |||
==File Involvement== | |||
1.app/models/assignment_team.rb | |||
2.spec/models/assignment_team_spec.rb | |||
3.spec/factories/factories.rb | |||
==Test Plan== | |||
1. two test cases for method "include?": When the team includes a given participant and When the team doesn't include a given participant | |||
2. one test case for method "parent_model": It returns "Assignment" when the method is called. | |||
3. two test cases for method "self.parent_model(id)": When it's given a correct id and When it's given an incorrect id. | |||
4. one test case for method "fullname": When the participant has an full name. | |||
5. one test case for method "review_map_type": It returns ReviewResponseMap when the method is called. | |||
6. one test case for method "self.prototype": It returns an new instance of AssignmentTeam when the method is called. | |||
7. two test cases for method "assign_reviewer(reviewer)": When the team has an assignment and When the assignment record can not be found. | |||
8. one test case for method "reviewd_by?": When it gets correct reviewer and returns true as an result. | |||
9. one test case for method " topic": When it returns the correct id. | |||
10. three test cases for method "has_submissions?": When the team doesn't submit any file or link, when team submits a link instead of files and | |||
when the team submits some files. | |||
11. two test cases for method "participants": When no participants in this team and When adding some participants and get all the participants. | |||
12. one test case for method "add_participant": When adding an participant, it will return an instance of AssignmentParticipant. | |||
13. two test cases for method " delete and destroy": Testing delete and destory. | |||
14. one test case for method "get_first_member": Let a team have two members, the first assigned member is expected to be returned by this method. | |||
15. two test cases for method "hyoerlinks": the current teams submitted hyperlinks and not submitted the hyperlinks | |||
16.three test cases for method "submit_hyperlink": the hyperlink is empty, the hyperlink is not empty and it calls the method on NET::HTTP,the hyperlink is not empty and it raises error | |||
17.three test cases for method "team": the participant is nil, the participant exists and the team user exists | |||
18.two test cases for method "export_files": an exception is expected if team is not exist or a new exported file is expected. | |||
==Unit Tests== | ==Unit Tests== | ||
Line 113: | Line 171: | ||
</pre> | </pre> | ||
2. When the assignment record can not be found | 2. When the assignment record can not be found | ||
<pre> | <pre> | ||
let(:assignment_team2) { build(:assignment_team, id: 2, parent_id: 2) } | let(:assignment_team2) { build(:assignment_team, id: 2, parent_id: 2) } | ||
Line 267: | Line 325: | ||
1. when the current teams submitted hyperlinks | 1. when the current teams submitted hyperlinks | ||
<pre> | <pre> | ||
let(:assignment_team) { build(:assignment_team) } | let(:assignment_team) { build(:assignment_team) } | ||
Line 286: | Line 345: | ||
end | end | ||
</pre> | </pre> | ||
====Testing files==== | |||
<pre> | |||
before :each do | |||
@directory = "a" | |||
@files = ["b.txt", "c.java", "d.txt"] | |||
@files1 = ["b/c", "d/e"] | |||
end | |||
it "call the method in Dir" do | |||
expect(Dir).to receive(:[]).with(@directory + "/*").and_return(@files) | |||
assignment_team.files(@directory) | |||
end | |||
</pre> | |||
====Testing submit_hyperlink==== | |||
3 test cases are designed to test this method: | |||
1. when the hyperlink is empty | |||
<pre> | |||
context "when the hyperlink is empty" do | |||
it "raise excpetion" do | |||
expect{(assignment_team.submit_hyperlink(""))}.to raise_error('The hyperlink cannot be empty!') | |||
end | |||
</pre> | |||
2. when the hyperlink is not empty and it calls the method on NET::HTTP | |||
<pre> | |||
before :each do | |||
@link = "htp.aa/.." | |||
end | |||
it "call the method on NET::HTTP" do | |||
expect(Net::HTTP).to receive(:get_response).with(URI(@link+'http://')) | |||
assignment_team.submit_hyperlink(@link) | |||
end | |||
</pre> | |||
3. when the hyperlink is not empty and it raises error | |||
<pre> | |||
it "raise error" do | |||
allow(Net::HTTP).to receive(:get_response).with(URI(@link+'http://')).and_return("402") | |||
expect{(assignment_team.submit_hyperlink(@link))}.to raise_error('HTTP status code: 402') | |||
end | |||
</pre> | |||
====Testing remove_hyperlink==== | |||
<pre> | |||
before :each do | |||
@hyperlink = "http://a.com" | |||
end | |||
it 'call the hyperlinks method' do | |||
expect(assignment_team).to receive(:hyperlinks).and_return(["https://www.expertiza.ncsu.edu"]) | |||
assignment_team.remove_hyperlink(@hyperlink) | |||
end | |||
</pre> | |||
====Testing team==== | |||
3 test cases are designed to test this method | |||
1. when the participant is nil then this method will return nil | |||
<pre> | |||
context 'when the participant is nil then this method will return nil' do | |||
it 'the participant is nil' do | |||
expect(AssignmentTeam.team(nil)).to eq(nil) | |||
end | |||
end | |||
</pre> | |||
2. when it can find the participant | |||
<pre> | |||
let(:participant) { build(:participant) } | |||
context 'can find the participant' do | |||
it 'send the correct user_id to the TeamsUser.where method' do | |||
expect(TeamsUser).to receive(:where).with(user_id: participant.user_id).and_return([team_user]) | |||
AssignmentTeam.team(participant) | |||
end | |||
</pre> | |||
3. when the team user exists | |||
<pre> | |||
let(:team_user) { build(:team_user) } | |||
context 'the team user exists' do | |||
before :each do | |||
allow(TeamsUser).to receive(:where).with(user_id: 1).and_return([team_user]) | |||
AssignmentTeam.team(participant) | |||
end | |||
</pre> | |||
====Testing export_fields==== | |||
2 test cases are designed to test this method | |||
1. when the team_name equals false | |||
<pre> | |||
it 'the team_name equals false' do | |||
options = {:team_name =>"false"} | |||
expect(AssignmentTeam.export_fields(options)).to eq(["Team Name", "Team members","Assignment Name"]) | |||
end | |||
</pre> | |||
2. when the team_name equals true | |||
<pre> | |||
it 'the team_name equals true' do | |||
options = {:team_name =>"true"} | |||
expect(AssignmentTeam.export_fields(options)).to eq(["Team Name", "Assignment Name"]) | |||
end | |||
</pre> | |||
====Testing remove_team_by_id==== | |||
<pre> | |||
it 'send find to Assignment' do | |||
expect(AssignmentTeam).to receive(:find).with(1) | |||
AssignmentTeam.remove_team_by_id(1) | |||
end | |||
</pre> | |||
====Testing path==== | |||
<pre> | |||
it 'can get the path' do | |||
expect(assignment_team.path).to eq(Rails.root.to_s+'/pg_data/instructor6/csc517/test/final_test/0') | |||
assignment_team.path | |||
end | |||
</pre> | |||
====Testing set_student_directory_num==== | |||
3 test cases are designed to test this method | |||
1. when directory_num >= 0 | |||
<pre> | |||
context 'directory_num >= 0' do | |||
it 'return when num>=0' do | |||
expect(assignment_team.set_student_directory_num).to eq(nil) | |||
end | |||
end | |||
</pre> | |||
2. when the directory_num does not exist and it gets max num | |||
<pre> | |||
let(:assignment_team1) {build(:assignment_team, directory_num: nil)} | |||
it 'get max num' do | |||
expect(AssignmentTeam).to receive_message_chain(:where,:order,:first,:directory_num).with(parent_id: assignment_team1.parent_id).with('directory_num desc').with(no_args).with(no_args).and_return(1) | |||
assignment_team1.set_student_directory_num | |||
end | |||
</pre> | |||
3. when the directory_num does not exist and it updates attribute | |||
<pre> | |||
it 'update attribute' do | |||
allow(AssignmentTeam).to receive_message_chain(:where,:order,:first,:directory_num).with(parent_id: assignment_team1.parent_id).with('directory_num desc').with(no_args).with(no_args).and_return(1) | |||
expect(assignment_team1).to receive(:update_attributes).with(directory_num: 2) | |||
assignment_team1.set_student_directory_num | |||
end | |||
</pre> | |||
====Testing received_any_peer_review?==== | |||
<pre> | |||
it 'send the request to where of the ResponseMap' do | |||
expect(ResponseMap).to receive(:where).with(reviewee_id: assignment_team.id, reviewed_object_id: assignment_team.parent_id).and_return([]) | |||
assignment_team.received_any_peer_review? | |||
end</pre> | |||
==Test Coverage== | |||
There is screenshot of the coverage page. | |||
[https://drive.google.com/open?id=12jHYbHoL_MpjnM1tdy52DVjqasGmnHie] |
Latest revision as of 03:49, 11 November 2018
For this progect, the goal is to wirte up unit tests for assignment_team.rb
Project Introduction
Background
assignment_team.rb is the child class of team.rb. It is used to handle multiple problems relates to team in the assignment. Its responsibilities can mainly fall in three categories: participant of the team, reviews of the team, and the operation for the whole team. For the participant, it can be used to decide if a participant is in a given team and view the members of the team or remove a member. For reviews, it deals with the problem that getting the reviews for the team, assign reviewer for the team and get if the team has been reviewed by a specific reviewers. For the whole team, we can delete the team or view the scores, etc. by using this class.
Motivation
Make sure assignment_team.rb provides all functions as expected is important for the whole system. It requires enough tests for all the functions and the edge cases may occur. However, there are not enough unit tests for this model in expertiza. The following tests are added to assignment_team.rb in this project. To make sure we can cover as many conditions as we can(the objective for this project is getting at least 90% coverage rate), we first design test cases. The following factors are taking into considerations: the expected functions for each method, the possible edge cases and the pre-conditions for each cases. Then we get the unit test plan and complete the test following test steps.
Memebers of Project
Jianshu Zhang
Wanjing Kuang
Wei Wu
Mentor
Zhewei Hu
File Involvement
1.app/models/assignment_team.rb
2.spec/models/assignment_team_spec.rb
3.spec/factories/factories.rb
Test Plan
1. two test cases for method "include?": When the team includes a given participant and When the team doesn't include a given participant
2. one test case for method "parent_model": It returns "Assignment" when the method is called.
3. two test cases for method "self.parent_model(id)": When it's given a correct id and When it's given an incorrect id.
4. one test case for method "fullname": When the participant has an full name.
5. one test case for method "review_map_type": It returns ReviewResponseMap when the method is called.
6. one test case for method "self.prototype": It returns an new instance of AssignmentTeam when the method is called.
7. two test cases for method "assign_reviewer(reviewer)": When the team has an assignment and When the assignment record can not be found.
8. one test case for method "reviewd_by?": When it gets correct reviewer and returns true as an result.
9. one test case for method " topic": When it returns the correct id.
10. three test cases for method "has_submissions?": When the team doesn't submit any file or link, when team submits a link instead of files and when the team submits some files.
11. two test cases for method "participants": When no participants in this team and When adding some participants and get all the participants.
12. one test case for method "add_participant": When adding an participant, it will return an instance of AssignmentParticipant.
13. two test cases for method " delete and destroy": Testing delete and destory.
14. one test case for method "get_first_member": Let a team have two members, the first assigned member is expected to be returned by this method.
15. two test cases for method "hyoerlinks": the current teams submitted hyperlinks and not submitted the hyperlinks
16.three test cases for method "submit_hyperlink": the hyperlink is empty, the hyperlink is not empty and it calls the method on NET::HTTP,the hyperlink is not empty and it raises error
17.three test cases for method "team": the participant is nil, the participant exists and the team user exists
18.two test cases for method "export_files": an exception is expected if team is not exist or a new exported file is expected.
Unit Tests
Unit Test Tool
Rspec
Unit Test File
expertiza/spec/models/assignment_team_spec.rb
Unit Test Steps
- Create unit test cases in the assignment_team_spec.rb
- run rspec spec/models/assignment_team_spec.rb under expertiza directory
- the rspec outputs the number of test cases that are passed and those that are failed.
Unit Test Cases
Testing include?
2 test cases are designed to test this method:
1. The team includes a given participant.
let(:assignment_team) { build(:assignment_team, id: 1, parent_id: 1, name: "full name") } let(:participant1) { build(:participant, id: 2, user: user) } it "returns true" do allow(assignment_team).to receive(:add_participants).with(participant1) expect(assignment_team.includes?(participant1)) end
2. The team doesn't include a given participant.
let(:assignment_team) { build(:assignment_team, id: 1, parent_id: 1, name: "full name") } let(:participant1) { build(:participant, id: 2, user: user) } let(:participant2) { build(:participant, id: 3) } it "returns false" do allow(assignment_team).to receive(:add_participants).with(participant1) expect(assignment_team.includes?(participant2)) end
Testing parent_model
1 test case is designed to test this method:
it "returns Assignment as result" do expect(assignment_team.parent_model).to eq("Assignment") end
Testing self.parent_model(id)
2 test cases are designed to test this method:
1.When it's given a correct id.
let(:assignment) { build(:assignment, id: 1) } it "returns an assignemt" do allow(Assignment).to receive(:find).with(1).and_return(assignment) expect(AssignmentTeam.parent_model(1)).to eq(assignment) end
2.When it's given an incorrect id.
it "raises an exception" do expect { AssignmentTeam.parent_model 2 }.to raise_exception(ActiveRecord::RecordNotFound) end
Testing fullname
1 test case is designed to test this method:
it "returns the full name of assignment team" do expect(assignment_team.fullname).to eq("full name") end
Testing review_map_type
1 test case is designed to test this method:
it "returns ReviewResponseMap as result" do expect(assignment_team.review_map_type).to eq("ReviewResponseMap") end
Testing self.prototype
1 test cases is designed to test this method:
it "returns an new instance of AssignmentTeam" do expect(AssignmentTeam.prototype).to be_instance_of(AssignmentTeam) end
Testing assign_reviewer(reviewer)
2 test cases are designed to test this method:
1. When the team has an assignment.
let(:reviewer) { build(:participant, id: 1) } it "returns an instance of ReviewResponseMap" do expect(assignment_team.assign_reviewer(reviewer)).to be_instance_of(ReviewResponseMap) end
2. When the assignment record can not be found
let(:assignment_team2) { build(:assignment_team, id: 2, parent_id: 2) } it "returns an exception" do expect { assignment_team2.assign_reviewer(reviewer) }.to raise_exception(ActiveRecord::RecordNotFound) end
Testing reviewd_by?
1 test case is designed to test this method:
it "returns true" do allow(ReviewResponseMap).to receive(:where).\ with('reviewee_id = ? && reviewer_id = ? && reviewed_object_id = ?', 1, 1, 1).and_return([review_response_map]) expect(assignment_team.reviewed_by?(reviewer)).to be true end
Testing topic
1 test case is designed to test this method:
let(:signed_up_team) { build(:signed_up_team, id: 1, team_id: 1, is_waitlisted: 0, topic_id: 1) } it "returns a topic id" do allow(SignedUpTeam).to receive(:find_by).with(team_id: 1, is_waitlisted: 0).and_return(signed_up_team) expect(assignment_team.topic).to eq(1) end
Testing has_submissions?
3 test cases are designed to test this method:
1.The team doesn't submit any file or link.
let(:team2) { build(:assignment_team, id: 2, parent_id: 1, name: "team2", submitted_hyperlinks: "") } it "no file or no link" do expect(team2.has_submissions?).to eq(false) end
2.The team submits a link instead of files.
let(:team1) { build(:assignment_team, id: 1, parent_id: 1, name: "team1", submitted_hyperlinks: "http://example.com") } it "submitted hyperlinks" do expect(team1.has_submissions?).to eq(true) end
3. The team submits some files. Stub is used to emulate the scenario that the team has submitted a file.
it "returns true" do allow(team2).to receive(:submitted_files).and_return([double(:File)]) expect(team2.has_submissions?).to be true end
Testing participants
1. No participants in this team
it '#no participant' do expect(team1.participants).to eq([]) end
2. add some participants and get all the participants
let(:student1) { build(:student, id: 1, name: 'johns', fullname: 'johns franklin') } let(:student2) { build(:student, id: 2, name: 'kate', fullname: 'kate moss') } let(:par1) { build(:participant, id: 1, parent_id: 1, user_id: 1) } let(:par2) { build(:participant, id: 2, parent_id: 1, user_id: 2) } it '#1 participant' do allow(AssignmentTeam).to receive(:users).with(id: team1.id).and_return([student1,student2]) expect(team1.participants).to eq([par1, par2]) end
Testing add_participant
it '#add participants' do expect(team1.add_participant(ass1.id, par1)).to be_instance_of(AssignmentParticipant) end
Testing the delete and destroy
it '#delete' do expect(team1.delete).to be_instance_of(AssignmentTeam) end
it '#destroy' do expect(team1.destroy).to be_instance_of(AssignmentTeam) end
Testing members
it '#get_first_member' do allow(AssignmentTeam).to receive(:find_by).with(id: team1.id).and_return(team1) allow(team1).to receive(:participants).and_return([par1, par2]) expect(AssignmentTeam.get_first_member(team1.id)).to eq(par1) end
Testing import and export
1. import a team to a non-existing assignment and expect an exception
it '#import an nonexisting assignment id' do row = {teamname: "hello_world", teammembers: %w[johns kate]} options = {has_teamname: "true_first"} expect { AssignmentTeam.import(row, 99_999, options) }.to raise_error(ImportError) end
2. export teams into a csv file
it '#export' do options = {} csv = CSV.open("assignment_team_export.csv", "w") assignment_id = ass1.id allow(AssignmentTeam).to receive(:where).with(parent_id: assignment_id).and_return([team1, team2, team3]) allow(TeamsUser).to receive(:where).and_return([par1, par2]) expect(AssignmentTeam.export(csv, assignment_id, options)).to be_instance_of(CSV) end
Testing copy
it '#copy' do allow(TeamsUser).to receive(:where).with(team_id: team1.id).and_return([par1]) expect(team1.copy(course1.id)).to eq([par1]) end
Testing hyperlinks
2 test cases are designed to test this method:
1. when the current teams submitted hyperlinks
let(:assignment_team) { build(:assignment_team) } context "when current teams submitted hyperlinks" do it "returns the hyperlinks submitted by the team" do expect(assignment_team.hyperlinks).to eq(["https://www.expertiza.ncsu.edu"]) end end
2. when current teams did not submit hyperlinks
let(:team_without_submitted_hyperlinks) { build(:assignment_team, submitted_hyperlinks: "") } context "when current teams did not submit hyperlinks" do it "returns an empty array" do expect(team_without_submitted_hyperlinks.hyperlinks).to eq([]) end end
Testing files
before :each do @directory = "a" @files = ["b.txt", "c.java", "d.txt"] @files1 = ["b/c", "d/e"] end it "call the method in Dir" do expect(Dir).to receive(:[]).with(@directory + "/*").and_return(@files) assignment_team.files(@directory) end
Testing submit_hyperlink
3 test cases are designed to test this method:
1. when the hyperlink is empty
context "when the hyperlink is empty" do it "raise excpetion" do expect{(assignment_team.submit_hyperlink(""))}.to raise_error('The hyperlink cannot be empty!') end
2. when the hyperlink is not empty and it calls the method on NET::HTTP
before :each do @link = "htp.aa/.." end it "call the method on NET::HTTP" do expect(Net::HTTP).to receive(:get_response).with(URI(@link+'http://')) assignment_team.submit_hyperlink(@link) end
3. when the hyperlink is not empty and it raises error
it "raise error" do allow(Net::HTTP).to receive(:get_response).with(URI(@link+'http://')).and_return("402") expect{(assignment_team.submit_hyperlink(@link))}.to raise_error('HTTP status code: 402') end
Testing remove_hyperlink
before :each do @hyperlink = "http://a.com" end it 'call the hyperlinks method' do expect(assignment_team).to receive(:hyperlinks).and_return(["https://www.expertiza.ncsu.edu"]) assignment_team.remove_hyperlink(@hyperlink) end
Testing team
3 test cases are designed to test this method
1. when the participant is nil then this method will return nil
context 'when the participant is nil then this method will return nil' do it 'the participant is nil' do expect(AssignmentTeam.team(nil)).to eq(nil) end end
2. when it can find the participant
let(:participant) { build(:participant) } context 'can find the participant' do it 'send the correct user_id to the TeamsUser.where method' do expect(TeamsUser).to receive(:where).with(user_id: participant.user_id).and_return([team_user]) AssignmentTeam.team(participant) end
3. when the team user exists
let(:team_user) { build(:team_user) } context 'the team user exists' do before :each do allow(TeamsUser).to receive(:where).with(user_id: 1).and_return([team_user]) AssignmentTeam.team(participant) end
Testing export_fields
2 test cases are designed to test this method
1. when the team_name equals false
it 'the team_name equals false' do options = {:team_name =>"false"} expect(AssignmentTeam.export_fields(options)).to eq(["Team Name", "Team members","Assignment Name"]) end
2. when the team_name equals true
it 'the team_name equals true' do options = {:team_name =>"true"} expect(AssignmentTeam.export_fields(options)).to eq(["Team Name", "Assignment Name"]) end
Testing remove_team_by_id
it 'send find to Assignment' do expect(AssignmentTeam).to receive(:find).with(1) AssignmentTeam.remove_team_by_id(1) end
Testing path
it 'can get the path' do expect(assignment_team.path).to eq(Rails.root.to_s+'/pg_data/instructor6/csc517/test/final_test/0') assignment_team.path end
Testing set_student_directory_num
3 test cases are designed to test this method
1. when directory_num >= 0
context 'directory_num >= 0' do it 'return when num>=0' do expect(assignment_team.set_student_directory_num).to eq(nil) end end
2. when the directory_num does not exist and it gets max num
let(:assignment_team1) {build(:assignment_team, directory_num: nil)} it 'get max num' do expect(AssignmentTeam).to receive_message_chain(:where,:order,:first,:directory_num).with(parent_id: assignment_team1.parent_id).with('directory_num desc').with(no_args).with(no_args).and_return(1) assignment_team1.set_student_directory_num end
3. when the directory_num does not exist and it updates attribute
it 'update attribute' do allow(AssignmentTeam).to receive_message_chain(:where,:order,:first,:directory_num).with(parent_id: assignment_team1.parent_id).with('directory_num desc').with(no_args).with(no_args).and_return(1) expect(assignment_team1).to receive(:update_attributes).with(directory_num: 2) assignment_team1.set_student_directory_num end
Testing received_any_peer_review?
it 'send the request to where of the ResponseMap' do expect(ResponseMap).to receive(:where).with(reviewee_id: assignment_team.id, reviewed_object_id: assignment_team.parent_id).and_return([]) assignment_team.received_any_peer_review? end
Test Coverage
There is screenshot of the coverage page. [1]