<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Hxia3</id>
	<title>Expertiza_Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Hxia3"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Hxia3"/>
	<updated>2026-05-12T16:23:50Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100330</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100330"/>
		<updated>2015-12-05T04:51:50Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team &lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/student_sign_in_spec.rb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment(in this test: Ethical analysis 2)&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
&lt;br /&gt;
On this page, we expect the sender's name will appear.&lt;br /&gt;
&lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/add_member_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, as this user has already signed up for this topic, we should get the following message: Your topic(s): Self-plagiarism. &lt;br /&gt;
# sign out &lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/select_a_topic_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# sign out &lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/select_a_submission_to_review_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click 'Begin'&lt;br /&gt;
# check that a review form has successfully been created&lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/bring_up_review_form_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click 'Begin'&lt;br /&gt;
# fill out all text fields&lt;br /&gt;
# select all scores from dropdowns&lt;br /&gt;
# save form&lt;br /&gt;
# check for successful save&lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/fill_out_review_form_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
To run this test run: $ rspec spec/features/student_view_score.rb&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Check for confirmation that the feedback was saved&lt;br /&gt;
To run this test run:$ rspec spec/features/review_feedback.rb&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
*Github repository:  https://github.com/xhy279/expertiza/tree/fall2015/spec/features&lt;br /&gt;
*Pull requests link: https://github.com/expertiza/expertiza/pull/640 &lt;br /&gt;
*Demo videos(4 in total): &amp;lt;br&amp;gt;&lt;br /&gt;
1. https://drive.google.com/open?id=0B3EOsci5DEveMGZOdVNIazJlNVE &amp;lt;br&amp;gt;&lt;br /&gt;
2. https://drive.google.com/a/ncsu.edu/file/d/0B-l-xu44qiJUZDRFMU02U09kZWs/view?usp=sharing &amp;lt;br&amp;gt;&lt;br /&gt;
3. https://drive.google.com/a/ncsu.edu/file/d/0B80MLsKsoSOmWFdvYThJZzdCVVE/view?usp=sharing &amp;lt;br&amp;gt; &lt;br /&gt;
4. https://drive.google.com/a/ncsu.edu/file/d/0B7dSj1bvwNp9X29TTHJMVFhPWkE/view?usp=sharing &amp;lt;br&amp;gt;&lt;br /&gt;
Note: There is a problem at the end of the third video and the save can not complete because of a time out issue. This does not effect the test, just the ability to demonstrate the test.&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100309</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100309"/>
		<updated>2015-12-05T04:39:35Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* We have &amp;quot;add_member_spec.rb&amp;quot; to do this task. Run test using the command &amp;quot;rspec spec/features/add_member_spec.rb &amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team &lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/student_sign_in_spec.rb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment(in this test: Ethical analysis 2)&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
&lt;br /&gt;
On this page, we expect the sender's name will appear.&lt;br /&gt;
&lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/add_member_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, as this user has already signed up for this topic, we should get the following message: Your topic(s): Self-plagiarism. &lt;br /&gt;
# sign out &lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/select_a_topic_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# sign out &lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/select_a_submission_to_review_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click 'Begin'&lt;br /&gt;
# check that a review form has successfully been created&lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/bring_up_review_form_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click 'Begin'&lt;br /&gt;
# fill out all text fields&lt;br /&gt;
# select all scores from dropdowns&lt;br /&gt;
# save form&lt;br /&gt;
# check for successful save&lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/fill_out_review_form_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
To run this test run: $ rspec spec/features/student_view_score.rb&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Check for confirmation that the feedback was saved&lt;br /&gt;
To run this test run:$ rspec spec/features/review_feedback.rb&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
*Github repository:  https://github.com/xhy279/expertiza/tree/fall2015/spec/features&lt;br /&gt;
*Demo videos(4 in total): &amp;lt;br&amp;gt;&lt;br /&gt;
1. https://drive.google.com/open?id=0B3EOsci5DEveMGZOdVNIazJlNVE &amp;lt;br&amp;gt;&lt;br /&gt;
2. https://drive.google.com/a/ncsu.edu/file/d/0B-l-xu44qiJUZDRFMU02U09kZWs/view?usp=sharing &amp;lt;br&amp;gt;&lt;br /&gt;
3. https://drive.google.com/a/ncsu.edu/file/d/0B80MLsKsoSOmWFdvYThJZzdCVVE/view?usp=sharing &amp;lt;br&amp;gt; &lt;br /&gt;
4. https://drive.google.com/a/ncsu.edu/file/d/0B7dSj1bvwNp9X29TTHJMVFhPWkE/view?usp=sharing &amp;lt;br&amp;gt;&lt;br /&gt;
Note: There is a problem at the end of the third video and the save can not complete because of a time out issue. This does not effect the test, just the ability to demonstrate the test.&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100307</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100307"/>
		<updated>2015-12-05T04:39:06Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* We have test file &amp;quot;student_sign_in.rb&amp;quot; do this task. Run test using command &amp;quot; rspec spec/features/student_sign_in_spec.rb&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team &lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/student_sign_in_spec.rb&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment(in this test: Ethical analysis 2)&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
&lt;br /&gt;
On this page, we expect the sender's name will appear.&lt;br /&gt;
&lt;br /&gt;
====We have &amp;quot;add_member_spec.rb&amp;quot; to do this task. Run test using the command &amp;quot;rspec spec/features/add_member_spec.rb &amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, as this user has already signed up for this topic, we should get the following message: Your topic(s): Self-plagiarism. &lt;br /&gt;
# sign out &lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/select_a_topic_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# sign out &lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/select_a_submission_to_review_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click 'Begin'&lt;br /&gt;
# check that a review form has successfully been created&lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/bring_up_review_form_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click 'Begin'&lt;br /&gt;
# fill out all text fields&lt;br /&gt;
# select all scores from dropdowns&lt;br /&gt;
# save form&lt;br /&gt;
# check for successful save&lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/fill_out_review_form_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
To run this test run: $ rspec spec/features/student_view_score.rb&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Check for confirmation that the feedback was saved&lt;br /&gt;
To run this test run:$ rspec spec/features/review_feedback.rb&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
*Github repository:  https://github.com/xhy279/expertiza/tree/fall2015/spec/features&lt;br /&gt;
*Demo videos(4 in total): &amp;lt;br&amp;gt;&lt;br /&gt;
1. https://drive.google.com/open?id=0B3EOsci5DEveMGZOdVNIazJlNVE &amp;lt;br&amp;gt;&lt;br /&gt;
2. https://drive.google.com/a/ncsu.edu/file/d/0B-l-xu44qiJUZDRFMU02U09kZWs/view?usp=sharing &amp;lt;br&amp;gt;&lt;br /&gt;
3. https://drive.google.com/a/ncsu.edu/file/d/0B80MLsKsoSOmWFdvYThJZzdCVVE/view?usp=sharing &amp;lt;br&amp;gt; &lt;br /&gt;
4. https://drive.google.com/a/ncsu.edu/file/d/0B7dSj1bvwNp9X29TTHJMVFhPWkE/view?usp=sharing &amp;lt;br&amp;gt;&lt;br /&gt;
Note: There is a problem at the end of the third video and the save can not complete because of a time out issue. This does not effect the test, just the ability to demonstrate the test.&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100221</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100221"/>
		<updated>2015-12-05T01:37:31Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Select a submission to review */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team &lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
==== We have test file &amp;quot;student_sign_in.rb&amp;quot; do this task. Run test using command &amp;quot; rspec spec/features/student_sign_in_spec.rb&amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment(in this test: Ethical analysis 2)&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
&lt;br /&gt;
On this page, we expect the sender's name will appear.&lt;br /&gt;
&lt;br /&gt;
====We have &amp;quot;add_member_spec.rb&amp;quot; to do this task. Run test using the command &amp;quot;rspec spec/features/add_member_spec.rb &amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, as this user has already signed up for this topic, we should get the following message: Your topic(s): Self-plagiarism. &lt;br /&gt;
# sign out &lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/select_a_topic_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# sign out &lt;br /&gt;
Run test using the command &amp;quot;rspec spec/features/select_a_submission_to_review_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click 'Begin'&lt;br /&gt;
# check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# open a review form&lt;br /&gt;
# fill out all text fields&lt;br /&gt;
# select all scores from dropdowns&lt;br /&gt;
# submit form&lt;br /&gt;
# check for successful save&lt;br /&gt;
&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# open a review form&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# fill out some text fields&lt;br /&gt;
# select some scores&lt;br /&gt;
# save form&lt;br /&gt;
# reopen form&lt;br /&gt;
# fill out remaining fields and scores&lt;br /&gt;
# save form&lt;br /&gt;
# check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
To run this test run: $ rspec spec/features/student_view_score.rb&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Check for confirmation that the feedback was saved&lt;br /&gt;
To run this test run:$ rspec spec/features/review_feedback.rb&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
*Github repository:  https://github.com/xhy279/expertiza/tree/fall2015/spec/features&lt;br /&gt;
*Demo videos(4 in total): &lt;br /&gt;
1. https://drive.google.com/open?id=0B3EOsci5DEveMGZOdVNIazJlNVE&lt;br /&gt;
2. https://drive.google.com/a/ncsu.edu/file/d/0B-l-xu44qiJUZDRFMU02U09kZWs/view?usp=sharing&lt;br /&gt;
3.&lt;br /&gt;
4. https://drive.google.com/a/ncsu.edu/file/d/0B7dSj1bvwNp9X29TTHJMVFhPWkE/view?usp=sharing&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100179</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100179"/>
		<updated>2015-12-05T01:05:22Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team &lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
==== We have test file &amp;quot;student_sign_in.rb&amp;quot; do this task. Run test using command &amp;quot; rspec spec/features/student_sign_in_spec.rb&amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment(in this test: Ethical analysis 2)&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
&lt;br /&gt;
On this page, we expect the sender's name will appear.&lt;br /&gt;
&lt;br /&gt;
====We have &amp;quot;add_member_spec.rb&amp;quot; to do this task. Run test using the command &amp;quot;rspec spec/features/add_member_spec.rb &amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, as this user has already signed up for this topic, we should get the following message: Your topic(s): Self-plagiarism. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click 'Begin'&lt;br /&gt;
# check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# open a review form&lt;br /&gt;
# fill out all text fields&lt;br /&gt;
# select all scores from dropdowns&lt;br /&gt;
# submit form&lt;br /&gt;
# check for successful save&lt;br /&gt;
&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# open a review form&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# fill out some text fields&lt;br /&gt;
# select some scores&lt;br /&gt;
# save form&lt;br /&gt;
# reopen form&lt;br /&gt;
# fill out remaining fields and scores&lt;br /&gt;
# save form&lt;br /&gt;
# check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
To run this test run: $ rspec spec/features/student_view_score.rb&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Check for confirmation that the feedback was saved&lt;br /&gt;
To run this test run:$ rspec spec/features/review_feedback.rb&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
*Github repository:  https://github.com/xhy279/expertiza/tree/fall2015/spec/features&lt;br /&gt;
*Demo videos(4 in total): &lt;br /&gt;
1. https://drive.google.com/open?id=0B3EOsci5DEveMGZOdVNIazJlNVE&lt;br /&gt;
2. https://drive.google.com/a/ncsu.edu/file/d/0B-l-xu44qiJUZDRFMU02U09kZWs/view?usp=sharing&lt;br /&gt;
3.&lt;br /&gt;
4. https://drive.google.com/a/ncsu.edu/file/d/0B7dSj1bvwNp9X29TTHJMVFhPWkE/view?usp=sharing&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100108</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100108"/>
		<updated>2015-12-04T22:13:45Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Test Plan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team &lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
==== We have test file &amp;quot;student_sign_in.rb&amp;quot; do this task. Run test using command &amp;quot; rspec spec/features/student_sign_in_spec.rb&amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment(in this test: Ethical analysis 2)&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
&lt;br /&gt;
On this page, we expect the sender's name will appear.&lt;br /&gt;
&lt;br /&gt;
====We have &amp;quot;add_member_spec.rb&amp;quot; to do this task. Run test using the command &amp;quot;rspec spec/features/add_member_spec.rb &amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, as this user has already signed up for this topic, we should get the following message: Your topic(s): Self-plagiarism. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click 'Begin'&lt;br /&gt;
# check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# open a review form&lt;br /&gt;
# fill out all text fields&lt;br /&gt;
# select all scores from dropdowns&lt;br /&gt;
# submit form&lt;br /&gt;
# check for successful save&lt;br /&gt;
&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# open a review form&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# fill out some text fields&lt;br /&gt;
# select some scores&lt;br /&gt;
# save form&lt;br /&gt;
# reopen form&lt;br /&gt;
# fill out remaining fields and scores&lt;br /&gt;
# save form&lt;br /&gt;
# check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Sign out&lt;br /&gt;
# Sign in as reviewer&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Other’s work’&lt;br /&gt;
# Check that a feedback exists.&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
*Github repository:  https://github.com/xhy279/expertiza/tree/fall2015/spec/features&lt;br /&gt;
*Demo videos(4 in total): 1. https://drive.google.com/open?id=0B3EOsci5DEveMGZOdVNIazJlNVE&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100075</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100075"/>
		<updated>2015-12-04T16:55:25Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team Should not be possible if you exceed the max # of team members)&lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
==== We have test file &amp;quot;student_sign_in.rb&amp;quot; do this task. Run test using command &amp;quot; rspec spec/features/student_sign_in_spec.rb&amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment(in this test: Ethical analysis 2)&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
&lt;br /&gt;
On this page, we expect the sender's name will appear.&lt;br /&gt;
&lt;br /&gt;
====We have &amp;quot;add_member_spec.rb&amp;quot; to do this task. Run test using the command &amp;quot;rspec spec/features/add_member_spec.rb &amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, or join the waiting list if the topic is not available. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# fill in all the required forms, and then click “save” to save our review. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# Execute the ‘Request a new submission’ button action  &lt;br /&gt;
# Check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out all text fields&lt;br /&gt;
# Select all scores from dropdowns&lt;br /&gt;
# Submit form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out some text fields&lt;br /&gt;
# Select some scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Reopen form&lt;br /&gt;
# Fill out remaining fields and scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Sign out&lt;br /&gt;
# Sign in as reviewer&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Other’s work’&lt;br /&gt;
# Check that a feedback exists.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
*Github repository:  https://github.com/xhy279/expertiza/tree/fall2015/spec/features&lt;br /&gt;
*Demo videos(4 in total): 1. https://drive.google.com/open?id=0B3EOsci5DEveMGZOdVNIazJlNVE&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100052</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100052"/>
		<updated>2015-12-04T02:24:02Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* We have &amp;quot;add_member_spec.rb&amp;quot; to do this task. Run test use the command &amp;quot;rspec spec/features/add_member_spec.rb &amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team Should not be possible if you exceed the max # of team members)&lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
==== We have test file &amp;quot;student_sign_in.rb&amp;quot; do this task. Run test using command &amp;quot; rspec spec/features/student_sign_in_spec.rb&amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment(in this test: Ethical analysis 2)&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
&lt;br /&gt;
On this page, we expect the sender's name will appear.&lt;br /&gt;
&lt;br /&gt;
====We have &amp;quot;add_member_spec.rb&amp;quot; to do this task. Run test using the command &amp;quot;rspec spec/features/add_member_spec.rb &amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, or join the waiting list if the topic is not available. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# fill in all the required forms, and then click “save” to save our review. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# Execute the ‘Request a new submission’ button action  &lt;br /&gt;
# Check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out all text fields&lt;br /&gt;
# Select all scores from dropdowns&lt;br /&gt;
# Submit form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out some text fields&lt;br /&gt;
# Select some scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Reopen form&lt;br /&gt;
# Fill out remaining fields and scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Sign out&lt;br /&gt;
# Sign in as reviewer&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Other’s work’&lt;br /&gt;
# Check that a feedback exists.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
*Github repository:  https://github.com/xhy279/expertiza/tree/fall2015/spec/features&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100051</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100051"/>
		<updated>2015-12-04T02:23:50Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* We have test file &amp;quot;student_sign_in.rb&amp;quot; do this task. Please run command &amp;quot; rspec spec/features/student_sign_in_spec.rb&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team Should not be possible if you exceed the max # of team members)&lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
==== We have test file &amp;quot;student_sign_in.rb&amp;quot; do this task. Run test using command &amp;quot; rspec spec/features/student_sign_in_spec.rb&amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment(in this test: Ethical analysis 2)&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
&lt;br /&gt;
On this page, we expect the sender's name will appear.&lt;br /&gt;
&lt;br /&gt;
====We have &amp;quot;add_member_spec.rb&amp;quot; to do this task. Run test use the command &amp;quot;rspec spec/features/add_member_spec.rb &amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, or join the waiting list if the topic is not available. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# fill in all the required forms, and then click “save” to save our review. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# Execute the ‘Request a new submission’ button action  &lt;br /&gt;
# Check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out all text fields&lt;br /&gt;
# Select all scores from dropdowns&lt;br /&gt;
# Submit form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out some text fields&lt;br /&gt;
# Select some scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Reopen form&lt;br /&gt;
# Fill out remaining fields and scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Sign out&lt;br /&gt;
# Sign in as reviewer&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Other’s work’&lt;br /&gt;
# Check that a feedback exists.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
*Github repository:  https://github.com/xhy279/expertiza/tree/fall2015/spec/features&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100050</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100050"/>
		<updated>2015-12-04T02:23:14Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Add someone to a team */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team Should not be possible if you exceed the max # of team members)&lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
==== We have test file &amp;quot;student_sign_in.rb&amp;quot; do this task. Please run command &amp;quot; rspec spec/features/student_sign_in_spec.rb&amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment(in this test: Ethical analysis 2)&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
&lt;br /&gt;
On this page, we expect the sender's name will appear.&lt;br /&gt;
&lt;br /&gt;
====We have &amp;quot;add_member_spec.rb&amp;quot; to do this task. Run test use the command &amp;quot;rspec spec/features/add_member_spec.rb &amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, or join the waiting list if the topic is not available. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# fill in all the required forms, and then click “save” to save our review. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# Execute the ‘Request a new submission’ button action  &lt;br /&gt;
# Check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out all text fields&lt;br /&gt;
# Select all scores from dropdowns&lt;br /&gt;
# Submit form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out some text fields&lt;br /&gt;
# Select some scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Reopen form&lt;br /&gt;
# Fill out remaining fields and scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Sign out&lt;br /&gt;
# Sign in as reviewer&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Other’s work’&lt;br /&gt;
# Check that a feedback exists.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
*Github repository:  https://github.com/xhy279/expertiza/tree/fall2015/spec/features&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100049</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100049"/>
		<updated>2015-12-04T02:23:04Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Add someone to a team */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team Should not be possible if you exceed the max # of team members)&lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
