CSC/ECE 517 Fall 2016/E1671. Unit Tests for participants.rb Hierarchy
This wiki page is for the description of changes made under E1671 OSS assignment for Fall 2016, 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 and complete assignments.
Problem
The participant, course_participant and assignment_pariticipant models does not have any unit tests.
Work to be Done
- Create a Factory for assignment participant and course participant model.
- Test the relationships and validations
- Write model spec for major instances
Files Modified/Created
- spec/factories/factories.rb
- spec/models/participant_spec.rb
- spec/models/assignment_participant_spec.rb
- spec/models/course_participant_spec.rb
Unit Test Description
Unit tests are used to test the functionality of methods in the model. These tests can be based on either test-driven development (TDD) or behavior-driven development (BDD). BDD is preferred for testing because it easy to understand compared to the more specialized TDD.<ref>https://www.toptal.com/freelance/your-boss-won-t-appreciate-tdd-try-bdd</ref> In this project, BDD is used to test the functionality using RSpec. RSpec is a testing tool for ruby using the BDD approach.<ref>https://semaphoreci.com/community/tutorials/getting-started-with-rspec</ref> Factories are used to populate the database before the tests are run.
Factories for the Given Classes
The factory for the Participant class is already present. The factories for the other two classes will be very similar. The only differentiating value will be type which can either equal AssignmentParticipant or CourseParticipant depending on the class. Below the factories for AssignmenmentParticipant and CourseParticipant are given.
factory :assignment_participant, class: AssignmentParticipant do can_submit true can_review true assignment { Assignment.first || association(:assignment) } association :user, factory: :student submitted_at nil permission_granted nil penalty_accumulated 0 grade nil type "AssignmentParticipant" handle "handle" time_stamp nil digital_signature nil duty nil can_take_quiz true end factory :course_participant, class: CourseParticipant do course { Course.first || association(:course) } can_submit true can_review true assignment { Assignment.first || association(:assignment) } association :user, factory: :student submitted_at nil permission_granted nil penalty_accumulated 0 grade nil type "CourseParticipant" handle "handle" time_stamp nil digital_signature nil duty nil can_take_quiz true end
Participant Unit Test
The Participant class is the base class for both the AssignmentParticipant class and the CourseParticipant class. We have used the rspec framework to test each of these three classes. The factory library used is Factory Girl and the factories themselves are located in factories.rb. Tests are usually centered around conditional statements, for example if there is a statement following a condition that evaluates to be true. Here it can be tested that the statement is always executed correctly when the condition evaluates to true.
The participant class is used to describe the participants of a university class. Unit tests for this class is written in the participant_spec.rb file. The first few unit tests defined are used to test the value of data members. There are also three unit tests to test the functionality of the fullname, topicname and name methods.
require 'rails_helper' describe Participant do before(:each) do @student = create(:student, name: "Student", fullname: "Student Test", email: "student1@gmail.com" , password: "123456", password_confirmation: "123456") @assignment = create(:assignment, name: "Assignment1", course: nil) @participant = create(:participant, parent_id: @assignment.id, user_id: @student.id) @assignment_questionnaire1 =create(:assignment_questionnaire, user_id: @student.id, assignment: @assignment) end it "is valid" do expect(@participant).to be_valid end it "can review" do expect(@participant.able_to_review).to be true end it "can submit" do expect(@participant.can_submit).to be true end it "can take quiz" do expect(@participant.can_take_quiz).to be true end it "has 0 penalty accumulated" do expect(@participant.penalty_accumulated).to be_zero end it "is type of assignment participant" do expect(@participant.type).to eql "AssignmentParticipant" end describe "#topicname" do it "returns the topic name" do expect(@participant.topic_name).to eql "<center>—</center>" end end describe "#name" do it "returns the name of the user" do expect(@participant.name).to eql "Student" end end describe "#fullname" do it "returns the full name of the user" do expect(@participant.fullname).to eql "Student Test" end end end
Assignment Participant Unit Test
The AssignmentParticipant class inherits from the Participant class. This first test is to validate whenever an object of AssignmentParticipant is created. Then there are three tests for the methods type, average_scores and copy. Lastly there are four unit tests defined to test the functionality of the method import. These tests can be found in assignment_participant_spec.rb.
require 'rails_helper' describe "AssignmentParticipant" do describe "validations" do before(:each) do @assignment_participant = build(:assignment_participant) end it "assignment participant is valid" do expect(@assignment_participant).to be_valid end end describe "#type" do it "checks if type is assignment participant" do assignment_participant = build(:assignment_participant) expect(assignment_participant.type).to eq("AssignmentParticipant") end end describe "#average_scores" do it "returns 0 if self.response_maps is empty" do assignment_participant = build(:assignment_participant) sum_scores = assignment_participant.average_score expect(sum_scores).to be_zero end end describe "#copy" do it "creates a copy if part is empty" do assignment_participant = build(:assignment_participant) course_part = assignment_participant.copy(0) expect(course_part).to be_an_instance_of(CourseParticipant) end end describe "#import" do it "raise error if record is empty" do row = [] expect {AssignmentParticipant.import(row,nil,nil,nil)}.to raise_error("No user id has been specified.") end it "raise error if record does not have enough items " do row = ["user_name","user_fullname","name@email.com"] expect {AssignmentParticipant.import(row,nil,nil,nil)}.to raise_error("The record containing #{row[0]} does not have enough items.") end it "raise error if assignment with id not found" do assignment = build(:assignment) session = {} row =[] allow(Assignment).to receive(:find).and_return(nil) allow(session[:user]).to receive(:id).and_return(1) row = ["user_name","user_fullname","name@email.com","user_role_name","user_parent_name"] expect {AssignmentParticipant.import(row,nil,session,2)}.to raise_error("The assignment with id \"2\" was not found.") end it "creates assignment participant form record if it does not exist" do assignment = build(:assignment) session = {} row =[] allow(Assignment).to receive(:find).and_return(assignment) allow(session[:user]).to receive(:id).and_return(1) row = ["user_name","user_fullname","name@email.com","user_role_name","user_parent_name"] assign_part = AssignmentParticipant.import(row,nil,session,2) expect(assign_part).to be_truthy end end end
Course Participant Unit Test
The Course Participant class is to show the participation of the student into a particular course. The course participant class is inherited from the participant class associated with the course class through belongs_to relationship. We have tested the four different methods of the class course participant. These tests are found in the course_participant_spec.rb file. The first method to test is the copy method. The copy method checks if an assignment participant exists for the corresponding parent_id. If it exists then a null is returned otherwise a new object for assignment participant is returned. We check both the functionality of the methods using two different tests for the method class. The next important method is the import method. The import method consists of four different scenarios and thus we have written test for testing four different scenarios for the import method. The import method takes a record field and input and checks for various condition on the record field and creates the course participant object. Below is a short snipped of the various tests written for the copy and import method
describe "#copy" do it "create a copy of participant" do assignment = build(:assignment) course_participant = build(:course_participant) assign_part = build(:assignment_participant) allow(AssignmentParticipant).to receive(:create).and_return(assign_part) allow(assign_part).to receive(:set_handle).and_return(true) expect(course_participant.copy(assignment.id)).to be_an_instance_of(AssignmentParticipant) end it "returns nil if copy exist" do assignment = build(:assignment) course_participant = build(:course_participant) assign_part = build(:assignment_participant) allow(AssignmentParticipant).to receive(:where).and_return(AssignmentParticipant) allow(AssignmentParticipant).to receive(:first).and_return(assign_part) allow(assign_part).to receive(:set_handle).and_return(true) expect(course_participant.copy(assignment.id)).to be_nil end end
describe "#import" do it "raise error if record is empty" do row = [] expect {CourseParticipant.import(row,nil,nil,nil)}.to raise_error("No user id has been specified.") end it "raise error if record does not have enough items " do row = ["user_name","user_fullname","name@email.com"] expect {CourseParticipant.import(row,nil,nil,nil)}.to raise_error("The record containing #{row[0]} does not have enough items.") end it "raise error if course with id not found" do course = build(:course) session = {} row =[] allow(Course).to receive(:find).and_return(nil) allow(session[:user]).to receive(:id).and_return(1) row = ["user_name","user_fullname","name@email.com","user_role_name","user_parent_name"] expect {CourseParticipant.import(row,nil,session,2)}.to raise_error("The course with the id \"2\" was not found.") end it "creates course participant form record" do course = build(:course) session = {} row =[] allow(Course).to receive(:find).and_return(course) allow(session[:user]).to receive(:id).and_return(1) row = ["user_name","user_fullname","name@email.com","user_role_name","user_parent_name"] course_part = CourseParticipant.import(row,nil,session,2) expect(course_part).to be_an_instance_of(CourseParticipant) end end
Run the Test
The tests can be run on the terminal from inside the expertiza folder using following commands:
For participant:
rspec spec/models/participant_spec.rb
For assignment_participant:
rspec spec/models/assignment_participant_spec.rb
For participant:
rspec spec/models/assignment_participant_spec.rb
External Links
https://github.com/hsy12321/expertiza
References
<references />