CSC/ECE 517 Fall 2016/E1674.Refactor leaderboard.rb and write unit tests: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 3: Line 3:
==Expertiza Background ==
==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. And students can be assigned in teams based on their selection of the topics. The Expertiza project is supported by the National Science Foundation.
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. And students can be assigned in teams based on their selection of the topics. The Expertiza project is supported by the National Science Foundation.
Currently in this web application the leaderboard page does not work.




Line 19: Line 21:


== Tools==
== Tools==
As for this project, we use the code climate plugin to test if our code is good enough. This plugin will obviously help us with the refactor part because it can show which part of the original codes have some problems. We also search through the internet and get to know how to write the Rspec files.
As for this project, we use the code climate plugin to test if our code is good enough. This plugin will obviously help us with the refactor part because it can show which part of the original codes have some problems. We also search through the internet and get to know how to write the Rspec files. We also ended up using the 'rspec/collection_matchers' class of rspec which allows us to match the number of items in a collection for an object.  





Revision as of 01:54, 29 October 2016

This page give a description of the changes made for the leaderboard.rb of Expertiza based OSS project.

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. And students can be assigned in teams based on their selection of the topics. The Expertiza project is supported by the National Science Foundation.

Currently in this web application the leaderboard page does not work.


Problem Statement

The task of the project is to refactor leaderboard.rb and write unit tests for it. As the name of the methods are not in a standard style, we use snake_case for method names. There are also some useless assignments to several variables. The rate of leaderboard.rb is D, which is needed to be improved.


Modified File

  • Refactor the leaderboard.rb
  • Create a RSpec file in /spec/models/ foler which contains unit test for leaderboard.rb


Thoughts

What we need to do is to deal with problems listed by the code climate. And we also need to write a new test file to test the functionality of leaderboard.rb. However, the leaderboard itself has some problems and IDE will report some problems when we want to run it. So we need to know which method in this file is broken first and just test others instead.


Tools

As for this project, we use the code climate plugin to test if our code is good enough. This plugin will obviously help us with the refactor part because it can show which part of the original codes have some problems. We also search through the internet and get to know how to write the Rspec files. We also ended up using the 'rspec/collection_matchers' class of rspec which allows us to match the number of items in a collection for an object.


Refactor

We will list each kind of problems we solved below.


Use snake_case for method names.

As we all know the snake_case means we need to name the methods and variables in this way. For example, we changed this method.

 def self.getIndependantAssignments(user_id)
   assignmentIds = AssignmentParticipant.where(user_id: user_id).pluck(:parent_id)
 end

Both variable names and method names are not in a good manner. We changed it to the version below.

 def self.get_independant_assignments(user_id)
   assignment_ids = AssignmentParticipant.where(user_id: user_id).pluck(:parent_id)
 end


Useless assignment to variable.

We just commented these useless variables.


Prefer `each` over `for`.

We know that 'each' function is more in ruby style for loops. So we would like to change all our 'for' to 'each'.

 for scoreEntry in scores
    ...
 end

We changed this loop to:

 scores.each do |scoreEntry|
    ...
 end

And the problem would be fixed.


Avoid more than 3 levels of block nesting.

 if qTypeHash.fetch(questionnaireType, {}).fetch(courseId, nil).nil?
    if qTypeHash.fetch(questionnaireType, nil).nil?
       ...
    end
    ...
 end

This is the third and fourth level of the block nesting. We need to merge them together.

 if q_type_hash.fetch(questionnaire_type, {}).fetch(course_id, nil).nil? && q_type_hash.fetch(questionnaire_type, nil).nil?
    ...
 elseif  q_type_hash.fetch(questionnaire_type, {}).fetch(course_id, nil).nil? && !q_type_hash.fetch(questionnaire_type, nil).nil?
    ...
 end

Then the 4-levels loop has been changed to 3-levels one.


`end` at 148, 1 is not aligned with `def` at 129, 2.

We just need to add a space in 148 line.


Rspec Test

The Leaderboard Class did not have any unit tests associated with it coming into this project so we have to create unit tests from scratch. Upon analysis of this class, we noticed that Leaderboard did not hold any variables and was only made up of static methods. So the first round of unit tests that were created made sure that each method could be called from the Leaderboard class with the correct number of arguments.

 it "Leaderboard responds to get_assignment_mapping" do
   expect(Leaderboard).to respond_to(:get_assignment_mapping).with(3).argument
 end

Next we needed to go through the methods and create tests for them. But in order to do this we had to make objects that this class depended on since this class takes the values from other classes to output arrays and hashes. Factories were used to create these objects with a few variables being overridden

 before(:each) do
   @student1 = create(:student, name: "Student1", fullname: "Student1 Test", email: "student1@mail.com" )
   @student2 = create(:student, name: "Student2", fullname: "Student2 Test", email: "student2@mail.com" )
   @instructor = create(:instructor)
   @course = create(:course)
   @assignment = create(:assignment, name: "Assign1", course: nil)
   @assignment2 = create(:assignment, name: "Assign2")
   @participant = create(:participant, parent_id: @assignment.id, user_id: @student1.id)
   @participant2 = create(:participant, parent_id: @assignment2.id, user_id: @student2.id)
   @questionnaire=create(:questionnaire)
   @assignment_questionnaire1 =create(:assignment_questionnaire, user_id: @student1.id, assignment: @assignment)
   @assignment_questionnaire2 =create(:assignment_questionnaire, user_id: @student2.id, assignment: @assignment2)
   @assignment_team = create(:assignment_team, name: "TestTeam", parent_id: @assignment2.id)
   @team_user = create(:team_user, team_id: @assignment_team.id, user_id: @student2.id)
 end

We tested the methods by seeing whether if we got the right amount of elements in our arrays/hashes like the following.

 it "getAssignmentsInCourses should return an assignment" do
   expect(Leaderboard.get_assignments_in_courses(1)).to have(1).items
 end

We also tested whether the code could handle invalid arguments like such.

 it "leaderboard_heading should return No Entry with invalid input" do    
   expect(Leaderboard.leaderboard_heading("Invalid")).to eq("No Entry")
 end

Additional

There are still some problems we need to figure out. For the code revising part, there are some methods with this problem: Assignment Branch Condition size for get_participants_score is too high.

I think we cannot make too many functions in one method so that we need to make some of these be executed outside of this method. Also, some of the code lines are too long so that it is not clear enough.

During the rspec testing we noticed that the methods get_participant_entries_in_assignment_list and find_by_qtype were being called but where not created in the program.

There was also no declaration of ScoreCache anywhere in the program which caused other methods to fail.