==== We have test file &amp;quot;student_sign_in.rb&amp;quot; do this task. Please run command &amp;quot; rspec spec/features/student_sign_in_spec.rb&amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment(in this test: Ethical analysis 2)&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
&lt;br /&gt;
On this page, we expect the sender's name will appear.&lt;br /&gt;
&lt;br /&gt;
====We have &amp;quot;add_member_spec.rb&amp;quot; to do this task. Run test use the command &amp;quot;rspec spec/features/add_member_spec.rb &amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, or join the waiting list if the topic is not available. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# fill in all the required forms, and then click “save” to save our review. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# Execute the ‘Request a new submission’ button action  &lt;br /&gt;
# Check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out all text fields&lt;br /&gt;
# Select all scores from dropdowns&lt;br /&gt;
# Submit form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out some text fields&lt;br /&gt;
# Select some scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Reopen form&lt;br /&gt;
# Fill out remaining fields and scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Sign out&lt;br /&gt;
# Sign in as reviewer&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Other’s work’&lt;br /&gt;
# Check that a feedback exists.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
*Github repository:  https://github.com/xhy279/expertiza/tree/fall2015/spec/features&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100048</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100048"/>
		<updated>2015-12-04T02:21:37Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Add someone to a team */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team Should not be possible if you exceed the max # of team members)&lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
==== We have test file &amp;quot;student_sign_in.rb&amp;quot; do this task. Please run command &amp;quot; rspec spec/features/student_sign_in_spec.rb&amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment(in this test: Ethical analysis 2)&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
&lt;br /&gt;
On this page, we expect the sender's name will appear.&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, or join the waiting list if the topic is not available. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# fill in all the required forms, and then click “save” to save our review. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# Execute the ‘Request a new submission’ button action  &lt;br /&gt;
# Check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out all text fields&lt;br /&gt;
# Select all scores from dropdowns&lt;br /&gt;
# Submit form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out some text fields&lt;br /&gt;
# Select some scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Reopen form&lt;br /&gt;
# Fill out remaining fields and scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Sign out&lt;br /&gt;
# Sign in as reviewer&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Other’s work’&lt;br /&gt;
# Check that a feedback exists.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
*Github repository:  https://github.com/xhy279/expertiza/tree/fall2015/spec/features&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100047</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100047"/>
		<updated>2015-12-04T02:19:46Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team Should not be possible if you exceed the max # of team members)&lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
==== We have test file &amp;quot;student_sign_in.rb&amp;quot; do this task. Please run command &amp;quot; rspec spec/features/student_sign_in_spec.rb&amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Fill in the box with invitation receiver name and click button send invitation. &lt;br /&gt;
After doing these steps, we expect fault would happen. We could capture contents ‘Your team already has max members.’ &lt;br /&gt;
* Scenario 2 : Team member  don't exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as the sender &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
On this page, we expect the receiver's name will appear.&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, or join the waiting list if the topic is not available. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# fill in all the required forms, and then click “save” to save our review. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# Execute the ‘Request a new submission’ button action  &lt;br /&gt;
# Check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out all text fields&lt;br /&gt;
# Select all scores from dropdowns&lt;br /&gt;
# Submit form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out some text fields&lt;br /&gt;
# Select some scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Reopen form&lt;br /&gt;
# Fill out remaining fields and scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Sign out&lt;br /&gt;
# Sign in as reviewer&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Other’s work’&lt;br /&gt;
# Check that a feedback exists.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
*Github repository:  https://github.com/xhy279/expertiza/tree/fall2015/spec/features&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100046</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100046"/>
		<updated>2015-12-04T02:19:28Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* External links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team Should not be possible if you exceed the max # of team members)&lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
