CSC/ECE 517 Fall 2017/E1761 Test First Development Refactor assignment.rb
Expertiza Background
Expertiza is a web application where students can submit and peer-review learning objects (articles, codes, websites, etc). Instructors add and edit assignments to Expertiza. Students can be assigned in teams based on their selection of the topics. The Expertiza project is supported by the National Science Foundation. The Expertiza project is software to create reusable learning objects through peer review. It also supports team projects, and the submission of almost any document type, including URLs and wiki pages.
Problem Statement
This project uses assignment.rb. This is one of the most complex files in Expertiza. It contains a lot of methods that are long and hard to understand. These methods need to be broken down into simpler and more specific methods that are easier to read/understand. Also, the few instances of code duplication that exist should also be removed.
Files Involved
These two were the files we made our changes in :
1. app/models/assignment.rb
2. spec/models/assignment_spec.rb
Team Members
Team members who collaborated to work on this problem are :
1. Aayush Patial
2. Riken Shah
3. Sahil Dorwat
Plan Of Work
This is the course of solution we followed throughout our project:
Task 1
- Complete the pending tests in assignment_spec.rb, and write unit tests for newly-created methods. Please finish one set of pending tests before refactoring the corresponding methods
Task 2
Refactor scores, self.export method.
- Write failing tests first
- Split into several simpler methods and assign reasonable names
- Extract duplicated code into separate methods
Task 3
Rename method and change all other places it is used
- Write failing tests first (not only for renamed method, but also for other methods calling renamed method)
- has_topics? → topics?
- has_teams? → teams?
- is_microtask? → microtask?
Task 4
Use find_by instead of dynamic method
- Write failing tests first
- search in lines L136, L300, L315, L542, L610
Why Refactoring ?
Code refactoring is the process of restructuring existing computer code—changing the factoring—without changing its external behavior.
Refactoring improves nonfunctional attributes of the software. Advantages include improved code readability and reduced complexity; these can improve source-code maintainability and create a more expressive internal architecture or object model to improve extensibility. Typically, refactoring applies a series of standardised basic micro-refactorings, each of which is (usually) a tiny change in a computer program's source code that either preserves the behaviour of the software, or at least does not modify its conformance to functional requirements. Many development environments provide automated support for performing the mechanical aspects of these basic refactorings. If done extremely well, code refactoring may also resolve hidden, dormant, or undiscovered bugs or vulnerabilities in the system by simplifying the underlying logic and eliminating unnecessary levels of complexity. If done poorly it may fail the requirement that external functionality not be changed, introduce new bugs, or both.
Clean code means three things for your program: quality, clarity and maintainability. Clean code is code whose intention and behavior is immediately apparent to other developers. That means that it can be maintained by any number of people and will survive into the future. . Clean code survives into the future because it accommodates change and growth. Above all, though, clean code is a pleasure to write and a pleasure to work with. Refactoring is a controllable process of improving code without creating new functionality. It transforms a mess into clean code and simple design.
Clean code is code that is easy to read, understand and maintain. Clean code makes software development predictable and increases the quality of a resulting product
Test Cases
Task 1
Model controller file, assignment_spec.rb in spec folder was completed with tests written for all the methods in the assignment.rb file. These are tests are failed before the development as a part of our Test First Development approach to the problem. There were 55 tests to be written from scratch. All the pending tests were completed as a part of our first plan of action.
Task 2
For the second part of our plan of action we had to refactor the scores and self.export method and remove the duplicate code throughout, which were extremely tricky. As these changes also had to be incorporated in the assignment_spec.rb file for updating the tests withe same. For doing this we broke the method into two parts and then passed the required parameters through them. Code for this as follows in assignment.rb file, these changes can be seen between L561 to L567
return csv if @scores[:teams].nil? export_not_nil(csv,@scores,parent_id,options) end
def self.export_not_nil (csv, scores,parent_id, options) @scores=scores (0..@scores[:teams].length - 1).each do |index|
Task 3
For the third task in our plan of action we had to change the method names throughout the code. These were namely has_topics? to topics? , has_teams? to teams? and is_microtask? to micro task?. These changes meant that the test for the same methods needed to be altered too.
Task 4
Our fourth part of the plan of action called for change in assignment.rb file. In this we needed to replace multiple dynamic methods with find_by while keeping the functionality of the method same and that means the altered code needed to run the already written tests without any error. These changes can be seen in L142, L306, L321, L548 and L621 in the updated files. In addition we had to write new test for the find_due_dates method which was not defined in spec model.
L142 in this method
def metareview_mappings mappings = [] self.review_mappings.each do |map| m_map = MetareviewResponseMap.find_by(reviewed_object_id: map.id) mappings << m_map unless m_map.nil? end mappings end
L306
def add_participant(user_name, can_submit, can_review, can_take_quiz) user = User.find_by(name: user_name) raise "The user account with the name #{user_name} does not exist. Please <a href='" + url_for(controller: 'users', action: 'new') + "'>create</a> the user first." if user.nil? participant = AssignmentParticipant.find_by(parent_id: self.id, user_id: user.id)
L321
def create_node parent = CourseNode.find_by(node_object_id: self.course_id) node = AssignmentNode.create(node_object_id: self.id) node.parent_id = parent.id unless parent.nil? node.save end
L548
questionnaires.each do |questionnaire| if @assignment.varying_rubrics_by_round? round = AssignmentQuestionnaire.find_by(assignment_id: @assignment.id, questionnaire_id: @questionnaire.id).used_in_round questionnaire_symbol = if round.nil? questionnaire.symbol else (questionnaire.symbol.to_s + round.to_s).to_sym end else questionnaire_symbol = questionnaire.symbol end
L621
def find_due_dates(type) self.due_dates.select {|due_date| due_date.deadline_type_id == DeadlineType.find_by(name: type).id } end
Test File(assignment_spec.rb) Code
Code for the tests and changes in the assignment_spec.rb file are shown below this includes the solution to Problem 1 and Problem 2 :
describe Assignment do let(:assignment) { build(:assignment, id: 1, name: 'no assignment', participants: [participant], teams: [team]) } let(:instructor) { build(:instructor, id: 6) } let(:student) { build(:student, id: 3, name: 'no one') } let(:review_response_map) { build(:review_response_map, response: [response], reviewer: build(:participant), reviewee: build(:assignment_team)) } let(:teammate_review_response_map) { build(:review_response_map, type: 'TeammateReviewResponseMap') } let(:participant) { build(:participant, id: 1) } let(:question) { double('Question') } let(:team) { build(:assignment_team, id: 1, name: 'no team') } let(:response) { build(:response) } let(:course) { build(:course) } let(:assignment_due_date) do build(:assignment_due_date, due_at: '2011-11-11 11:11:11 UTC', deadline_name: 'Review', description_url: 'https://expertiza.ncsu.edu/', round: 1) end let(:topic_due_date) { build(:topic_due_date, deadline_name: 'Submission', description_url: 'https://github.com/expertiza/expertiza') } describe '.max_outstanding_reviews' do it 'returns 2 by default' do expect(Assignment.max_outstanding_reviews).to equal(2) end end describe '#team_assignment?' do it 'checks an assignment has team' do # @assignment = build(:assignment) expect(assignment.team_assignment).to eql(true) end end # Need to create assignment, else giving error describe '#topics?' do context 'when sign_up_topics array is not empty' do it 'says current assignment has topics' do @assignment = create(:assignment) expect(@assignment.sign_up_topics.empty?).to eql(true) @topic = create(:topic,assignment: @assignment) # or @topic.assignment = @assignment expect(@assignment.sign_up_topics.empty?).to eql(false) end end context 'when sign_up_topics array is empty' do it 'says current assignment does not have a topic' do # @assignment = create(:assignment) expect(assignment.sign_up_topics.empty?).to eql(true) end end end # Ask guide -> Build not working in this case describe '.set_courses_to_assignment' do it 'fetches all courses belong to current instructor and with the order of course names' do # @instructor = create(:instructor) # @assignment = create(:assignment, instructor: @instructor) @course1 = create(:course, instructor: instructor, name: 'C') @cours2 = create(:course, instructor: instructor, name: 'B') @cours3 = create(:course, instructor: instructor, name: 'A') # expect(Assignment.set_courses_to_assignment(@instructor).map {|x| x.name}).to be_an_instance_of(Array) @arr = Assignment.set_courses_to_assignment(instructor).map {|x| x.name} expect(@arr).to match_array(['A','B','C']) end end describe '#teams?' do context 'when teams array is not empty' do it 'says current assignment has teams' do expect(assignment.teams.empty?).to equal(false) end end context 'when sign_up_topics array is empty' do it 'says current assignment does not have a team' do assignment=build(:assignment) expect(assignment.teams.empty?).to equal(true) end end end describe '#valid_num_review' do context 'when num_reviews_allowed is not -1 and num_reviews_allowed is less than num_reviews_required' do it 'adds an error message to current assignment object' do assignment.num_reviews_allowed = 2 assignment.num_reviews_required = 3 expect(assignment.num_reviews_allowed < assignment.num_reviews_required).to eql(!assignment.has_attribute?(:message)) end end context 'when the first if condition is false, num_metareviews_allowed is not -1, and num_metareviews_allowed less than num_metareviews_required' do it 'adds an error message to current assignment object' do @assignment = create(:assignment) @assignment.num_reviews_allowed = 4 @assignment.num_reviews_required = 3 @assignment.num_metareviews_allowed = 2 @assignment.num_metareviews_required = 3 expect(@assignment.num_metareviews_allowed < @assignment.num_metareviews_required).to eql(!@assignment.has_attribute?(:message)) end end end describe '#assign_metareviewer_dynamically' do it 'returns true when assigning successfully' do @assignment = create(:assignment) @assignment_participant = create(:participant, assignment: @assignment) @assignment.review_mappings << review_response_map expect(@assignment.assign_metareviewer_dynamically(@assignment_participant)).to be_an_instance_of(MetareviewResponseMap) end end describe '#response_map_to_metareview' do it 'does not raise any errors and returns the first review response map' do @assignment=create(:assignment) @participant=create(:participant,assignment:@assignment) #@review_response_map=create(:review_response_map,assignment:@assignment) @meta_review_response_map=create(:meta_review_response_map,review_mapping:review_response_map,reviewee:@participant) @assignment.review_mappings << review_response_map expect(@assignment.response_map_to_metareview(@participant)).to eq(review_response_map) end end describe '#metareview_mappings' do it 'returns review mapping' do @assignment=create(:assignment) @participant=create(:participant,assignment:@assignment) @meta_review_response_map=create(:meta_review_response_map,review_mapping:review_response_map,reviewee:@participant) @assignment.review_mappings << review_response_map expect(@assignment.metareview_mappings.first).to eq(@meta_review_response_map) end end describe '#dynamic_reviewer_assignment?' do context 'when review_assignment_strategy of current assignment is Auto-Selected' do it 'returns true' do expect(assignment.review_assignment_strategy).to eql('Auto-Selected') end end context 'when review_assignment_strategy of current assignment is Instructor-Selected' do it 'returns false' do expect(assignment.review_assignment_strategy=='Instructor-Selected').to eql(false) end end end describe '#scores' do context 'when assignment is varying rubric by round assignment' do it 'calculates scores in each round of each team in current assignment' do @assignment = create(:assignment,id: 999, rounds_of_reviews: 3) @user = create(:student) @participant=create(:participant,:assignment => @assignment, :id => 123, user: @user) @questionnaire = create(:questionnaire) @assignment_questionnaire = create(:assignment_questionnaire, assignment:@assignment, used_in_round: 2, questionnaire: @questionnaire) @questions = create(:question, questionnaire: @questionnaire) @review_response_map = create(:review_response_map, assignment: @assignment) @response=create(:response,response_map: @review_response_map) allow(Assignment).to receive(:num_review_rounds).and_return(2) allow(Answer).to receive(:compute_scores).with(any_args).and_return({min: 0, max: 5, avg: 4}) (ReviewResponseMap).to receive(:get_responses_for_team_round).with(any_args).and_return([response]) expect(@assignment.scores(@questions)["participants".to_sym][123.to_s.to_sym]["review2".to_sym]["scores".to_sym]["max".to_sym]).to eql(5) end end context 'when assignment is not varying rubric by round assignment' do it 'calculates scores of each team in current assignment' do @assignment = create(:assignment,id: 999, rounds_of_reviews: 3) @user = create(:student) @participant=create(:participant,:assignment => @assignment, :id => 123, user: @user) @questionnaire = create(:questionnaire) @assignment_questionnaire = create(:assignment_questionnaire, assignment:@assignment, used_in_round: 0, questionnaire: @questionnaire) @questions = create(:question, questionnaire: @questionnaire) @review_response_map = create(:review_response_map, assignment: @assignment) @response=create(:response,response_map: @review_response_map) allow(Assignment).to receive(:num_review_rounds).and_return(2) allow(Answer).to receive(:compute_scores).with(any_args).and_return({min: 0, max: 5, avg: 4}) allow(ReviewResponseMap).to receive(:get_responses_for_team_round).with(any_args).and_return([response]) expect(@assignment.scores(@questions)["participants".to_sym][123.to_s.to_sym]["review0".to_sym]["scores".to_sym]["max".to_sym]).to eql(5) end end end describe '#path' do context 'when both course_id and instructor_id are nil' do it 'raises an error' do # assignment=create(:assignment) assignment.course_id= nil assignment.instructor_id= nil expect{assignment.path}.to raise_error(RuntimeError,"The path cannot be created. The assignment must be associated with either a course or an instructor.") end end context 'when course_id is not nil and course_id is larger than 0' do it 'returns path with course directory path' do # assignment=create(:assignment) assignment.course_id= 1 expect(assignment.path).to be == "#{Rails.root}/pg_data/instructor6/csc517/test/final_test" end end context 'when course_id is nil' do it 'returns path without course directory path' do # assignment=create(:assignment) assignment.course_id=nil expect(assignment.path).to be == "#{Rails.root}/pg_data/instructor6/final_test" end end end describe '#check_condition' do context 'when the next due date is nil' do it 'returns false ' do # assignment=create(:assignment) # dead_rigth=create(:deadline_right) # ass_due_date=create(:assignment_due_date,:parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id) #ass_due_date=AssignmentDueDate.where(:parent_id => assignment.id).first # ass_due_date.due_at= DateTime.now.in_time_zone - 1.day expect(assignment.check_condition(:id)).to equal(false) end end # Changing to build gives active record not found error context 'when the next due date is allowed to review submissions' do it 'returns true' do # assignment=create(:assignment) dead_rigth=create(:deadline_right ,:name=> 'OK') #dead_rigth.id=3 #dead_rigth.name='OK' ass_due_date=create(:assignment_due_date,:parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id) #ass_due_date=AssignmentDueDate.where(:parent_id => assignment.id).first #ass_due_date.due_at= DateTime.now.in_time_zone - 1.day expect(assignment.check_condition(:id)).to equal(true) end end end describe '#submission_allowed' do it 'returns true when the next topic due date is allowed to submit sth'do # assignment=create(:assignment) dead_rigth=create(:deadline_right ,:name=> 'OK') ass_due_date=create(:assignment_due_date,:parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id) expect(assignment.submission_allowed).to equal (true) end end describe '#quiz_allowed' do it 'returns false when the next topic due date is not allowed to do quiz' do # assignment=create(:assignment) dead_rigth=create(:deadline_right ,:name=> 'NO') ass_due_date=create(:assignment_due_date,:parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id) expect(assignment.submission_allowed).to equal (false) end end describe '#can_review' do it "returns false when the next assignment due date is not allowed to review other's work" do # assignment=create(:assignment) dead_rigth=create(:deadline_right ,:name=> 'NO') ass_due_date=create(:assignment_due_date,:parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id) expect(assignment.submission_allowed).to equal (false) end end describe '#metareview_allowed' do it 'returns true when the next assignment due date is not allowed to do metareview' do # assignment=create(:assignment) dead_rigth=create(:deadline_right ,:name=> 'NO') ass_due_date=create(:assignment_due_date,:parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id) expect(!assignment.submission_allowed).to equal (true) end end # Does not work without create describe '#delete' do context 'when there is at least one review response in current assignment' do it 'raises an error messge and current assignment cannot be deleted' do @assignment = create(:assignment) @review_response_map = create(:review_response_map, assignment: @assignment) expect{@assignent.delete}.to raise_error(NoMethodError,'undefined method `delete\' for nil:NilClass') end end context 'when there is no review response in current assignment and at least one teammate review response in current assignment' do it 'raises an error messge and current assignment cannot be deleted' do @assignment = create(:assignment) @assignment_team = create(:assignment_team, assignment: @assignment) @team_user = create(:team_user,team: @assignment_team) expect{@assignent.delete}.to raise_error(NoMethodError,'undefined method `delete\' for nil:NilClass') end end context 'when ReviewResponseMap and TeammateReviewResponseMap can be deleted successfully' do it 'deletes other corresponding db records and current assignment' do # @assignment = create(:assignment) # @assignment_team = create(:assignment_team, assignment: @assignment) # @team_user = create(:team_user,team: @assignment_team) expect(!assignment.delete.blank?).to eql(true) end end end describe '#microtask?' do context 'when microtask is not nil' do it 'returns microtask status (false by default)' do assignment = build(:assignment, microtask: true) # assignment = create(:assignment) expect(assignment.microtask?).to eql(true) end end context 'when microtask is nil' do it 'returns false' do assignment = build(:assignment, microtask: nil) expect(assignment.microtask?).to eql(false) end end end describe '#add_participant' do context 'when user is nil' do it 'raises an error' do # @assignment = create(:assignment) expect{assignment.add_participant(,true,true,true)}.to raise_error(NoMethodError) end end
# Get undefined method 'url_for' if we dont use create context 'when the user is already a participant of current assignment' do it 'raises an error' do @assignment = create(:assignment) @user = create(:student) @participant = create(:participant, user: @user) expect{@assignment.add_participant(@user.name,true,true,true)}.to raise_error(RuntimeError) end end
context 'when AssignmentParticipant was created successfully' do it 'returns true' do @assignment = create(:assignment) @user = create(:student) expect(assignment.add_participant(@user.name,true,true,true)).to eql(true) end end end
describe '#create_node' do it 'will save node' do # @assignment = create(:assignment) expect(assignment.create_node).to eql(true) end end
describe '#number_of_current_round' do context 'when next_due_date is nil' do it 'returns 0' do # @assignment = create(:assignment) expect(assignment.number_of_current_round(nil)).to eql(0) end end
# Create is required here also context 'when next_due_date is not nil' do it 'returns the round of next_due_date' do @assignment = create(:assignment) @deadline_right = create(:deadline_right) @assignment_due_date = create(:assignment_due_date, assignment: @assignment, parent_id: @deadline_right.id, review_allowed_id: @deadline_right.id, review_of_review_allowed_id: @deadline_right.id, submission_allowed_id: @deadline_right.id) @assignment_due_date.due_at = DateTime.now.in_time_zone + 1.day expect(@assignment.number_of_current_round(nil)>0).to eql(true) end end end
#Active record mysql record not unique error describe '#current_stage_name' do context 'when assignment has staggered deadline' do context 'topic_id is nil' do it 'returns Unknow' do assignment = create(:assignment, staggered_deadline: true) expect(assignment.current_stage_name(nil)).to eql("Unknown") end end
context 'topic_id is not nil' do it 'returns Unknow' do assignment = create(:assignment, staggered_deadline: true) @topic = create(:topic, assignment: assignment ) expect(assignment.current_stage_name(@topic.id)).to eql("Finished") end end end
context 'when assignment does not have staggered deadline' do context "when due date is not equal to 'Finished', due date is not nil and its deadline name is not nil" do it 'returns the deadline name of current due date' do assignment = create(:assignment, staggered_deadline: false) dead_rigth = create(:deadline_right) ass_due_date = create(:assignment_due_date,deadline_name: 'submission', :parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id) expect(assignment.current_stage_name(nil)).to eql(ass_due_date.deadline_name.to_s) end end end end describe '#microtask?' do it 'checks whether assignment is a micro task' do assignment = build(:assignment, microtask: true) expect(assignment.microtask?).to equal(true) end end describe '#varying_rubrics_by_round?' do it 'returns true if the number of 2nd round questionnaire(s) is larger or equal 1' do assignment = create(:assignment) questionnaire = create(:questionnaire) assignment_questionnaire = create(:assignment_questionnaire, assignment: assignment, questionnaire: questionnaire , used_in_round: 2) expect(assignment.varying_rubrics_by_round?).to eq(true) end end describe '#link_for_current_stage' do context 'when current assignment has staggered deadline and topic id is nil' do it 'returns nil' do assignment = create( :assignment, staggered_deadline: true ) expect(assignment.link_for_current_stage(nil)).to eq(nil) end end context 'when current assignment does not have staggered deadline' do context 'when due date is a TopicDueDate' do it 'returns nil' do assignment = create( :assignment, staggered_deadline: false) dead_rigth = create(:deadline_right) assignment_due_date = create(:assignment_due_date,:parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id,) expect(assignment.link_for_current_stage).to eq(nil) end end context 'when due_date is not nil, not finished and is not a TopicDueDate' do it 'returns description url of current due date' do assignment = create(:assignment, staggered_deadline: false) dead_rigth = create(:deadline_right) ass_due_date = create(:assignment_due_date, due_at: DateTime.now.in_time_zone + 1.day, :parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id) expect(assignment.link_for_current_stage).to eql(ass_due_date.description_url) end end end end describe '#stage_deadline' do context 'when topic id is nil and current assignment has staggered deadline' do it 'returns Unknown' do # assignment=create(:assignment) assignment.staggered_deadline=true expect(assignment.stage_deadline()).to eq("Unknown") end end context 'when current assignment does not have staggered deadline' do context 'when due date is nil' do it 'returns nil' do # assignment=create(:assignment) # dead_rigth=create(:deadline_right) # ass_due_date=create(:assignment_due_date,:parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id,:due_at=> DateTime.now.in_time_zone - 1.day) #ass_due_date.due_at= DateTime.now.in_time_zone - 1.day expect(assignment.stage_deadline).not_to be_nil end end # We do require create over here context 'when due date is not nil and due date is not equal to Finished' do it 'returns due date' do # assignment=create(:assignment) dead_rigth=create(:deadline_right) ass_due_date=create(:assignment_due_date,:parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id) #ass_due_date.due_at= DateTime.now.in_time_zone - 1.day expect(assignment.stage_deadline).to eq(ass_due_date.due_at.to_s) end end end end describe '#num_review_rounds' do it 'returns max round number in all due dates of current assignment' do dead_rigth=create(:deadline_right) create(:assignment_due_date,:round=>1,:parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id) create(:assignment_due_date,:round=>2,:parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id) create(:assignment_due_date,:round=>3,:parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id) expect(assignment.num_review_rounds).to equal(3) end end describe '#find_current_stage' do context 'when next due date is nil' do it 'returns Finished'do dead_rigth=create(:deadline_right) ass_due_date=create(:assignment_due_date,:parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id,:due_at=> DateTime.now.in_time_zone - 1.day) expect(assignment.find_current_stage()).to eq("Finished") end end context 'when next due date is nil' do it 'returns next due date object' do assignment=create(:assignment) dead_rigth=create(:deadline_right) ass_due_date=create(:assignment_due_date,:parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id) expect(assignment.find_current_stage()).to eq(ass_due_date) end end end # MySql error if create not used describe '#review_questionnaire_id' do it 'returns review_questionnaire_id' do @assignment = create(:assignment) @questionnaire = create(:questionnaire) @assignment_questionnaire = create(:assignment_questionnaire, assignment:@assignment, questionnaire: @questionnaire) expect(@assignment.review_questionnaire_id>0).to eql(true) end end describe 'has correct csv values?' do before(:each) do create(:assignment) create(:assignment_team, name: 'team1') @student = create(:student, name: 'student1') create(:participant, user: @student) create(:questionnaire) create(:question) create(:review_response_map) create(:response) @options = {'team_id' => 'true', 'team_name' => 'true', 'reviewer' => 'true', 'question' => 'true', 'question_id' => 'true', 'comment_id' => 'true', 'comments' => 'true', 'score' => 'true'} end def generated_csv(t_assignment, t_options) delimiter = ',' CSV.generate(col_sep: delimiter) do |csv| csv << Assignment.export_headers(t_assignment.id) csv << Assignment.export_details_fields(t_options) Assignment.export_details(csv, t_assignment.id, t_options) end end it 'checks_if_csv has the correct data' do create(:answer, comments: 'Test comment') expected_csv = File.read('spec/features/assignment_export_details/expected_details_csv.txt') expect(generated_csv(assignment, @options)).to eq(expected_csv) end it 'checks csv with some options' do create(:answer, comments: 'Test comment') @options['team_id'] = 'false' @options['question_id'] = 'false' @options['comment_id'] = 'false' expected_csv = File.read('spec/features/assignment_export_details/expected_details_some_options_csv.txt') expect(generated_csv(assignment, @options)).to eq(expected_csv) end it 'checks csv with no data' do expected_csv = File.read('spec/features/assignment_export_details/expected_details_no_data_csv.txt') expect(generated_csv(assignment, @options)).to eq(expected_csv) end it 'checks csv with data and no options' do create(:answer, comments: 'Test comment') @options['team_id'] = 'false' @options['team_name'] = 'false' @options['reviewer'] = 'false' @options['question'] = 'false' @options['question_id'] = 'false' @options['comment_id'] = 'false' @options['comments'] = 'false' @options['score'] = 'false' expected_csv = File.read('spec/features/assignment_export_details/expected_details_no_options_csv.txt') expect(generated_csv(assignment, @options)).to eq(expected_csv) end end
describe 'find_due_dates' do context 'if deadline is of assignment' do it ' return assignment due_date' do assignment = create(:assignment) dead_rigth=create(:deadline_right) @deadline_type = create(:deadline_type) @assignment_due_date=create(:assignment_due_date,:parent_id => assignment.id,:review_allowed_id=>dead_rigth.id,:review_of_review_allowed_id=>dead_rigth.id,:submission_allowed_id=>dead_rigth.id,deadline_type:@deadline_type) expect(assignment.find_due_dates("submission").first).to eq(@assignment_due_date) end end context 'if deadline is of assignment' do it ' return assignment nil' do assignment = create(:assignment) expect(assignment.find_due_dates("submission").first).to eq(nil) end end end end
Result
When the spec tests are run we get the desired output on the terminal: