back-end grade calculator supports grading period weighting

closes CNVS-34105

test plan:

- Setup -
1. At the account-level, create a new grading period set that uses
   weighted grading periods. Attach the default enrollment term to this
   set.
2. Create a grading period (GP1) that runs from January 1, 2017 to June
   30, 2017. Give it a weight of 75%.
3. Create a grading period (GP2) that runs from July 1, 2017 to
   December 31, 2017. Give it a weight of 25%.
4. Create a course that belongs to the default enrollment term from
   step 1. Enroll one student in the course. Make sure that student is
   enrolled in at least one other course.
5. In the course settings, enable Multiple Grading Periods and enable
   Display ‘All Grading Period’ Totals.
6. In the course, create an assignment (Assignment in GP1) that is
   worth 10 points and due for everyone on March 15, 2017.
7. In the course, create an assignment (Assignment in GP2) that is
   worth 10 points and due for everyone on September 15, 2017.
8. Go to the gradebook and give the student 5/10 on Assignment in GP1
   and 10/10 on Assignment in GP2. Ignore the totals that show up in
   the gradebook.

- Grade Verification -
1.  Sign in as the student and go to the /grades page.
2.  Verify the grade for GP1 is 50%.
3.  Verify the grade for GP2 is 100%.
4.  Verify the grade for ‘All Grading Periods’ is 62.5%.
5.  Sign in as the account admin. Change the weight for GP1 to 20% and
    change the weight for GP2 to 40%.
6.  Sign in as the student and go to the /grades page.
7.  Verify the grade for GP1 is 50%.
8.  Verify the grade for GP2 is 100%.
9.  Verify the grade for ‘All Grading Periods’ is 83.33%.
10. Sign in as the account admin. Change the weight for GP1 to 100% and
    change the weight for GP2 to 100%.
11. Sign in as the student and go to the /grades page.
12. Verify the grade for GP1 is 50%.
13. Verify the grade for GP2 is 100%.
14. Verify the grade for ‘All Grading Periods’ is 150%.
15. Sign in as the account admin. Change the weight for GP1 to 100% and
    change the weight for GP2 to 0%.
16. Sign in as the student and go to the /grades page.
17. Verify the grade for GP1 is 50%.
18. Verify the grade for GP2 is 100%.
19. Verify the grade for ‘All Grading Periods’ is 50%.
20. Sign in as the account admin. Change the weight for GP1 to 0% and
    change the weight for GP2 to 0%.
21. Sign in as the student and go to the /grades page.
22. Verify the grade for GP1 is 50%.
23. Verify the grade for GP2 is 100%.
24. Verify the grade for ‘All Grading Periods’ is 0%.
25. Sign in as the account admin. Uncheck the box on the grading period
    set for ‘weighting’.
26. Sign in as the student and go to the /grades page.
27. Verify the grade for GP1 is 50%.
28. Verify the grade for GP2 is 100%.
29. Verify the grade for ‘All Grading Periods’ is 75%.

Change-Id: Iac23e92986f371b13de2d5e0524d6bed8a277bc4
Reviewed-on: https://gerrit.instructure.com/99040
Reviewed-by: Derek Bender <djbender@instructure.com>
Tested-by: Jenkins
Reviewed-by: Jeremy Neander <jneander@instructure.com>
QA-Review: KC Naegle <knaegle@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
This commit is contained in:
Spencer Olson 2017-01-03 13:59:14 -06:00
parent fe7b0b2b0a
commit 74d948ff3b
4 changed files with 383 additions and 73 deletions

View File

@ -1,5 +1,5 @@
#
# Copyright (C) 2011 - 2014 Instructure, Inc.
# Copyright (C) 2011 - 2017 Instructure, Inc.
#
# This file is part of Canvas.
#
@ -65,33 +65,18 @@ class GradeCalculator
def compute_scores
@submissions = @course.submissions.
except(:order, :select).
for_user(@user_ids).
where(assignment_id: @assignments).
select("submissions.id, user_id, assignment_id, score, excused, submissions.workflow_state")
submissions_by_user = @submissions.group_by(&:user_id)
result = []
except(:order, :select).
for_user(@user_ids).
where(assignment_id: @assignments).
select("submissions.id, user_id, assignment_id, score, excused, submissions.workflow_state")
scores_and_group_sums = []
@user_ids.each_slice(100) do |batched_ids|
load_assignment_visibilities_for_users(batched_ids)
batched_ids.each do |user_id|
user_submissions = submissions_by_user[user_id] || []
user_submissions.select!{|s| assignment_ids_visible_to_user(user_id).include?(s.assignment_id)}
current, current_groups = calculate_current_score(user_id, user_submissions)
final, final_groups = calculate_final_score(user_id, user_submissions)
scores = {
current: current,
current_groups: current_groups,
final: final,
final_groups: final_groups
}
result << scores
end
scores_and_group_sums_batch = compute_scores_and_group_sums_for_batch(batched_ids)
scores_and_group_sums.concat(scores_and_group_sums_batch)
clear_assignment_visibilities_cache
end
result
scores_and_group_sums
end
def compute_and_save_scores
@ -103,8 +88,114 @@ class GradeCalculator
private
def compute_scores_and_group_sums_for_batch(user_ids)
user_ids.map do |user_id|
group_sums = compute_group_sums_for_user(user_id)
scores = compute_scores_for_user(user_id, group_sums)
update_changes_hash_for_user(user_id, scores)
{
current: scores[:current],
current_groups: group_sums[:current].index_by { |group| group[:id] },
final: scores[:final],
final_groups: group_sums[:final].index_by { |group| group[:id] }
}
end
end
def compute_group_sums_for_user(user_id)
user_submissions = submissions_by_user.fetch(user_id, []).select do |submission|
assignment_ids_visible_to_user(user_id).include?(submission.assignment_id)
end
{
current: create_group_sums(user_submissions, user_id, ignore_ungraded: true),
final: create_group_sums(user_submissions, user_id, ignore_ungraded: false)
}
end
def compute_scores_for_user(user_id, group_sums)
if compute_course_scores_from_weighted_grading_periods?
scores = calculate_total_from_weighted_grading_periods(user_id)
else
scores = {
current: calculate_total_from_group_scores(group_sums[:current]),
final: calculate_total_from_group_scores(group_sums[:final])
}
end
Rails.logger.info "GRADES: calculated: #{scores.inspect}"
scores
end
def update_changes_hash_for_user(user_id, scores)
@current_updates[user_id] = scores[:current][:grade]
@final_updates[user_id] = scores[:final][:grade]
end
def calculate_total_from_weighted_grading_periods(user_id)
enrollment = enrollments_by_user[user_id].first
grading_period_ids = grading_periods_for_course.map(&:id)
# using Enumberable#select because the scores are preloaded
grading_period_scores = enrollment.scores.select do |score|
grading_period_ids.include?(score.grading_period_id)
end
scores = apply_grading_period_weights_to_scores(grading_period_scores)
scale_and_round_scores(scores, grading_period_scores)
end
def apply_grading_period_weights_to_scores(grading_period_scores)
grading_period_scores.each_with_object(
{ current: { full_weight: 0.0, grade: 0.0 }, final: { full_weight: 0.0, grade: 0.0 } }
) do |score, scores|
weight = grading_period_weights[score.grading_period_id] || 0.0
scores[:final][:full_weight] += weight
scores[:current][:full_weight] += weight if score.current_score
scores[:current][:grade] += (score.current_score || 0.0) * (weight / 100.0)
scores[:final][:grade] += (score.final_score || 0.0) * (weight / 100.0)
end
end
def scale_and_round_scores(scores, grading_period_scores)
[:current, :final].each_with_object({ current: {}, final: {} }) do |score_type, adjusted_scores|
score = scores[score_type][:grade]
full_weight = scores[score_type][:full_weight]
score = scale_score_up(score, full_weight) if full_weight < 100
if score == 0.0 && score_type == :current && grading_period_scores.none?(&:current_score)
score = nil
end
adjusted_scores[score_type][:grade] = score ? score.round(2) : score
end
end
def scale_score_up(score, weight)
return 0.0 if weight.zero?
(score * 100.0) / weight
end
def compute_course_scores_from_weighted_grading_periods?
return @compute_from_weighted_periods if @compute_from_weighted_periods.present?
if @grading_period || !@course.feature_enabled?(:multiple_grading_periods) || grading_periods_for_course.empty?
@compute_from_weighted_periods = false
else
@compute_from_weighted_periods = grading_periods_for_course.first.grading_period_group.weighted?
end
end
def grading_periods_for_course
@periods ||= GradingPeriod.for(@course)
end
def grading_period_weights
@grading_period_weights ||= grading_periods_for_course.each_with_object({}) do |period, weights|
weights[period.id] = period.weight
end
end
def submissions_by_user
@submissions_by_user ||= @submissions.group_by(&:user_id)
end
def calculate_grading_period_scores
GradingPeriod.for(@course).each do |grading_period|
grading_periods_for_course.each do |grading_period|
# update this grading period score, and do not
# update any other scores (grading period or course)
# after this one
@ -132,7 +223,7 @@ class GradeCalculator
def enrollments
@enrollments ||= Enrollment.shard(@course).active.
where(user_id: @user_ids, course_id: @course.id).
select(:id, :user_id)
select(:id, :user_id).preload(:scores)
end
def joined_enrollment_ids
@ -225,27 +316,6 @@ class GradeCalculator
end
end
# The score ignoring unsubmitted assignments
def calculate_current_score(user_id, submissions)
calculate_score(submissions, user_id, true)
end
# The final score for the class, so unsubmitted assignments count as zeros
def calculate_final_score(user_id, submissions)
calculate_score(submissions, user_id, false)
end
def calculate_score(submissions, user_id, ignore_ungraded)
group_sums = create_group_sums(submissions, user_id, ignore_ungraded)
info = calculate_total_from_group_scores(group_sums)
Rails.logger.info "GRADES: calculated: #{info.inspect}"
updates_hash = ignore_ungraded ? @current_updates : @final_updates
updates_hash[user_id] = info[:grade]
[info, group_sums.index_by { |s| s[:id] }]
end
# returns information about assignments groups in the form:
# [
# {
@ -256,7 +326,7 @@ class GradeCalculator
# :weight => 50},
# ...]
# each group
def create_group_sums(submissions, user_id, ignore_ungraded=true)
def create_group_sums(submissions, user_id, ignore_ungraded: true)
visible_assignments = @assignments
visible_assignments = visible_assignments.select{|a| assignment_ids_visible_to_user(user_id).include?(a.id)}

