CSC/ECE 517 Fall 2018/E1852 Unit Test for Participant Model
Expertiza
Expertiza is a web application designed for academia. The users of this application are instructors and students. A user as an instructor can create new assignments as well as customize existing assignments for students. Students can submit assignments, view assignment deadlines, bid for assignment topic, create a team and peer-review learning objects (articles, code, websites, etc).
Steps for Implementation
Plan of Work
The task is to write unit test cases for testing the participant model file. The Rspec file participant_spec.rb existed with test cases for name and fullname methods and provided path coverage of 36.08% for the participant model. The procedure for project planning included :-
1. Setting the Expertiza environment.
2. Understand the functionality of model file in participant.rb
3. Understand the linked data attributes being used, like assignment, topic, questionnaire
4. Writing testing conditions for different functions.
Setting the Expertiza environment
1. Reserve a NCSU VCL image of [CSC517, S18] Ruby on Rails / Expertiza.
2. Connect to the reservation using SSH and enter your campus credentials for User ID and password.
3. Commands executed for setup in terminal of VCL image:
sudo su gem install bundler exit git clone [Your forked Expertiza repo url] cd expertiza bash setup.sh (change config/database.yml, there is no MySQL password by default) bundle install rails server
Test Cases
TASKS IDENTIFIED
Test team
A Participant can be a member of a Team. When team method is called on a Participant, it should return the Team it belongs to.
describe "#team" do it "returns the team id for the user" do expect(participant.team).to eq(nil) end end
Test responses
A Participant has many ResponseMaps that map a connection between this participant as a reviewer and as a reviewee. Each ResponseMap has many Responses associated with it. When responses method is called on a Participant, it should return an array of responses associated to this Participant.
def responses response_maps.map(&:response) end
The test below will test a participant with no corresponding mapping. Hence the result of the responses provided by the participant is a nil list
describe '#responses' do it 'returns an array of responses of the participant' do expect(participant.responses).to eql([]) end end
Test name
The method name returns the name of the participants
def name(ip_address = nil) self.user.name(ip_address) end
The test below will return the name of the participant. A factory build initializes the participant with the name as student and calls the function to expect student as the outcome
describe "#name" do it "returns the name of the user" do expect(participant.name).to eq "Student" end end
A Participant is a User. When name method is called on a Participant, it should return the name of this User.
Link title
Test fullname
A Participant is a User. When fullname method is called on a Participant, it should return the full name of this User.
def fullname(ip_address = nil) self.user.fullname(ip_address) end
The test is done similar to name that it expects a name which was loaded in the factory build
describe "#name" do it "returns the name of the user" do expect(participant.name).to eq "Student" end end
Test handle
def handle(ip_address = nil) User.anonymized_view?(ip_address) ? 'handle' : self[:handle] end
Test delete
def delete(force = nil) maps = ResponseMap.where('reviewee_id = ? or reviewer_id = ?', self.id, self.id) if force or (maps.blank? and self.team.nil?) force_delete(maps) else raise "Associations exist for this participant." end end
Test force_delete
def force_delete(maps) maps and maps.each(&:destroy) if self.team and self.team.teams_users.length == 1 self.team.delete elsif self.team self.team.teams_users.each {|teams_user| teams_user.destroy if teams_user.user_id == self.id } end self.destroy end
Test topic_name
describe '#topic_name' do context 'when the participant has an assignment without a topic' do it 'returns error message' do expect(participant.topic_name).to eql('<center>—</center>') end end
Test able_to_review
def able_to_review can_review end
When able_to_review method is called on a Participant, it should return true if it can review and false otherwise.
When scores method is called on a Participant, it should return the total scores it received for a given number of questions.
Test get_permissions
This method returns a hash of the boolean value based on the authorization. The result of the boolean determined the ability to review , take quiz and submit.
def self.get_permissions(authorization) can_submit = true can_review = true can_take_quiz = true case authorization when 'reader' can_submit = false when 'reviewer' can_submit = false can_take_quiz = false when 'submitter' can_review = false can_take_quiz = false end {can_submit: can_submit, can_review: can_review, can_take_quiz: can_take_quiz} end
The test case here checks whether the output hash will have the correct combination of trues and false for the authorization
describe '.get_permissions' do context 'when current participant is authorized as reader' do it 'participant cannot submit' do expect(Participant.get_permissions('reader')).to eql({ :can_submit => false, :can_review => true, :can_take_quiz => true}) end end context 'when current participant is authorized as reviewer' do it 'participant can only review' do expect(Participant.get_permissions('reviewer')).to eql({ :can_submit => false, :can_review => true, :can_take_quiz => false}) end end context 'when current participant is authorized as submitter' do it 'participant can only submit' do expect(Participant.get_permissions('submitter')).to eql({ :can_submit => true, :can_review => false, :can_take_quiz => false}) end end end
Test get_authorization
The method get authorization basically determies the role based on the ability to submit, review and take quiz
def self.get_authorization(can_submit, can_review, can_take_quiz) authorization = 'participant' authorization = 'reader' if can_submit == false and can_review == true and can_take_quiz == true authorization = 'submitter' if can_submit == true and can_review == false and can_take_quiz == false authorization = 'reviewer' if can_submit == false and can_review == true and can_take_quiz == false authorization end
The test cases below are designed to validate whether the method produced the 3 desired outcomes.
The first test case validates the outcome to be reader, second one check for the outcome submitter and third will check if its a reviewer
describe ".get_authorization" do it "returns authorization as reader when input is true for can_review and can_take quiz" do expect(Participant.get_authorization(false, true, true )).to eq('reader') end it "returns authorization submitter when input is true only for can_submit" do expect(Participant.get_authorization(true, false, false)).to eq('submitter') end it "returns authorization as reviewer when the input is true for only for can_review" do expect(Participant.get_authorization(false, true, false)).to eq('reviewer') end end
Test sort_by_name
def self.sort_by_name(participants) users = [] participants.each {|p| users << p.user } users.sort! {|a, b| a.name.downcase <=> b.name.downcase } # Sort the users based on the name participants.sort_by {|p| users.map(&:id).index(p.user_id) } end
Participants are Users. When self.sort_by_name method is called on a Participant, it should sort a given set of participants based on their user names.