==== We have test file &amp;quot;student_sign_in.rb&amp;quot; do this task. Please run command &amp;quot; rspec spec/features/student_sign_in_spec.rb&amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Fill in the box with invitation receiver name and click button send invitation. &lt;br /&gt;
After doing these steps, we expect fault would happen. We could capture contents ‘Your team already has max members.’ &lt;br /&gt;
* Scenario 2 : Team member  don't exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as the sender &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
On this page, we expect the receiver's name will appear.&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, or join the waiting list if the topic is not available. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# fill in all the required forms, and then click “save” to save our review. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# Execute the ‘Request a new submission’ button action  &lt;br /&gt;
# Check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out all text fields&lt;br /&gt;
# Select all scores from dropdowns&lt;br /&gt;
# Submit form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out some text fields&lt;br /&gt;
# Select some scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Reopen form&lt;br /&gt;
# Fill out remaining fields and scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Sign out&lt;br /&gt;
# Sign in as reviewer&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Other’s work’&lt;br /&gt;
# Check that a feedback exists.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
* Github repository:  [https://github.com/xhy279/expertiza/tree/fall2015/spec/features]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100044</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100044"/>
		<updated>2015-12-04T02:11:02Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* We have file &amp;quot;student_sign_in.rb&amp;quot; do this take. Please run command &amp;quot; rspec spec/features/student_sign_in_spec.rb&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team Should not be possible if you exceed the max # of team members)&lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
==== We have test file &amp;quot;student_sign_in.rb&amp;quot; do this task. Please run command &amp;quot; rspec spec/features/student_sign_in_spec.rb&amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Fill in the box with invitation receiver name and click button send invitation. &lt;br /&gt;
After doing these steps, we expect fault would happen. We could capture contents ‘Your team already has max members.’ &lt;br /&gt;
* Scenario 2 : Team member  don't exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as the sender &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
On this page, we expect the receiver's name will appear.&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, or join the waiting list if the topic is not available. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# fill in all the required forms, and then click “save” to save our review. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# Execute the ‘Request a new submission’ button action  &lt;br /&gt;
# Check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out all text fields&lt;br /&gt;
# Select all scores from dropdowns&lt;br /&gt;
# Submit form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out some text fields&lt;br /&gt;
# Select some scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Reopen form&lt;br /&gt;
# Fill out remaining fields and scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Sign out&lt;br /&gt;
# Sign in as reviewer&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Other’s work’&lt;br /&gt;
# Check that a feedback exists.&lt;br /&gt;
&lt;br /&gt;
==External links==&lt;br /&gt;
* [http://rspec.info/ Official website]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100043</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=100043"/>
		<updated>2015-12-04T02:10:25Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Log in */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team Should not be possible if you exceed the max # of team members)&lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
==== We have file &amp;quot;student_sign_in.rb&amp;quot; do this take. Please run command &amp;quot; rspec spec/features/student_sign_in_spec.rb&amp;quot;====&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Fill in the box with invitation receiver name and click button send invitation. &lt;br /&gt;
After doing these steps, we expect fault would happen. We could capture contents ‘Your team already has max members.’ &lt;br /&gt;
* Scenario 2 : Team member  don't exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as the sender &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
On this page, we expect the receiver's name will appear.&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, or join the waiting list if the topic is not available. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# fill in all the required forms, and then click “save” to save our review. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# Execute the ‘Request a new submission’ button action  &lt;br /&gt;
# Check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out all text fields&lt;br /&gt;
# Select all scores from dropdowns&lt;br /&gt;
# Submit form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out some text fields&lt;br /&gt;
# Select some scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Reopen form&lt;br /&gt;
# Fill out remaining fields and scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Sign out&lt;br /&gt;
# Sign in as reviewer&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Other’s work’&lt;br /&gt;
# Check that a feedback exists.&lt;br /&gt;
&lt;br /&gt;
==External links==&lt;br /&gt;
* [http://rspec.info/ Official website]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=99991</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=99991"/>
		<updated>2015-11-17T02:04:55Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Testing tools */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave. It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team Should not be possible if you exceed the max # of team members)&lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Fill in the box with invitation receiver name and click button send invitation. &lt;br /&gt;
After doing these steps, we expect fault would happen. We could capture contents ‘Your team already has max members.’ &lt;br /&gt;
* Scenario 2 : Team member  don't exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as the sender &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
On this page, we expect the receiver's name will appear.&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, or join the waiting list if the topic is not available. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# fill in all the required forms, and then click “save” to save our review. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# Execute the ‘Request a new submission’ button action  &lt;br /&gt;
# Check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out all text fields&lt;br /&gt;
# Select all scores from dropdowns&lt;br /&gt;
# Submit form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out some text fields&lt;br /&gt;
# Select some scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Reopen form&lt;br /&gt;
# Fill out remaining fields and scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Sign out&lt;br /&gt;
# Sign in as reviewer&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Other’s work’&lt;br /&gt;
# Check that a feedback exists.&lt;br /&gt;
&lt;br /&gt;
==External links==&lt;br /&gt;
* [http://rspec.info/ Official website]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=99990</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=99990"/>
		<updated>2015-11-17T02:04:27Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* External links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave.&amp;lt;ref name=&amp;quot;origin&amp;quot;&amp;gt;Ed Gibbs, [http://edgibbs.com/2007/12/02/jbehave-and-rspec-history/ JBehave and RSpec History] (Blog entry)&amp;lt;/ref&amp;gt; It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team Should not be possible if you exceed the max # of team members)&lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Fill in the box with invitation receiver name and click button send invitation. &lt;br /&gt;
After doing these steps, we expect fault would happen. We could capture contents ‘Your team already has max members.’ &lt;br /&gt;
* Scenario 2 : Team member  don't exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as the sender &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
On this page, we expect the receiver's name will appear.&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, or join the waiting list if the topic is not available. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# fill in all the required forms, and then click “save” to save our review. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# Execute the ‘Request a new submission’ button action  &lt;br /&gt;
# Check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out all text fields&lt;br /&gt;
# Select all scores from dropdowns&lt;br /&gt;
# Submit form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out some text fields&lt;br /&gt;
# Select some scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Reopen form&lt;br /&gt;
# Fill out remaining fields and scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Sign out&lt;br /&gt;
# Sign in as reviewer&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Other’s work’&lt;br /&gt;
# Check that a feedback exists.&lt;br /&gt;
&lt;br /&gt;
==External links==&lt;br /&gt;
* [http://rspec.info/ Official website]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=99989</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=99989"/>
		<updated>2015-11-17T02:04:19Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Respond to a review (“author feedback”) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave.&amp;lt;ref name=&amp;quot;origin&amp;quot;&amp;gt;Ed Gibbs, [http://edgibbs.com/2007/12/02/jbehave-and-rspec-history/ JBehave and RSpec History] (Blog entry)&amp;lt;/ref&amp;gt; It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team Should not be possible if you exceed the max # of team members)&lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Fill in the box with invitation receiver name and click button send invitation. &lt;br /&gt;
After doing these steps, we expect fault would happen. We could capture contents ‘Your team already has max members.’ &lt;br /&gt;
* Scenario 2 : Team member  don't exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as the sender &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
On this page, we expect the receiver's name will appear.&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, or join the waiting list if the topic is not available. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# fill in all the required forms, and then click “save” to save our review. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# Execute the ‘Request a new submission’ button action  &lt;br /&gt;
# Check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out all text fields&lt;br /&gt;
# Select all scores from dropdowns&lt;br /&gt;
# Submit form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out some text fields&lt;br /&gt;
# Select some scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Reopen form&lt;br /&gt;
# Fill out remaining fields and scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Sign out&lt;br /&gt;
# Sign in as reviewer&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Other’s work’&lt;br /&gt;
# Check that a feedback exists.&lt;br /&gt;
&lt;br /&gt;
==External links==&lt;br /&gt;
 [http://rspec.info/ Official website]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=99988</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=99988"/>
		<updated>2015-11-17T02:03:56Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* External links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave.&amp;lt;ref name=&amp;quot;origin&amp;quot;&amp;gt;Ed Gibbs, [http://edgibbs.com/2007/12/02/jbehave-and-rspec-history/ JBehave and RSpec History] (Blog entry)&amp;lt;/ref&amp;gt; It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team Should not be possible if you exceed the max # of team members)&lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Fill in the box with invitation receiver name and click button send invitation. &lt;br /&gt;
After doing these steps, we expect fault would happen. We could capture contents ‘Your team already has max members.’ &lt;br /&gt;
* Scenario 2 : Team member  don't exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as the sender &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
On this page, we expect the receiver's name will appear.&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, or join the waiting list if the topic is not available. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# fill in all the required forms, and then click “save” to save our review. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# Execute the ‘Request a new submission’ button action  &lt;br /&gt;
# Check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out all text fields&lt;br /&gt;
# Select all scores from dropdowns&lt;br /&gt;
# Submit form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out some text fields&lt;br /&gt;
# Select some scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Reopen form&lt;br /&gt;
# Fill out remaining fields and scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Sign out&lt;br /&gt;
# Sign in as reviewer&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Other’s work’&lt;br /&gt;
# Check that a feedback exists.&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=99987</id>
		<title>CSC/ECE 517 Fall 2015 E1581 Integration testing for student interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015_E1581_Integration_testing_for_student_interface&amp;diff=99987"/>
		<updated>2015-11-17T02:03:39Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* External links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Create integration tests for the student interface using capybara and rspec. Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
To properly execute the integration tests we will write the test cases to mimic a user operating the system. We will create strong integration test cases to help ensure the outcome of application's student interface remains the same regardless of changes to its inner functionality. In an attempt to keep our tests DRY we will put common code in a support directory.&lt;br /&gt;
&lt;br /&gt;
== Testing tools ==&lt;br /&gt;
'''RSpec''' is a behavior-driven development (BDD) framework for the Ruby (programming language)|Ruby programming language, inspired by JBehave.&amp;lt;ref name=&amp;quot;origin&amp;quot;&amp;gt;Ed Gibbs, [http://edgibbs.com/2007/12/02/jbehave-and-rspec-history/ JBehave and RSpec History] (Blog entry)&amp;lt;/ref&amp;gt; It contains its own mocking framework that is fully integrated into the framework based upon JMock.&lt;br /&gt;
&lt;br /&gt;
'''Capybara''' is a web-based automation framework used for creating functional tests which can simulate how users would interact with your application.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
There are 8 features to be tested:&lt;br /&gt;
# Log in&lt;br /&gt;
# Add someone to a team Should not be possible if you exceed the max # of team members)&lt;br /&gt;
# Select a topic(if the assignment has topics)&lt;br /&gt;
# Select a submission to review For assignments with or without topics&lt;br /&gt;
# Bring up a review form&lt;br /&gt;
# Fill out &amp;amp; submit a review form&lt;br /&gt;
# View your scores&lt;br /&gt;
# Respond to a review (“author feedback”)&lt;br /&gt;
&lt;br /&gt;
=== Log in ===&lt;br /&gt;
we create a file called ‘student_signin_spec.rb’.  We define a method named login; and because we need this method in every later  feature test we will put this in the support directory.&lt;br /&gt;
* Scenario 1: Log in with ‘invalid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘Invalid username/password’ appear in the new page.&lt;br /&gt;
* Scenario 2: Log in with ‘valid combination of username and password’&lt;br /&gt;
When we sign in with correct name and password; we expect that there should be content ‘User: (username)’ appear in the new page.&lt;br /&gt;
&lt;br /&gt;
=== Add someone to a team ===&lt;br /&gt;
* Scenario 1: Team member exceed max amount&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Fill in the box with invitation receiver name and click button send invitation. &lt;br /&gt;
After doing these steps, we expect fault would happen. We could capture contents ‘Your team already has max members.’ &lt;br /&gt;
* Scenario 2 : Team member  don't exceed max amount&lt;br /&gt;
# Sign in &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team” &lt;br /&gt;
# Fill in the text area with invitation receiver name&lt;br /&gt;
# Click send invitation button&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as receiver&lt;br /&gt;
# Click link assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
# Click  button ‘accept’&lt;br /&gt;
# Sign out.&lt;br /&gt;
# Sign in as the sender &lt;br /&gt;
# Click link certain assignment&lt;br /&gt;
# Click link  “Your team”&lt;br /&gt;
On this page, we expect the receiver's name will appear.&lt;br /&gt;
&lt;br /&gt;
=== Select a topic ===&lt;br /&gt;
Note: assignment has topics&lt;br /&gt;
&lt;br /&gt;
We need the following steps:&lt;br /&gt;
# sign in. &lt;br /&gt;
# click the link for assignment &lt;br /&gt;
# click link  “signup sheet”&lt;br /&gt;
# click the sign up for the remaining topic we want, or join the waiting list if the topic is not available. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Select a submission to review ===&lt;br /&gt;
# sign in.  &lt;br /&gt;
# click the link for the assignment we want to review.&lt;br /&gt;
# click the link for “other’s work”&lt;br /&gt;
# click the link for the submission we want to review&lt;br /&gt;
# fill in all the required forms, and then click “save” to save our review. &lt;br /&gt;
# sign out &lt;br /&gt;
&lt;br /&gt;
=== Bring up a review form ===&lt;br /&gt;
Repeated for an assignment without a topic and an assignment with a topic&lt;br /&gt;
# Execute the ‘Request a new submission’ button action  &lt;br /&gt;
# Check that a review form has successfully been created&lt;br /&gt;
&lt;br /&gt;
=== Fill out and submit a review form ===&lt;br /&gt;
* Scenario 1:&lt;br /&gt;
Note: Do this for an assignment without a topic and an assignment with a topic.&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out all text fields&lt;br /&gt;
# Select all scores from dropdowns&lt;br /&gt;
# Submit form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
* Scenario 2:&lt;br /&gt;
# Open a review form&lt;br /&gt;
# Fill out some text fields&lt;br /&gt;
# Select some scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Reopen form&lt;br /&gt;
# Fill out remaining fields and scores&lt;br /&gt;
# Save form&lt;br /&gt;
# Check for successful save&lt;br /&gt;
&lt;br /&gt;
=== View your scores ===&lt;br /&gt;
* Scenario 1: No Scores available yet&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that nothing exists yet&lt;br /&gt;
# Check for dashes.&lt;br /&gt;
* Scenario 2: Scores available.&lt;br /&gt;
# Sign in&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Check that displayed scores match scores independently calculated from all reviews.&lt;br /&gt;
&lt;br /&gt;
=== Respond to a review (“author feedback”) ===&lt;br /&gt;
# Sign in as author&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Your scores’&lt;br /&gt;
# Click ‘show reviews’&lt;br /&gt;
# Click ‘Give feedback’&lt;br /&gt;
# Fill out Feedback form&lt;br /&gt;
# Click Save Feedback&lt;br /&gt;
# Sign out&lt;br /&gt;
# Sign in as reviewer&lt;br /&gt;
# Click link for Assignment&lt;br /&gt;
# Click ‘Other’s work’&lt;br /&gt;
# Check that a feedback exists.&lt;br /&gt;
&lt;br /&gt;
==External links==&lt;br /&gt;
 [http://rspec.info/ Official website]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=98127</id>
		<title>CSC/ECE 517 Fall 2015/ossE1568BZHXJS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=98127"/>
		<updated>2015-11-04T02:59:50Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* RUN TEST:  rspec spec/models/answer_spec.rb */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project, the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrote Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
&lt;br /&gt;
=RUN TEST with command in terminal:  rspec spec/models/answer_spec.rb=&lt;br /&gt;
&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Test from UI==&lt;br /&gt;
To verify that our code did not break the original functions. Sign in as instructor6 with password of 'password'  and go to 'Assignments' then pick an assignment; and check scores. The result remains same.&lt;br /&gt;
&lt;br /&gt;
=Relative Links=&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository]&lt;br /&gt;
#[http://52.10.11.33:3000  Deployment]&lt;br /&gt;
#[https://github.com/expertiza/expertiza/pull/584 Pull Request on GitHub]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=98126</id>
		<title>CSC/ECE 517 Fall 2015/ossE1568BZHXJS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=98126"/>
		<updated>2015-11-04T02:59:27Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* RUN the Test:  rspec spec/models/answer_spec.rb */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project, the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrote Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
&lt;br /&gt;
=RUN TEST:  rspec spec/models/answer_spec.rb=&lt;br /&gt;
&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Test from UI==&lt;br /&gt;
To verify that our code did not break the original functions. Sign in as instructor6 with password of 'password'  and go to 'Assignments' then pick an assignment; and check scores. The result remains same.&lt;br /&gt;
&lt;br /&gt;
=Relative Links=&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository]&lt;br /&gt;
#[http://52.10.11.33:3000  Deployment]&lt;br /&gt;
#[https://github.com/expertiza/expertiza/pull/584 Pull Request on GitHub]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=98125</id>
		<title>CSC/ECE 517 Fall 2015/ossE1568BZHXJS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=98125"/>
		<updated>2015-11-04T02:58:48Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Command to run the test: rspec spec/models/answer_spec.rb */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project, the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrote Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
&lt;br /&gt;
=RUN the Test:  rspec spec/models/answer_spec.rb=&lt;br /&gt;
&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Test from UI==&lt;br /&gt;
To verify that our code did not break the original functions. Sign in as instructor6 with password of 'password'  and go to 'Assignments' then pick an assignment; and check scores. The result remains same.&lt;br /&gt;
&lt;br /&gt;
=Relative Links=&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository]&lt;br /&gt;
#[http://52.10.11.33:3000  Deployment]&lt;br /&gt;
#[https://github.com/expertiza/expertiza/pull/584 Pull Request on GitHub]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=98124</id>
		<title>CSC/ECE 517 Fall 2015/ossE1568BZHXJS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=98124"/>
		<updated>2015-11-04T02:57:37Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Command to run the test: rspec spec/models/answer_spec.rb */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project, the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrote Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
&lt;br /&gt;
=Command to run the test: rspec spec/models/answer_spec.rb=&lt;br /&gt;
&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Test from UI==&lt;br /&gt;
To verify that our code did not break the original functions. Sign in as instructor6 with password of 'password'  and go to 'Assignments' then pick an assignment; and check scores. The result remains same.&lt;br /&gt;
&lt;br /&gt;
=Relative Links=&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository]&lt;br /&gt;
#[http://52.10.11.33:3000  Deployment]&lt;br /&gt;
#[https://github.com/expertiza/expertiza/pull/584 Pull Request on GitHub]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=98123</id>
		<title>CSC/ECE 517 Fall 2015/ossE1568BZHXJS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=98123"/>
		<updated>2015-11-04T02:53:32Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Test from UI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project, the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrote Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Test from UI==&lt;br /&gt;
To verify that our code did not break the original functions. Sign in as instructor6 with password of 'password'  and go to 'Assignments' then pick an assignment; and check scores. The result remains same.&lt;br /&gt;
&lt;br /&gt;
=Relative Links=&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository]&lt;br /&gt;
#[http://52.10.11.33:3000  Deployment]&lt;br /&gt;
#[https://github.com/expertiza/expertiza/pull/584 Pull Request on GitHub]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=98122</id>
		<title>CSC/ECE 517 Fall 2015/ossE1568BZHXJS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=98122"/>
		<updated>2015-11-04T02:53:04Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Test from UI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project, the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrote Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Test from UI==&lt;br /&gt;
To verify that our code did not break the original functions. Sign in as instructor6 with password of 'password'  and go to Assignments and pick an assignment; and check scores. The result remains same.&lt;br /&gt;
&lt;br /&gt;
=Relative Links=&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository]&lt;br /&gt;
#[http://52.10.11.33:3000  Deployment]&lt;br /&gt;
#[https://github.com/expertiza/expertiza/pull/584 Pull Request on GitHub]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=98121</id>
		<title>CSC/ECE 517 Fall 2015/ossE1568BZHXJS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=98121"/>
		<updated>2015-11-04T02:52:32Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project, the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrote Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Test from UI==&lt;br /&gt;
To verify that our code did not break the original functions. Sign in as instructor6 with password of 'password'  and go to Assignments and pick an assignment; and check scores. The result remains same.&lt;br /&gt;
&lt;br /&gt;
Go to Assignments&lt;br /&gt;
Pick an assignment, and check scores&lt;br /&gt;
=Relative Links=&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository]&lt;br /&gt;
#[http://52.10.11.33:3000  Deployment]&lt;br /&gt;
#[https://github.com/expertiza/expertiza/pull/584 Pull Request on GitHub]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=97224</id>
		<title>CSC/ECE 517 Fall 2015/ossE1568BZHXJS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=97224"/>
		<updated>2015-10-27T20:11:16Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Relative links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project, the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrote Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=Relative Links=&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository]&lt;br /&gt;
#[http://52.10.11.33:3000  Deployment]&lt;br /&gt;
#[https://github.com/expertiza/expertiza/pull/584 Pull Request on GitHub]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=97223</id>
		<title>CSC/ECE 517 Fall 2015/ossE1568BZHXJS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=97223"/>
		<updated>2015-10-27T20:08:54Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Relative links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project, the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrote Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=Relative links=&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository]&lt;br /&gt;
#[http://52.10.11.33:3000  Deployment]&lt;br /&gt;
#[https://github.com/expertiza/expertiza/pull/584 Pull Request on GitHub]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=97222</id>
		<title>CSC/ECE 517 Fall 2015/ossE1568BZHXJS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=97222"/>
		<updated>2015-10-27T20:08:07Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Relative links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project, the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrote Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=Relative links=&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository]&lt;br /&gt;
#[https://52.10.11.33:3000  Deployment]&lt;br /&gt;
#[https://github.com/expertiza/expertiza/pull/584 Pull Request on GitHub]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=97221</id>
		<title>CSC/ECE 517 Fall 2015/ossE1568BZHXJS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=97221"/>
		<updated>2015-10-27T20:07:30Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project, the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrote Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=Relative links=&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository]&lt;br /&gt;