View File

@ -460,6 +460,7 @@ describe AssignmentsController do
it "to wiki page" do
Course.any_instance.stubs(:feature_enabled?).with(:conditional_release).returns(true)
Course.any_instance.stubs(:feature_enabled?).with(:multiple_grading_periods).returns(false)
wiki_page_assignment_model course: @course
get 'edit', :course_id => @course.id, :id => @page.assignment.id
expect(response).to redirect_to controller.edit_course_wiki_page_path(@course, @page)

View File

@ -479,39 +479,42 @@ describe GradeCalculator do
describe '#compute_and_save_scores' do
before(:once) do
@first_period, @second_period = grading_periods(count: 2)
first_assignment = @course.assignments.create!(
@first_assignment = @course.assignments.create!(
due_at: 1.day.from_now(@first_period.start_date),
points_possible: 100
)
second_assignment = @course.assignments.create!(
@second_assignment = @course.assignments.create!(
due_at: 1.day.from_now(@second_period.start_date),
points_possible: 100
)
first_assignment.grade_student(@student, grade: 25, grader: @teacher)
second_assignment.grade_student(@student, grade: 75, grader: @teacher)
# update_column to avoid callbacks on submission that would trigger score updates
Submission.where(user: @student, assignment: first_assignment).first.update_column(:score, 100.0)
Submission.where(user: @student, assignment: second_assignment).first.update_column(:score, 95.0)
@first_assignment.grade_student(@student, grade: 25, grader: @teacher)
@second_assignment.grade_student(@student, grade: 75, grader: @teacher)
# update_column to avoid callbacks on submission that would trigger the grade calculator
submission_for_first_assignment.update_column(:score, 99.6)
submission_for_second_assignment.update_column(:score, 95.0)
end
let(:scores) { @student.enrollments.first.scores }
let(:overall_course_score) { scores.where(grading_period_id: nil).first }
let(:scores) { @student.enrollments.first.scores.index_by(&:grading_period_id) }
let(:overall_course_score) { scores[nil] }
let(:submission_for_first_assignment) { Submission.find_by(user: @student, assignment: @first_assignment) }
let(:submission_for_second_assignment) { Submission.find_by(user: @student, assignment: @second_assignment) }
it 'updates the overall course score' do
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.current_score).to eq(97.5)
expect(overall_course_score.current_score).to eq(97.3)
end
it 'updates all grading period scores' do
GradeCalculator.new(@student.id, @course).compute_and_save_scores
grading_period_scores = scores.where.not(grading_period_id: nil).order(:current_score).pluck(:current_score)
expect(grading_period_scores).to match_array([100.0, 95.0])
expect(scores[@first_period.id].current_score).to eq(99.6)
expect(scores[@second_period.id].current_score).to eq(95.0)
end
it 'does not update grading period scores if update_all_grading_period_scores is false' do
GradeCalculator.new(@student.id, @course, update_all_grading_period_scores: false).compute_and_save_scores
grading_period_scores = scores.where.not(grading_period_id: nil).order(:current_score).pluck(:current_score)
expect(grading_period_scores).to match_array([25.0, 75.0])
expect(scores[@first_period.id].current_score).to eq(25.0)
expect(scores[@second_period.id].current_score).to eq(75.0)
end
it 'restores and updates previously deleted scores' do
@ -523,19 +526,17 @@ describe GradeCalculator do
context 'grading period is provided' do
it 'updates the grading period score' do
GradeCalculator.new(@student.id, @course, grading_period: @first_period).compute_and_save_scores
score = scores.where(grading_period_id: @first_period).first
expect(score.current_score).to eq(100.0)
expect(scores[@first_period.id].current_score).to eq(99.6)
end
it 'updates the overall course score' do
GradeCalculator.new(@student.id, @course, grading_period: @first_period).compute_and_save_scores
expect(overall_course_score.current_score).to eq(97.5)
expect(overall_course_score.current_score).to eq(97.3)
end
it 'does not update scores for other grading periods' do
GradeCalculator.new(@student.id, @course, grading_period: @first_period).compute_and_save_scores
score = scores.where(grading_period_id: @second_period).first
expect(score.current_score).to eq(75.0)
expect(scores[@second_period.id].current_score).to eq(75.0)
end
it 'does not update the overall course score if update_course_score is false' do
@ -544,14 +545,252 @@ describe GradeCalculator do
).compute_and_save_scores
expect(overall_course_score.current_score).to eq(50.0)
end
it 'does not restore previously deleted score if grading period is deleted too' do
score = scores.where(grading_period_id: @first_period).first
score = scores[@first_period.id]
@first_period.destroy
GradeCalculator.new(@student.id, @course, grading_period: @first_period).compute_and_save_scores
expect(score.reload).to be_deleted
end
end
context 'weighted grading periods' do
before(:once) do
group = @first_period.grading_period_group
group.update!(weighted: true)
@ungraded_assignment = @course.assignments.create!(
due_at: 1.day.from_now(@second_period.start_date),
points_possible: 100
)
end
it 'calculates the course score from weighted grading period scores' do
@first_period.update!(weight: 25.0)
@second_period.update!(weight: 75.0)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
# (99.6 * 0.25) + (95.0 * 0.75) = 96.15
expect(overall_course_score.current_score).to eq(96.15)
# (99.6 * 0.25) + (47.5 * 0.75) = 60.525 rounds to 60.53
expect(overall_course_score.final_score).to eq(60.53)
end
it 'up-scales grading period weights which add up to less than 100 percent' do
@first_period.update!(weight: 25.0)
@second_period.update!(weight: 50.0)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
# (99.6 * 0.25) + (95.0 * 0.50) = 72.4
# 72.4 / (0.25 + 0.50) = 96.5333 rounded to 96.53
expect(overall_course_score.current_score).to eq(96.53)
# (99.6 * 0.25) + (47.5 * 0.50) = 48.65
# 48.65 / (0.25 + 0.50) = 64.8666 rounded to 64.87
expect(overall_course_score.final_score).to eq(64.87)
end
it 'does not down-scale grading period weights which add up to greater than 100 percent' do
@first_period.update!(weight: 100.0)
@second_period.update!(weight: 50.0)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
# (99.6 * 1.0) + (95.0 * 0.5) = 147.1
expect(overall_course_score.current_score).to eq(147.1)
# (99.6 * 1.0) + (47.5 * 0.5) = 123.35
expect(overall_course_score.final_score).to eq(123.35)
end
it 'sets current course score to zero when all grading period weights are zero' do
@first_period.update!(weight: 0)
@second_period.update!(weight: 0)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.current_score).to eq(0.0)
end
it 'sets final course score to zero when all grading period weights are zero' do
@first_period.update!(weight: 0)
@second_period.update!(weight: 0)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.final_score).to eq(0.0)
end
it 'sets current course score to zero when all grading period weights are nil' do
@first_period.update!(weight: nil)
@second_period.update!(weight: nil)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.current_score).to eq(0.0)
end
it 'sets current course score to zero when all grading period weights are nil or zero' do
@first_period.update!(weight: 0.0)
@second_period.update!(weight: nil)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.current_score).to eq(0.0)
end
it 'sets final course score to zero when all grading period weights are nil' do
@first_period.update!(weight: nil)
@second_period.update!(weight: nil)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.final_score).to eq(0.0)
end
it 'sets final course score to zero when all grading period weights are nil or zero' do
@first_period.update!(weight: 0.0)
@second_period.update!(weight: nil)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.final_score).to eq(0.0)
end
it 'treats grading periods with nil weights as zero when some grading period ' \
'weights are nil and computing current score' do
@first_period.update!(weight: nil)
@second_period.update!(weight: 50.0)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.current_score).to eq(95.0)
end
it 'treats grading periods with nil weights as zero when some grading period ' \
'weights are nil and computing final score' do
@first_period.update!(weight: nil)
@second_period.update!(weight: 50.0)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.final_score).to eq(47.50)
end
it 'sets current course score to nil when all grading period current scores are nil' do
@first_period.update!(weight: 25.0)
@second_period.update!(weight: 75.0)
# update_all to avoid callbacks on submission that would trigger the grade calculator
@student.submissions.update_all(score: nil)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.current_score).to be_nil
end
it 'sets final course score to zero when all grading period final scores are nil' do
@first_period.update!(weight: 25.0)
@second_period.update!(weight: 75.0)
# update_all to avoid callbacks on assignment that would trigger the grade calculator
@course.assignments.update_all(omit_from_final_grade: true)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.final_score).to eq(0.0)
end
it 'does not consider grading periods with nil current score when computing course current score' do
@first_period.update!(weight: 25.0)
@second_period.update!(weight: 75.0)
# update_column to avoid callbacks on submission that would trigger the grade calculator
submission_for_first_assignment.update_column(:score, nil)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
# (0.0 * 0.0) + (95.0 * 0.75) = 71.25
# 71.25 / (0.0 + 0.75) = 95.0
expect(overall_course_score.current_score).to eq(95.0)
end
it 'considers grading periods with nil final score as having zero score when computing course final score' do
@first_period.update!(weight: 25.0)
@second_period.update!(weight: 75.0)
# update_column to avoid callbacks on assignment that would trigger the grade calculator
@first_assignment.update_column(:omit_from_final_grade, true)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
# (0.0 * 0.25) + (47.5 * 0.75) = 35.625 rounded to 35.63
expect(overall_course_score.final_score).to eq(35.63)
end
it 'sets course current score to zero when all grading period current scores are zero' do
@first_period.update!(weight: 25.0)
@second_period.update!(weight: 75.0)
# update_all to avoid callbacks on submission that would trigger the grade calculator
@student.submissions.update_all(score: 0.0)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.current_score).to eq(0.0)
end
it 'sets course final score to zero when all grading period final scores are zero' do
@first_period.update!(weight: 25.0)
@second_period.update!(weight: 75.0)
# update_all to avoid callbacks on submission that would trigger the grade calculator
@student.submissions.update_all(score: 0.0)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.final_score).to eq(0.0)
end
it 'sets course current score to nil when all grading period current scores are nil ' \
'and all grading period weights are nil' do
@first_period.update!(weight: nil)
@second_period.update!(weight: nil)
# update_all to avoid callbacks on submission that would trigger the grade calculator
@student.submissions.update_all(score: nil)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.current_score).to be_nil
end
it 'sets course final score to zero when all grading period final scores are nil and all ' \
'grading period weights are nil' do
@first_period.update!(weight: nil)
@second_period.update!(weight: nil)
# update_all to avoid callbacks on assignment that would trigger the grade calculator
@course.assignments.update_all(omit_from_final_grade: true)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.final_score).to eq(0.0)
end
it 'sets course current score to zero when all grading period current scores are zero ' \
'and all grading period weights are zero' do
@first_period.update!(weight: 0.0)
@second_period.update!(weight: 0.0)
# update_all to avoid callbacks on submission that would trigger the grade calculator
@student.submissions.update_all(score: 0.0)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.current_score).to eq(0.0)
end
it 'sets course final score to zero when all grading period final scores are zero and ' \
'all grading period weights are zero' do
@first_period.update!(weight: 0.0)
@second_period.update!(weight: 0.0)
# update_all to avoid callbacks on submission that would trigger the grade calculator
@student.submissions.update_all(score: 0.0)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.final_score).to eq(0.0)
end
it 'sets course current score to nil when all grading period current scores are nil and ' \
'all grading period weights are zero' do
@first_period.update!(weight: 0.0)
@second_period.update!(weight: 0.0)
# update_all to avoid callbacks on submission that would trigger the grade calculator
@student.submissions.update_all(score: nil)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.current_score).to be_nil
end
it 'sets course final score to zero when all grading period final scores are nil and all ' \
'grading period weights are zero' do
@first_period.update!(weight: 0.0)
@second_period.update!(weight: 0.0)
# update_all to avoid callbacks on assignment that would trigger the grade calculator
@course.assignments.update_all(omit_from_final_grade: true)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.final_score).to eq(0.0)
end
it 'sets course current score to zero when all grading period current scores are zero and ' \
'all grading period weights are nil' do
@first_period.update!(weight: nil)
@second_period.update!(weight: nil)
# update_all to avoid callbacks on submission that would trigger the grade calculator
@student.submissions.update_all(score: 0.0)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.current_score).to eq(0.0)
end
it 'sets course final score to zero when all grading period final scores are zero and all ' \
'grading period weights are nil' do
@first_period.update!(weight: nil)
@second_period.update!(weight: nil)
# update_all to avoid callbacks on submission that would trigger the grade calculator
@student.submissions.update_all(score: 0.0)
GradeCalculator.new(@student.id, @course).compute_and_save_scores
expect(overall_course_score.final_score).to eq(0.0)
end
end
end
it "should return grades in the order they are requested" do

