CSC/ECE 517 Spring 2019 - Project E1921. Write tests for popup controller.rb: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
 
(10 intermediate revisions by 2 users not shown)
Line 28: Line 28:
1.Write RSpec integration tests to make the statement coverage above 90%.
1.Write RSpec integration tests to make the statement coverage above 90%.


2.Coverage as many edge cases as you can.
2.Cover as many edge cases as you can.


3.Achieve as high branch coverage as you can. We will use the mutant-rspec gem to measure test thoroughness and fault-finding capability of your tests.
3.Achieve as high branch coverage as you can. Teaching staff will use the mutant-rspec gem to measure test thoroughness and fault-finding capability of tests.


== Design ==
== Test Plan ==
In total, we write tests to cover all 10 methods in popup controller. We mock several different roles involved in the controller.
In total, we wrote tests to cover all 10 methods in the popup controller. We mocked many different objects involved in the controller.


====popup controller methods====
====Popup Controller Methods====
 
The code of the controller can be found [https://github.com/YChen239/expertiza/blob/master/app/controllers/popup_controller.rb here]. The methods are:


*action_allowed?
*action_allowed?
Line 48: Line 50:
*self_review_popup
*self_review_popup


 
====Mock Models====
====mock models====
Based on the controller, we mocked models to test different conditions. Models have complex and interdependent relationships, but the Expertiza project already includes a factory to build many of the models. This factory can be seen [https://github.com/expertiza/expertiza/blob/master/spec/factories/factories.rb here]. Additional database information can be accessed [http://wiki.expertiza.ncsu.edu/index.php/Documentation_on_Database_Tables here]. As you can see from our setup below, most of the objects we created relied on the factory with the exception of the final_versions array, which is not used in enough tests to warrant its own factory statement. Other objects are just built with additional/overwritten attributes, such as the student object.
Base on the controller, we mock several models to test different conditions. Each model has different relationship with each other and we can see the factory in [https://github.com/expertiza/expertiza/blob/master/spec/factories/factories.rb here] and DB [http://wiki.expertiza.ncsu.edu/index.php/Documentation_on_Database_Tables here].
<pre>
<pre>
let(:assignment_team) { build(:assignment_team, id: 1, name: "team1", assignment: assignment) }
let(:assignment_team) { build(:assignment_team, id: 1, name: "team1", assignment: assignment) }
Line 80: Line 81:
</pre>
</pre>


====test frame====
We made one change to the factory.rb file to build an instance of Team. We assume that the Team class may be used in other tests globally, so this should be added to the factory file and thus can be built more easily in future tests. Our addition to the factory.rb file is:
 
<pre>
factory :team, class: Team do
  id 1
  parent_id 1
end
</pre>
 
====Test Frame====
Since it's integration test, we need to test basic logic and return value in both methods in the controller and related methods in the controller. However, some of the methods have been tested in other rspec, all we need to do is to test the methods that haven't been tested. For 'action_allowed?', 'author_feedback_popup', 'team_users_popup', 'participants_popup', 'reviewer_details_popup', 'self_review_popup' methods, we test it separately. With 'tone_analysis_chart_popup', 'view_review_scores_popup', 'build_tone_analysis_report', 'build_tone_analysis_heatmap', we test them together since they both need to get each assignment'answer. Also 'tone_analysis_chart_popup' and 'view_review_scores_popup' all get 'build_tone_analysis_report' and 'build_tone_analysis_heatmap' in their method.
Since it's integration test, we need to test basic logic and return value in both methods in the controller and related methods in the controller. However, some of the methods have been tested in other rspec, all we need to do is to test the methods that haven't been tested. For 'action_allowed?', 'author_feedback_popup', 'team_users_popup', 'participants_popup', 'reviewer_details_popup', 'self_review_popup' methods, we test it separately. With 'tone_analysis_chart_popup', 'view_review_scores_popup', 'build_tone_analysis_report', 'build_tone_analysis_heatmap', we test them together since they both need to get each assignment'answer. Also 'tone_analysis_chart_popup' and 'view_review_scores_popup' all get 'build_tone_analysis_report' and 'build_tone_analysis_heatmap' in their method.


== Test Outline ==
== Test Outline ==


The following sections show the Rspec outline of the tests we created.
The following section shows the Rspec outline of the tests we created. The full test code can be found [https://github.com/YChen239/expertiza/blob/master/spec/controllers/popup_controller_spec.rb here]


'''PopupController'''
'''PopupController'''


Use four different roles to go into the method.
Check action permission with four different roles.


<pre>
<pre>
Line 103: Line 113:
</pre>
</pre>


Ger feedback when feedback exists.
Get feedback when feedback exists.


<pre>
<pre>
     #author_feedback_popup
     #author_feedback_popup
       when response_id exists
       when response_id exists
        get the result
</pre>
</pre>


Get response when the response map exists.
Get response stats when the response map exists, otherwise only find the team and users.
 
<pre>
<pre>
     #team_users_popup
     #team_users_popup
Line 119: Line 131:
</pre>
</pre>


Show different score when the reponse exists or not.  
Calculate scores depending on the existence of the response. If a review questionnaire is present, calculate scores with a max.


<pre>
<pre>
Line 132: Line 144:
</pre>
</pre>


Test all tone analysis related test together.
All tone analysis tests are run together. Both popup_* methods set instance variables before calling a build_* method. build_* methods are responsible for actually creating tone analysis tests and returning JSON information/graphics.
 
<pre>
<pre>
     tone analysis tests
     tone analysis tests
Line 138: Line 151:
         review tone analysis is calculated
         review tone analysis is calculated
           prepares tone analysis report for building
           prepares tone analysis report for building
      #build_tone_analysis_report
        upon selecting summery, the tone analysis for review comments is calculated and applied to the page
          builds a tone analysis report and returns the heat map URLs
       #view_review_scores_popup
       #view_review_scores_popup
         prepares tone analysis report for building
         review tone analysis is calculated
          prepares tone analysis report for building
       #build_tone_analysis_report
       #build_tone_analysis_report
         when answer not exists
         answer is provided
           return answer is none
           build tone analysis report
         when answer exists
         answer is not provided
           return answer
           build tone analysis report
       #build_tone_analysis_heatmap
       #build_tone_analysis_heatmap
         test some constant value
         sentiment is empty
          build tone analysis heatmap
 
</pre>  
</pre>  


Test the review details.
Test showing details about the reviewer.
 
<pre>  
<pre>  
     #reviewer_details_popup
     #reviewer_details_popup
Line 159: Line 173:
</pre>
</pre>


Get sef review.
Get reviews done by self.
 
<pre>   
<pre>   
     #self_review_popup
     #self_review_popup
Line 167: Line 182:


== Results ==
== Results ==
The total coverage of the test is 96.41% which meets the requirment.
The total coverage of the test is 96.41%, meeting our coverage requirement.


=== Related Links===
=== Related Links===
Line 179: Line 194:
===Conclusion===
===Conclusion===


The testing framework in the assignment_team_spec.rb used integration tests to test the methods in the controller. The mock instances are created at the beginning and the method logic is tested the each 'require'. For 'context', it gives the conditions for each test and for 'it'. For it, it excutes the code. For 'get', it goes through the whole method. Besides, we use gem 'byebug' to debug our test code.
The testing framework in the assignment_team_spec.rb used integration tests to test the methods in the controller. The mock instances are created at the beginning and the method logic is tested in each 'describe'. In addition, we used the Byebug gem to debug our test code.
In building the test framework, the key is to understand the logic in the method and understand the input and output value for the method.
The key to building successful tests is to understand the logic in the method and understand the input and output value for the method.

Latest revision as of 14:53, 31 March 2019

The goal of this project was to add testing for the PopupController to raise statement coverage above 90%. See the Test Outline section for specifics of our work.

Project Introduction

The PopupController is responsible for preparing data that will be displayed in popup views. To render the data, which mostly concerns assignments, the controller makes many accesses to database tables such as Response, ResponseMap, Question, Questionnaire, Answer, and Participant. Before our project, there were only two tests implemented that together only achieved a statement coverage of 7%. Our changes have brought the statement coverage to 96%.

Team

Zhewei Hu, zhu6 (mentor)

  • Yuhan Chen, ychen239
  • Hao Lu, hlu6
  • Drew Marshburn, rdmarshb

Files Involved

popup_controller.rb

popup_controller_spec.rb

Running Tests

What we need to do is to set up the environment and complete the 'popup_controller_spec.rb' to finish the integration tests for popup controller. This rspec test file can be run by calling the following code:

  rspec spec/controllers/popup_controller_spec.rb

What needs to be done

1.Write RSpec integration tests to make the statement coverage above 90%.

2.Cover as many edge cases as you can.

3.Achieve as high branch coverage as you can. Teaching staff will use the mutant-rspec gem to measure test thoroughness and fault-finding capability of tests.

Test Plan

In total, we wrote tests to cover all 10 methods in the popup controller. We mocked many different objects involved in the controller.

Popup Controller Methods

The code of the controller can be found here. The methods are:

  • action_allowed?
  • author_feedback_popup
  • team_users_popup
  • participants_popup
  • tone_analysis_chart_popup
  • view_review_scores_popup
  • build_tone_analysis_report
  • build_tone_analysis_heatmap
  • reviewer_details_popup
  • self_review_popup

Mock Models

Based on the controller, we mocked models to test different conditions. Models have complex and interdependent relationships, but the Expertiza project already includes a factory to build many of the models. This factory can be seen here. Additional database information can be accessed here. As you can see from our setup below, most of the objects we created relied on the factory with the exception of the final_versions array, which is not used in enough tests to warrant its own factory statement. Other objects are just built with additional/overwritten attributes, such as the student object.

let(:assignment_team) { build(:assignment_team, id: 1, name: "team1", assignment: assignment) }
  let(:team) {build(:team)}
  let(:team_user) {build(:team_user)}
  let(:student) { build(:student, id: 1, name: "student") }
  let(:student2) { build(:student, id: 2, name: "student2") }
  let(:admin) { build(:admin) }
  let(:instructor) { build(:instructor) }
  let(:ta) { build(:teaching_assistant) }
  let(:participant) { build(:participant, id: 1, user_id: 1, user: student, assignment: assignment) }
  let(:participant2) { build(:participant, id: 2, user: student2, assignment: assignment) }

  let(:response) { build(:response, id: 1) }
  let(:questionnaire) { build(:questionnaire, id: 1, max_question_score: 15)}
  let(:question) { build(:question, id: 1, questionnaire_id: questionnaire.id)}
  let(:answer) { build(:answer, id: 1, question_id: question.id, response_id: response.id, answer: 10) }

  let(:assignment) { build(:assignment, id: 1) }
  let(:response_map) { build(:review_response_map, id: 1, reviewee_id: assignment_team.id, reviewer_id: participant2.id, response: [response], assignment: assignment) }
  let(:final_versions) {{
      review_round_one: {questionnaire_id: 1, response_ids: [1]},
      review_round_two: {questionnaire_id: 2, response_ids: [2]},
      review_round_three: {questionnaire_id: 3, response_ids: [3], }
  }}

  test_url = "http://peerlogic.csc.ncsu.edu/reviewsentiment/viz/478-5hf542"
  mocked_comments_one = OpenStruct.new(comments: "test comment")

We made one change to the factory.rb file to build an instance of Team. We assume that the Team class may be used in other tests globally, so this should be added to the factory file and thus can be built more easily in future tests. Our addition to the factory.rb file is:

factory :team, class: Team do
  id 1
  parent_id 1
end

Test Frame

Since it's integration test, we need to test basic logic and return value in both methods in the controller and related methods in the controller. However, some of the methods have been tested in other rspec, all we need to do is to test the methods that haven't been tested. For 'action_allowed?', 'author_feedback_popup', 'team_users_popup', 'participants_popup', 'reviewer_details_popup', 'self_review_popup' methods, we test it separately. With 'tone_analysis_chart_popup', 'view_review_scores_popup', 'build_tone_analysis_report', 'build_tone_analysis_heatmap', we test them together since they both need to get each assignment'answer. Also 'tone_analysis_chart_popup' and 'view_review_scores_popup' all get 'build_tone_analysis_report' and 'build_tone_analysis_heatmap' in their method.

Test Outline

The following section shows the Rspec outline of the tests we created. The full test code can be found here

PopupController

Check action permission with four different roles.

     #action_allowed?
       when the role current user is student
         does not allow certain action
       when the role current user is ta
         allows certain action
       when the role name of current user is super admin or admin
         allows certain action
       when the role current user is super instructor
         allows certain action

Get feedback when feedback exists.

    #author_feedback_popup
      when response_id exists
        get the result

Get response stats when the response map exists, otherwise only find the team and users.

    #team_users_popup
      when a response map exists
        calculates response stats for one response
      when a response map does not exist
        finds team and users

Calculate scores depending on the existence of the response. If a review questionnaire is present, calculate scores with a max.

    #participants_popup
      called with no response
        does not calculate scores
      called with a response
        assignment has a review questionnaire
          calculates the scores with a max
        assignment has no review questionnaire
          calculates the scores without a max

All tone analysis tests are run together. Both popup_* methods set instance variables before calling a build_* method. build_* methods are responsible for actually creating tone analysis tests and returning JSON information/graphics.

    tone analysis tests
      #tone_analysis_chart_popup
        review tone analysis is calculated
          prepares tone analysis report for building
      #view_review_scores_popup
        review tone analysis is calculated
          prepares tone analysis report for building
      #build_tone_analysis_report
        answer is provided
          build tone analysis report
        answer is not provided
          build tone analysis report
      #build_tone_analysis_heatmap
        sentiment is empty
          build tone analysis heatmap

Test showing details about the reviewer.

 
    #reviewer_details_popup
      it will show the reviewer details
        it will show the reviewer details

Get reviews done by self.

  
    #self_review_popup
      when response_id exists
        get the result

Results

The total coverage of the test is 96.41%, meeting our coverage requirement.

Related Links

A video of all tests running can be seen here.

The main repository can be found here

The forked git repository for this project can be found here

Conclusion

The testing framework in the assignment_team_spec.rb used integration tests to test the methods in the controller. The mock instances are created at the beginning and the method logic is tested in each 'describe'. In addition, we used the Byebug gem to debug our test code. The key to building successful tests is to understand the logic in the method and understand the input and output value for the method.