CSC/ECE 517 Fall 2016/E1670. Unit tests for answers.rb
E1670 . Unit tests for answers.rb
This wiki page is for the description of changes made under E1670 OSS assignment for Fall 2016, CSC/ECE 517.
Background
Expertiza is an Open Source web application developed on Ruby On Rails platform. It is a platform which allows students to take assignments posted by the course instructors. Expertiza allows students to select assignment topics, form teams and submit their work. It also allows them to review other students' submissions and improve their work based on this feedback.
Project Description
In Expertiza, each questionnaire contains many questions, those question may have different types (e.g. checkbox, criterion, etc). When a user fills in a rubric, the responses for each question will become an answer record. The responses of rubrics are stored in answers table in DB. The answer.rb is the model for the answers table in DB. Answer.rb model does not have any test cases and the aim of the project is to write fast, effective and flexible unit test cases that offer maximum code coverage.
Functions in answers.rb
Function Name : Compute_scores
Compute_scores is a function in model answer.rb which gives the average, maximum and minimum scores obtained in a series a responses/assessments. It has two input parameters: List of assessments and questions. The function iterates over each assessment to get the total score of that assessment. If the response or review is invalid, that assessment won’t be considered in the calculation of the score average. After iterating over all assessments, Max score, and Min scores are calculated along with the average score based on the number of valid assessments. Their scores are returned by the function.
Rspec Unit Test : Compute_scores
Following scenarios are tested:
- To return scores as nil if the input list of assessments is nil. This is to make sure no Null Pointer exceptions are thrown by the code
- To return a particular score when a single valid assessment is given as an input.
- To return a particular score when multiple valid assessments are given as an input. This is to test the looping functionality of the method.
- To return a particular score when invalid assessments are given as an input. The validity and total scores are returned by a mock and not by the actual functions. This is to make the test cases less rigid so that failure of dependent functions do not disrupt the functionality of interface level tests.
- To return a particular score when invalid flag is nil. Invalid flag can either be 0,1 or nil. Nil situation is tested to prevent NullPointer Exceptions
- To check if the method get_total_score is called with the right parameters.
Function Name : Get_total_scores
This function is called by the Compute_scores method of the answer.rb model to compute the total score of an assessment. The input consists of assessment for which the total score is being calculated and the list of questions being evaluated in the assessment. The method uses questionnaire id from the questions and response id to obtain a score view questionnaire data. This score view is a read-only record. The questionaire data mainly consists of q1_max_question_score, sum_of_weights and wieghted_score. Before calculating the score, the function performs two crucial tasks.
- Checks if the answer for a scored question is nil. If it is nil or unanswered, the the question will be ignored and not counted towards the score of this response.
- Calls the subsission_valid function by passing the response record to set the @invalid flag based on the validity of the response.
The total score is calculated using the below formula
(weighted_score / (sum_of_weights * max_question_score)) * 100
Any edge cases would return -1 indicating no score
Rspec Unit Test : Get_total_scores
Following scenarios are tested:
- To return an anticipated total score of a single response without any edge cases. Since this function will be called only on one response at a time, there is no need to test for multiple responses at the same time.
- To return an anticipated total score of a response where nil answer is for a scored question. This is to check if its weight gets removed from the sum_of_weights.
- To return -1 when the sum of weights becomes 0. This can happen when all the scored questions are unanswered.Value of -1 is checked at the calling function to ensure if a score is returned or not.
- To return -1 when weighted_score of questionnaireData is nil
- To check if submission_valid is called. This method is called to set invalid flag to indicate whether the response entered is valid or not. The validity criteria is explained in the submission_valid? Function.
This unit test uses two stubs and returns mock results
ScoreView.stub(:find_by_sql)
Answer.stub(:where)
This is to reduce the outcome of the test to depend on DB calls. For example, in case the connection to DB fails, this unit test would still pass making it less rigid.