View File

@ -160,7 +160,7 @@ describe GradingPeriod do
context "where end_date equals Time.now" do
it "does not include period" do
Timecop.freeze(Time.zone.now.change(usec: 0)) do
Timecop.freeze(now.change(usec: 0)) do
period.update!(end_date: now)
is_expected.to be_present
end
@ -169,7 +169,7 @@ describe GradingPeriod do
context "where end_date equals Time.now + 1" do
it "does not include period" do
Timecop.freeze(Time.zone.now.change(usec: 0) + 1) do
Timecop.freeze(now.change(usec: 0) + 1) do
period.update!(end_date: now)
is_expected.to be_empty
end
@ -178,7 +178,7 @@ describe GradingPeriod do
context "where start_date equals Time.now" do
it "does not include period" do
Timecop.freeze(Time.zone.now.change(usec: 0)) do
Timecop.freeze(now.change(usec: 0)) do
period.update!(start_date: now)
is_expected.to be_empty
end
@ -187,7 +187,7 @@ describe GradingPeriod do
context "where start_date equals Time.now + 1" do
it "does not include period" do
Timecop.freeze(Time.zone.now.change(usec: 0) + 1) do
Timecop.freeze(now.change(usec: 0) + 1) do
period.update!(start_date: now)
is_expected.to be_present
end