#[52.10.11.33:3000  Deployment]&lt;br /&gt;
#[https://github.com/expertiza/expertiza/pull/584 Pull Request on GitHub]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=97220</id>
		<title>CSC/ECE 517 Fall 2015/ossE1568BZHXJS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=97220"/>
		<updated>2015-10-27T19:42:11Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Rewrite Line 89 long SQL */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project, the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrote Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository Fork]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=97219</id>
		<title>CSC/ECE 517 Fall 2015/ossE1568BZHXJS</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015/ossE1568BZHXJS&amp;diff=97219"/>
		<updated>2015-10-27T19:39:42Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: Created page with &amp;quot;== E1568. Remove AnswersController==   = Introduction = Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc)...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project, the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrite Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository Fork]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015&amp;diff=97218</id>
		<title>CSC/ECE 517 Fall 2015</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015&amp;diff=97218"/>
		<updated>2015-10-27T19:38:58Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Writing Assignment 2==&lt;br /&gt;
*[[CSC/ECE_517_Fall_2015/sample_page]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2015/ossE1558BGJ]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2015/oss/M1502/AAAASS]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2015/oss/M1503/IntegrateXMLParser]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2015/ossE1568BZHXJS]]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97217</id>
		<title>User:Hxia3</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97217"/>
		<updated>2015-10-27T19:31:50Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Refactored self.compute_scores method */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CSC/ECE_517_Fall_2015/ossE1568BZHXJS&lt;br /&gt;
== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project, the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrite Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository Fork]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97216</id>
		<title>User:Hxia3</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97216"/>
		<updated>2015-10-27T19:31:37Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Command to run the test: rspec spec/models/answer_spec.rb */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CSC/ECE_517_Fall_2015/ossE1568BZHXJS&lt;br /&gt;
== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project , the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrite Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository Fork]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97215</id>
		<title>User:Hxia3</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97215"/>
		<updated>2015-10-27T19:31:18Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Command to run the test: rspec spec/models/answer_spec.rb */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CSC/ECE_517_Fall_2015/ossE1568BZHXJS&lt;br /&gt;
== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project , the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrite Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository Fork]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97214</id>
		<title>User:Hxia3</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97214"/>
		<updated>2015-10-27T19:30:57Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Command to run the test: rspec spec/models/answer_spec.rb */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CSC/ECE_517_Fall_2015/ossE1568BZHXJS&lt;br /&gt;
== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project , the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrite Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_scores'&lt;br /&gt;
    describe 'compute_scores' do&lt;br /&gt;
      context 'when assessment is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          question=Question.new(&lt;br /&gt;
              txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
              weight: 1,&lt;br /&gt;
              questionnaire_id: 200,&lt;br /&gt;
              type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
              break_before: true)&lt;br /&gt;
          assessment = 'Assessment'&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          allow(Answer).to receive(:compute_stat).and_return([100, scores1])&lt;br /&gt;
          expect(Answer.compute_scores([assessment], [question])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when assessment is nil' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_scores(nil, nil)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'computer_quiz_scores'&lt;br /&gt;
    describe 'compute_quiz_scores' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is not nil' do&lt;br /&gt;
        it 'should return valid scores' do&lt;br /&gt;
          responses=Response.new&lt;br /&gt;
          responses.id=1000&lt;br /&gt;
          responses.created_at = DateTime.current&lt;br /&gt;
          responses.updated_at = DateTime.current&lt;br /&gt;
          responses.map_id=1&lt;br /&gt;
          responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
          responses.version_num=1&lt;br /&gt;
                &lt;br /&gt;
          allow(QuizQuestionnaire).to receive(:find)&lt;br /&gt;
          allow(nil).to receive(:questions)&lt;br /&gt;
          allow(nil).to receive(:reviewed_object_id)&lt;br /&gt;
          allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
          scores1 = {max: 100, min: 100, avg: 100}&lt;br /&gt;
          expect(Answer.compute_quiz_scores([responses])).to eq scores1&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context 'when responses is empty' do&lt;br /&gt;
        it 'should return nil for score hash' do&lt;br /&gt;
          responses = []&lt;br /&gt;
          scores2 = {max: nil, min: nil, avg: nil}&lt;br /&gt;
          expect(Answer.compute_quiz_scores(responses)).to eq scores2&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow(Answer).to receive(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        allow(ScoreView).to receive(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'compute_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        allow(Answer).to receive(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'submission valid'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        allow_message_expectations_on_nil&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
    &lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        allow(ResponseMap).to receive(:find).and_return(map)&lt;br /&gt;
        allow(map).to receive(:reviewed_object_id)&lt;br /&gt;
        allow(map).to receive(:reviewee_id)&lt;br /&gt;
        allow(DueDate).to receive(:where).and_return(sorted_deadlines)&lt;br /&gt;
        allow(sorted_deadlines).to receive(:order).and_return(sorted_deadlines)&lt;br /&gt;
        allow(ResubmissionTime).to receive(:where)&lt;br /&gt;
        allow(nil).to receive(:order)&lt;br /&gt;
        allow(Answer).to receive(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
    &lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        allow(@responses).to receive(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    #Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
    &lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository Fork]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97213</id>
		<title>User:Hxia3</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97213"/>
		<updated>2015-10-27T19:27:31Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Unit tests using Rspec */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CSC/ECE_517_Fall_2015/ossE1568BZHXJS&lt;br /&gt;
== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project , the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrite Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        Answer.stub(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        ScoreView.stub(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'computer_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        Answer.stub(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
  &lt;br /&gt;
  # Unit test for 'submission_valid?'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        ResponseMap.stub(:find).and_return(map)&lt;br /&gt;
        map.stub(:reviewed_object_id)&lt;br /&gt;
        map.stub(:reviewee_id)&lt;br /&gt;
        DueDate.stub(:where).and_return(sorted_deadlines)&lt;br /&gt;
        sorted_deadlines.stub(:order).and_return(sorted_deadlines)&lt;br /&gt;
        ResubmissionTime.stub(:where)&lt;br /&gt;
        nil.stub(:order)&lt;br /&gt;
        Answer.stub(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository Fork]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97212</id>
		<title>User:Hxia3</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97212"/>
		<updated>2015-10-27T19:26:15Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Refactored &amp;quot;submission_valid?&amp;quot; method */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CSC/ECE_517_Fall_2015/ossE1568BZHXJS&lt;br /&gt;
== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project , the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
We found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;.  See the changes below:&lt;br /&gt;
====Command to run the test: rspec spec/models/answer_spec.rb====&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrite Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        Answer.stub(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        ScoreView.stub(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'computer_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        Answer.stub(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
  &lt;br /&gt;
  # Unit test for 'submission_valid?'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        ResponseMap.stub(:find).and_return(map)&lt;br /&gt;
        map.stub(:reviewed_object_id)&lt;br /&gt;
        map.stub(:reviewee_id)&lt;br /&gt;
        DueDate.stub(:where).and_return(sorted_deadlines)&lt;br /&gt;
        sorted_deadlines.stub(:order).and_return(sorted_deadlines)&lt;br /&gt;
        ResubmissionTime.stub(:where)&lt;br /&gt;
        nil.stub(:order)&lt;br /&gt;
        Answer.stub(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository Fork]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97209</id>
		<title>User:Hxia3</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97209"/>
		<updated>2015-10-27T04:18:42Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Refactored self.submission_valid? method */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CSC/ECE_517_Fall_2015/ossE1568BZHXJS&lt;br /&gt;
== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project , the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Refactored &amp;quot;submission_valid?&amp;quot; method==&lt;br /&gt;
we found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;. See the changes below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrite Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        Answer.stub(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        ScoreView.stub(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'computer_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        Answer.stub(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
  &lt;br /&gt;
  # Unit test for 'submission_valid?'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        ResponseMap.stub(:find).and_return(map)&lt;br /&gt;
        map.stub(:reviewed_object_id)&lt;br /&gt;
        map.stub(:reviewee_id)&lt;br /&gt;
        DueDate.stub(:where).and_return(sorted_deadlines)&lt;br /&gt;
        sorted_deadlines.stub(:order).and_return(sorted_deadlines)&lt;br /&gt;
        ResubmissionTime.stub(:where)&lt;br /&gt;
        nil.stub(:order)&lt;br /&gt;
        Answer.stub(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository Fork]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97208</id>
		<title>User:Hxia3</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97208"/>
		<updated>2015-10-27T04:16:56Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Unit tests using Rspec */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CSC/ECE_517_Fall_2015/ossE1568BZHXJS&lt;br /&gt;
== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project , the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Refactored self.submission_valid? method==&lt;br /&gt;
we found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;. See the changes below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrite Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        Answer.stub(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        ScoreView.stub(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'computer_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        Answer.stub(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
  &lt;br /&gt;
  # Unit test for 'submission_valid?'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        ResponseMap.stub(:find).and_return(map)&lt;br /&gt;
        map.stub(:reviewed_object_id)&lt;br /&gt;
        map.stub(:reviewee_id)&lt;br /&gt;
        DueDate.stub(:where).and_return(sorted_deadlines)&lt;br /&gt;
        sorted_deadlines.stub(:order).and_return(sorted_deadlines)&lt;br /&gt;
        ResubmissionTime.stub(:where)&lt;br /&gt;
        nil.stub(:order)&lt;br /&gt;
        Answer.stub(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository Fork]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97207</id>
		<title>User:Hxia3</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97207"/>
		<updated>2015-10-27T04:16:15Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Unit tests using Rspec */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CSC/ECE_517_Fall_2015/ossE1568BZHXJS&lt;br /&gt;
== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project , the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Refactored self.submission_valid? method==&lt;br /&gt;
we found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;. See the changes below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrite Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        Answer.stub(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        ScoreView.stub(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'computer_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        Answer.stub(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
   # Unit test for 'submission_valid?'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        ResponseMap.stub(:find).and_return(map)&lt;br /&gt;
        map.stub(:reviewed_object_id)&lt;br /&gt;
        map.stub(:reviewee_id)&lt;br /&gt;
        DueDate.stub(:where).and_return(sorted_deadlines)&lt;br /&gt;
        sorted_deadlines.stub(:order).and_return(sorted_deadlines)&lt;br /&gt;
        ResubmissionTime.stub(:where)&lt;br /&gt;
        nil.stub(:order)&lt;br /&gt;
        Answer.stub(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository Fork]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97206</id>
		<title>User:Hxia3</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97206"/>
		<updated>2015-10-27T04:13:21Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Refactored self.submission_valid? method */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CSC/ECE_517_Fall_2015/ossE1568BZHXJS&lt;br /&gt;
== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project , the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Refactored self.submission_valid? method==&lt;br /&gt;
we found some parts of codes in the 'self.submission_valid?' method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as 'latest_review_deadline&amp;quot;. See the changes below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrite Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        Answer.stub(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        ScoreView.stub(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'computer_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        Answer.stub(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    # Unit test for 'submission_valid?'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        ResponseMap.stub(:find).and_return(map)&lt;br /&gt;
        map.stub(:reviewed_object_id)&lt;br /&gt;
        map.stub(:reviewee_id)&lt;br /&gt;
        DueDate.stub(:where).and_return(sorted_deadlines)&lt;br /&gt;
        sorted_deadlines.stub(:order).and_return(sorted_deadlines)&lt;br /&gt;
        ResubmissionTime.stub(:where)&lt;br /&gt;
        nil.stub(:order)&lt;br /&gt;
        Answer.stub(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository Fork]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97205</id>
		<title>User:Hxia3</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97205"/>
		<updated>2015-10-27T04:12:42Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Rewrite Line 89 long SQL */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CSC/ECE_517_Fall_2015/ossE1568BZHXJS&lt;br /&gt;
== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project , the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Refactored self.submission_valid? method==&lt;br /&gt;
we found some parts of codes in the self.submission_valid? method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as &amp;quot;self.latest_review_deadline&amp;quot;. See the changes below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrite Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violates the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        Answer.stub(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        ScoreView.stub(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'computer_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        Answer.stub(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    # Unit test for 'submission_valid?'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        ResponseMap.stub(:find).and_return(map)&lt;br /&gt;
        map.stub(:reviewed_object_id)&lt;br /&gt;
        map.stub(:reviewee_id)&lt;br /&gt;
        DueDate.stub(:where).and_return(sorted_deadlines)&lt;br /&gt;
        sorted_deadlines.stub(:order).and_return(sorted_deadlines)&lt;br /&gt;
        ResubmissionTime.stub(:where)&lt;br /&gt;
        nil.stub(:order)&lt;br /&gt;
        Answer.stub(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository Fork]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97204</id>
		<title>User:Hxia3</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97204"/>
		<updated>2015-10-27T01:33:24Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CSC/ECE_517_Fall_2015/ossE1568BZHXJS&lt;br /&gt;
== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project , the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Refactored self.submission_valid? method==&lt;br /&gt;
we found some parts of codes in the self.submission_valid? method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as &amp;quot;self.latest_review_deadline&amp;quot;. See the changes below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrite Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violated the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        Answer.stub(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        ScoreView.stub(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'computer_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        Answer.stub(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    # Unit test for 'submission_valid?'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        ResponseMap.stub(:find).and_return(map)&lt;br /&gt;
        map.stub(:reviewed_object_id)&lt;br /&gt;
        map.stub(:reviewee_id)&lt;br /&gt;
        DueDate.stub(:where).and_return(sorted_deadlines)&lt;br /&gt;
        sorted_deadlines.stub(:order).and_return(sorted_deadlines)&lt;br /&gt;
        ResubmissionTime.stub(:where)&lt;br /&gt;
        nil.stub(:order)&lt;br /&gt;
        Answer.stub(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/junjieshen/expertiza GitHub Project Repository Fork]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97203</id>
		<title>User:Hxia3</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=User:Hxia3&amp;diff=97203"/>
		<updated>2015-10-27T01:30:57Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: Created page with &amp;quot;CSC/ECE_517_Fall_2015/ossE1568BZHXJS == E1568. Remove AnswersController==   = Introduction = Expertiza is a web application where students can submit and peer-review learning obj...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CSC/ECE_517_Fall_2015/ossE1568BZHXJS&lt;br /&gt;
== E1568. Remove AnswersController==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This page provides a description of the Expertiza based on OSS project. As the project, our team members successfully removed the answer controller, split confusing methods and provided all unit test in the Answer model. Changes can be found in the Answer.rb file which locates in expertiza/app/models/.&lt;br /&gt;
&lt;br /&gt;
= Problem Statement =&lt;br /&gt;
There is a answer.rb file which handle all methods related to answer calculations. But there is no related view file related to AnswerController. All methods in it are show,action_allowed? and calculate_all_penalties. It is obvious that calculate_all_penalties method has already been deployed in GradesController. So we can get rid of calculate_all_penalties in AnswersController. Action_allowed? method is used to set the access authorization for different users.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
==Remove AnswersController.rb==&lt;br /&gt;
Because there is not show view page related to show method. So we can remove AnswerController. This can be checked in the controllers folder.&lt;br /&gt;
&lt;br /&gt;
==Refactored self.compute_scores method==&lt;br /&gt;
As described in OSS project , the self.compute_scores method is complex. Followed the principle that one method only do one thing, we split the the self.compute_scores by adding a method called self.compute_stat to take on some responsibilities from the self.compute_scores method, namely, computing the current score.  Specific changes before and after are shown below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
  class Answer &amp;lt; ActiveRecord::Base&lt;br /&gt;
  belongs_to :question&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
  def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil?&amp;amp;&amp;amp;assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments=assessments.length.to_f&lt;br /&gt;
      assessments.each { |assessment|&lt;br /&gt;
        curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
        if curr_score &amp;gt; scores[:max]&lt;br /&gt;
          scores[:max] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        if curr_score &amp;lt; scores[:min]&lt;br /&gt;
          scores[:min] = curr_score&lt;br /&gt;
        end&lt;br /&gt;
        # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
        if  @invalid==1&lt;br /&gt;
          length_of_assessments=length_of_assessments-1&lt;br /&gt;
          curr_score=0&lt;br /&gt;
        end&lt;br /&gt;
        total_score += curr_score&lt;br /&gt;
      }&lt;br /&gt;
      if (length_of_assessments!=0)&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg]=0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;compute_scores&amp;quot;====&lt;br /&gt;
  # Computes the total score for a *list of assessments*&lt;br /&gt;
  # parameters&lt;br /&gt;
  #  assessments - a list of assessments of some type (e.g., author feedback, teammate review)&lt;br /&gt;
  #  questions - the list of questions that was filled out in the process of doing those assessments&lt;br /&gt;
   def self.compute_scores(assessments, questions)&lt;br /&gt;
    scores = Hash.new&lt;br /&gt;
    if !assessments.nil? &amp;amp;&amp;amp; assessments.length &amp;gt; 0&lt;br /&gt;
      scores[:max] = -999999999&lt;br /&gt;
      scores[:min] = 999999999&lt;br /&gt;
      total_score = 0&lt;br /&gt;
      length_of_assessments = assessments.length.to_f&lt;br /&gt;
      assessments.each do |assessment|&lt;br /&gt;
        current_score, scores = compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
        total_score += current_score&lt;br /&gt;
      end&lt;br /&gt;
      if length_of_assessments != 0&lt;br /&gt;
        scores[:avg] = total_score.to_f / length_of_assessments&lt;br /&gt;
      else&lt;br /&gt;
        scores[:avg] = 0&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      scores[:max] = nil&lt;br /&gt;
      scores[:min] = nil&lt;br /&gt;
      scores[:avg] = nil&lt;br /&gt;
    end&lt;br /&gt;
    return scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==== Method &amp;quot;compute_stat&amp;quot; ====&lt;br /&gt;
  def self.compute_stat(assessment, questions, scores, length_of_assessments)&lt;br /&gt;
    curr_score = get_total_score(:response =&amp;gt; [assessment], :questions =&amp;gt; questions)&lt;br /&gt;
    if curr_score &amp;gt; scores[:max]&lt;br /&gt;
      scores[:max] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    if curr_score &amp;lt; scores[:min]&lt;br /&gt;
      scores[:min] = curr_score&lt;br /&gt;
    end&lt;br /&gt;
    # Check if the review is invalid. If is not valid do not include in score calculation&lt;br /&gt;
    if @invalid == 1&lt;br /&gt;
      length_of_assessments = length_of_assessments - 1&lt;br /&gt;
      curr_score = 0&lt;br /&gt;
    end&lt;br /&gt;
    return curr_score, scores&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Refactored self.submission_valid? method==&lt;br /&gt;
we found some parts of codes in the self.submission_valid? method can be taken out as a individual method.  To fulfill the function which calculates the latest review phase start time, we named this method as &amp;quot;self.latest_review_deadline&amp;quot;. See the changes below:&lt;br /&gt;
&lt;br /&gt;
===Before changes===&lt;br /&gt;
    def self.submission_valid?(response)&lt;br /&gt;
      if response&lt;br /&gt;
        map=ResponseMap.find(response.map_id)&lt;br /&gt;
        #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
        @sorted_deadlines = nil&lt;br /&gt;
        @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
        # to check the validity of the response&lt;br /&gt;
        if @sorted_deadlines.nil?&lt;br /&gt;
          #find the latest review deadline&lt;br /&gt;
          #less than current time&lt;br /&gt;
          flag = 0&lt;br /&gt;
          latest_review_phase_start_time = nil&lt;br /&gt;
          current_time = Time.new&lt;br /&gt;
          for deadline in @sorted_deadlines&lt;br /&gt;
            # if flag is set then we saw a review deadline in the&lt;br /&gt;
            # previous iteration - check if this deadline is a past&lt;br /&gt;
            # deadline&lt;br /&gt;
            if ((flag == 1) &amp;amp;&amp;amp; (deadline.due_at &amp;lt;= current_time))&lt;br /&gt;
              latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
              break&lt;br /&gt;
            else&lt;br /&gt;
              flag = 0&lt;br /&gt;
            end&lt;br /&gt;
            # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
            # to check if it is past&lt;br /&gt;
            if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)&lt;br /&gt;
              flag = 1&lt;br /&gt;
            end&lt;br /&gt;
          end&lt;br /&gt;
          resubmission_times =   ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
          if response .is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
            @invalid = 0&lt;br /&gt;
          else&lt;br /&gt;
            @invalid = 1&lt;br /&gt;
          end&lt;br /&gt;
          return @invalid&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===After changes===&lt;br /&gt;
====Method &amp;quot;latest_review_deadline&amp;quot;====&lt;br /&gt;
  def self.latest_review_deadline(sorted_deadlines)&lt;br /&gt;
    flag = 0&lt;br /&gt;
    latest_review_phase_start_time = nil&lt;br /&gt;
    current_time = Time.new&lt;br /&gt;
    for deadline in sorted_deadlines&lt;br /&gt;
      # if flag is set then we saw a review deadline in the&lt;br /&gt;
      # previous iteration - check if this deadline is a past&lt;br /&gt;
      # deadline&lt;br /&gt;
      if flag == 1 &amp;amp;&amp;amp; deadline.due_at &amp;lt;= current_time&lt;br /&gt;
        latest_review_phase_start_time = deadline.due_at&lt;br /&gt;
        break&lt;br /&gt;
      else&lt;br /&gt;
        flag = 0&lt;br /&gt;
      end&lt;br /&gt;
      # we found a review or re-review deadline - examine the next deadline&lt;br /&gt;
      # to check if it is past&lt;br /&gt;
      if deadline.deadline_type_id == 4 || deadline.deadline_type_id == 2&lt;br /&gt;
        flag = 1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    return latest_review_phase_start_time&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
====Method &amp;quot;submission_valid?&amp;quot; ====&lt;br /&gt;
  def self.submission_valid?(response)&lt;br /&gt;
    if response&lt;br /&gt;
      map=ResponseMap.find(response.map_id)&lt;br /&gt;
      #assignment_participant = Participant.where([&amp;quot;id = ?&amp;quot;, map.reviewee_id])&lt;br /&gt;
      @sorted_deadlines = nil&lt;br /&gt;
      @sorted_deadlines = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, map.reviewed_object_id]).order('due_at DESC')&lt;br /&gt;
      # to check the validity of the response&lt;br /&gt;
      if !@sorted_deadlines.nil?&lt;br /&gt;
        latest_review_phase_start_time = latest_review_deadline(@sorted_deadlines)&lt;br /&gt;
        resubmission_times = ResubmissionTime.where(participant_id: map.reviewee_id).order('resubmitted_at DESC')&lt;br /&gt;
        if response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)&lt;br /&gt;
          @invalid = 0&lt;br /&gt;
        else&lt;br /&gt;
          @invalid = 1&lt;br /&gt;
        end&lt;br /&gt;
        return @invalid&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Changed code to Rails 4 format==&lt;br /&gt;
Line 89 SQL query uses 'find_by_sql' which is not in accord with Rails 4 format and we substituted it with 'where'; which can be reflected in Line 93 in our case. &lt;br /&gt;
&lt;br /&gt;
==Rewrite Line 89 long SQL==&lt;br /&gt;
Since Line 89 SQL is too long, which violated the rule that code should be readable; thus we take the following measures:&lt;br /&gt;
     questionnaire_data = ScoreView.where(type: 'Scale', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
     questionnaire_data += ScoreView.where(type: 'Criterion', q1_id: @questions[0].questionnaire_id, s_response_id: @response.id)&lt;br /&gt;
&lt;br /&gt;
==Unit tests using Rspec==&lt;br /&gt;
There are six methods in the new version of answer.rb; so we performed six unit tests. The test file for Answer model is answer_spec.rb which can be found in the directory: expertiza/spec/models/ . Below is the unit test code:&lt;br /&gt;
&lt;br /&gt;
    require 'rspec'&lt;br /&gt;
    require_relative '../rails_helper'&lt;br /&gt;
    #Unit test for 'get_total_score'&lt;br /&gt;
    describe 'get_total_score' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        Answer.stub(:submission_valid?)&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        @question=Question.new(&lt;br /&gt;
            txt: &amp;quot;qusetionaaaaa&amp;quot;,&lt;br /&gt;
            weight: 1,&lt;br /&gt;
            questionnaire_id: 200,&lt;br /&gt;
            type: &amp;quot;Criterion&amp;quot;,&lt;br /&gt;
            break_before: true)&lt;br /&gt;
      }&lt;br /&gt;
      it 'should return weighted total score when sum_of_weights &amp;gt; 0 &amp;amp;&amp;amp; max_question_score' do&lt;br /&gt;
        score = ScoreView.new(:type =&amp;gt; 'Criterion',&lt;br /&gt;
                              :q1_id =&amp;gt; @question.questionnaire_id,&lt;br /&gt;
                              :s_response_id =&amp;gt; @responses.id,&lt;br /&gt;
                              :question_weight =&amp;gt; 1,&lt;br /&gt;
                              :s_score =&amp;gt; 5,&lt;br /&gt;
                              :q1_max_question_score =&amp;gt; 5)&lt;br /&gt;
        ScoreView.stub(:where).and_return([score])&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq 100&lt;br /&gt;
      end&lt;br /&gt;
      it 'should return -1 when sum_of_weights &amp;lt;= 0 or max_question_score does not exist' do&lt;br /&gt;
        expect(Answer.get_total_score(:response =&amp;gt; [@responses], :questions =&amp;gt; [@question])).to eq -1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Unit test for 'compute_stat'&lt;br /&gt;
    describe 'computer_stat' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        @scores = {max: -999999999, min: 999999999}&lt;br /&gt;
        Answer.stub(:get_total_score).and_return(100)&lt;br /&gt;
      }&lt;br /&gt;
      context &amp;quot;when invalid is 1&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 1)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [0, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      context &amp;quot;when invalid is 0&amp;quot; do&lt;br /&gt;
        it 'should return current score and scores' do&lt;br /&gt;
          Answer.instance_variable_set(:@invalid, 0)&lt;br /&gt;
          expect(Answer.compute_stat(nil, nil, @scores, 5)).to eq [100, @scores]&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    # Unit test for 'submission_valid?'&lt;br /&gt;
    describe 'submission valid' do&lt;br /&gt;
      before(:each) {&lt;br /&gt;
        late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
        sorted_deadlines = [late_due, early_due]&lt;br /&gt;
        @responses=Response.new&lt;br /&gt;
        @responses.id=1000&lt;br /&gt;
        @responses.created_at = DateTime.current&lt;br /&gt;
        @responses.updated_at = DateTime.current&lt;br /&gt;
        @responses.map_id=1&lt;br /&gt;
        @responses.additional_comment=&amp;quot;additional_comment&amp;quot;&lt;br /&gt;
        @responses.version_num=1&lt;br /&gt;
        map=double(:ResponseMap)&lt;br /&gt;
        ResponseMap.stub(:find).and_return(map)&lt;br /&gt;
        map.stub(:reviewed_object_id)&lt;br /&gt;
        map.stub(:reviewee_id)&lt;br /&gt;
        DueDate.stub(:where).and_return(sorted_deadlines)&lt;br /&gt;
        sorted_deadlines.stub(:order).and_return(sorted_deadlines)&lt;br /&gt;
        ResubmissionTime.stub(:where)&lt;br /&gt;
        nil.stub(:order)&lt;br /&gt;
        Answer.stub(:latest_review_deadline)&lt;br /&gt;
      }&lt;br /&gt;
      it 'invalid should be 1' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(false)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 1&lt;br /&gt;
      end&lt;br /&gt;
      it 'invalid should be 0' do&lt;br /&gt;
        @responses.stub(:is_valid_for_score_calculation?).and_return(true)&lt;br /&gt;
        expect(Answer.submission_valid?(@responses)).to eq 0&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Unit test for 'latest review deadline'&lt;br /&gt;
    describe 'latest review deadline' do&lt;br /&gt;
      late_due = DueDate.new(due_at: Time.parse(&amp;quot;2020-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      early_due = DueDate.new(due_at: Time.parse(&amp;quot;2010-10-30&amp;quot;), deadline_type_id: 2)&lt;br /&gt;
      sorted_deadlines = [late_due, early_due]&lt;br /&gt;
      it 'should return early due date' do&lt;br /&gt;
        expect(Answer.latest_review_deadline(sorted_deadlines)).to eq early_due.due_at&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015&amp;diff=97197</id>
		<title>CSC/ECE 517 Fall 2015</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015&amp;diff=97197"/>
		<updated>2015-10-26T22:21:37Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Writing Assignment 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Writing Assignment 2==&lt;br /&gt;
*[[CSC/ECE_517_Fall_2015/sample_page]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2015/ossE1558BGJ]]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015&amp;diff=97196</id>
		<title>CSC/ECE 517 Fall 2015</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2015&amp;diff=97196"/>
		<updated>2015-10-26T22:20:58Z</updated>

		<summary type="html">&lt;p&gt;Hxia3: /* Writing Assignment 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Writing Assignment 2==&lt;br /&gt;
*[[CSC/ECE_517_Fall_2015/sample_page]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2015/ossE1558BGJ]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2015/oss]]&lt;/div&gt;</summary>
		<author><name>Hxia3</name></author>
	</entry>
</feed>