average those groupings and the way up the framework. Likert scores for a survey_item are averaged. Then all the survey_items in a scale are averaged. Then student scales in a measure are averaged. And teacher scales in a measure are averaged. Then the average of those two calculations becomes the score for a measure. Then the measures in a subcategory are averaged.pull/1/head
parent
1ca88bf6d1
commit
d4df7cbc06
@ -1,11 +1,11 @@
|
||||
class AdminDataItem < ActiveRecord::Base
|
||||
belongs_to :measure
|
||||
belongs_to :scale
|
||||
|
||||
scope :for_measures, ->(measure) {
|
||||
joins(:measure).where('admin_data_items.measure': measure)
|
||||
scope :for_measures, lambda { |measures|
|
||||
joins(:scale).where('scale.measure': measures)
|
||||
}
|
||||
|
||||
scope :non_hs_items_for_measures, ->(measure) {
|
||||
scope :non_hs_items_for_measures, lambda { |measure|
|
||||
for_measures(measure).where(hs_only_item: false)
|
||||
}
|
||||
end
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
class Scale < ApplicationRecord
|
||||
belongs_to :measure
|
||||
has_many :survey_items
|
||||
has_many :admin_data_items
|
||||
|
||||
def score(school:, academic_year:)
|
||||
@score ||= Hash.new do |memo|
|
||||
memo[[school, academic_year]] = survey_items.map do |survey_item|
|
||||
survey_item.score(school:, academic_year:)
|
||||
end.average
|
||||
end
|
||||
@score[[school, academic_year]]
|
||||
end
|
||||
|
||||
scope :teacher_scales, lambda {
|
||||
where("scale_id LIKE 't-%'")
|
||||
}
|
||||
scope :student_scales, lambda {
|
||||
where("scale_id LIKE 's-%'")
|
||||
}
|
||||
end
|
||||
@ -1,11 +1,21 @@
|
||||
class SurveyItem < ActiveRecord::Base
|
||||
belongs_to :measure
|
||||
belongs_to :scale
|
||||
has_one :measure, through: :scale
|
||||
|
||||
has_many :survey_item_responses
|
||||
|
||||
scope :student_survey_items_for_measures, lambda { |measures|
|
||||
joins(:measure).where(measure: measures).where("survey_item_id LIKE 's-%'")
|
||||
def score(school:, academic_year:)
|
||||
@score ||= Hash.new do |memo|
|
||||
memo[[school, academic_year]] = survey_item_responses.where(school:, academic_year:).average(:likert_score).to_f
|
||||
end
|
||||
|
||||
@score[[school, academic_year]]
|
||||
end
|
||||
|
||||
scope :student_survey_items, lambda {
|
||||
where("survey_item_id LIKE 's-%'")
|
||||
}
|
||||
scope :teacher_survey_items_for_measures, lambda { |measures|
|
||||
joins(:measure).where(measure: measures).where("survey_item_id LIKE 't-%'")
|
||||
scope :teacher_survey_items, lambda {
|
||||
where("survey_item_id LIKE 't-%'")
|
||||
}
|
||||
end
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
class CreateScales < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
create_table :scales do |t|
|
||||
t.string :scale_id, index: { unique: true }, null: false
|
||||
t.references :measure, null: false, foreign_key: true
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,6 @@
|
||||
class AddScaleToSurveyItem < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_reference :survey_items, :scale, null: false, foreign_key: true
|
||||
remove_reference :survey_items, :measure, null: false, foreign_key: true
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,7 @@
|
||||
class AddScaleToAdminDataItem < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_reference :admin_data_items, :scale, null: false, foreign_key: true
|
||||
remove_reference :admin_data_items, :measure
|
||||
add_index :admin_data_items, :admin_data_item_id, unique: true
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,26 @@
|
||||
# Application decision record 2
|
||||
|
||||
# Add scale to framework
|
||||
|
||||
## Status
|
||||
|
||||
Completed
|
||||
|
||||
## Context
|
||||
|
||||
The calculations needed to be reworked. When calculating a score for a measure, we had looped through all the survey_items_responses for a measure and taken the average for all of them. Doing it that way means student responses are given more weight than teacher responses since the number of students responses will outnumber teacher responses. Another consequence is that survey_items with more questions will be prioritized over ones with fewer questions since they will create more survey item responses.
|
||||
|
||||
Story: #181205114 and #181209931
|
||||
|
||||
## Decision
|
||||
|
||||
Change the calculations so that scores bubble up through the framework hierarchy.
|
||||
|
||||
## Consequences
|
||||
|
||||
Added scales to framework. Changed calculations to first group based on the most atomic bits of the framework and then
|
||||
average those groupings as we go up the framework. First, likert scores are averaged for
|
||||
all survey item responses in a survey item. Then all the survey items in a scale are
|
||||
averaged. Then student scales in a measure are averaged. And teacher
|
||||
scales in a measure are averaged. The average of student and teacher scales becomes the score for a measure. Then the measures in a
|
||||
subcategory are averaged.
|
||||
@ -0,0 +1,41 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Scale, type: :model do
|
||||
let(:school) { create(:school) }
|
||||
let(:academic_year) { create(:academic_year) }
|
||||
let(:scale) { create(:scale) }
|
||||
|
||||
describe '.score' do
|
||||
let(:teacher_survey_item_1) { create(:teacher_survey_item, scale:) }
|
||||
let(:teacher_survey_item_2) { create(:teacher_survey_item, scale:) }
|
||||
let(:teacher_survey_item_3) { create(:teacher_survey_item, scale:) }
|
||||
|
||||
before :each do
|
||||
create(:survey_item_response,
|
||||
survey_item: teacher_survey_item_1, academic_year:, school:, likert_score: 3)
|
||||
create(:survey_item_response,
|
||||
survey_item: teacher_survey_item_2, academic_year:, school:, likert_score: 4)
|
||||
create(:survey_item_response,
|
||||
survey_item: teacher_survey_item_3, academic_year:, school:, likert_score: 5)
|
||||
end
|
||||
|
||||
it 'returns the average of the likert scores of the survey items' do
|
||||
expect(scale.score(school:, academic_year:)).to eq 4
|
||||
end
|
||||
|
||||
context 'when other scales exist' do
|
||||
before :each do
|
||||
create(:survey_item_response,
|
||||
academic_year:, school:, likert_score: 1)
|
||||
create(:survey_item_response,
|
||||
academic_year:, school:, likert_score: 1)
|
||||
create(:survey_item_response,
|
||||
academic_year:, school:, likert_score: 1)
|
||||
end
|
||||
|
||||
it 'does not affect the score for the original scale' do
|
||||
expect(scale.score(school:, academic_year:)).to eq 4
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,60 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Subcategory, type: :model do
|
||||
let(:school) { create(:school) }
|
||||
let(:academic_year) { create(:academic_year) }
|
||||
let(:subcategory) { create(:subcategory) }
|
||||
let(:measure_1) { create(:measure, subcategory: subcategory) }
|
||||
let(:teacher_scale) { create(:teacher_scale, measure: measure_1) }
|
||||
let(:measure_2) { create(:measure, subcategory: subcategory) }
|
||||
let(:student_scale) { create(:student_scale, measure: measure_2) }
|
||||
|
||||
describe '.score' do
|
||||
let(:teacher_survey_item_1) { create(:teacher_survey_item, scale: teacher_scale) }
|
||||
let(:teacher_survey_item_2) { create(:teacher_survey_item, scale: teacher_scale) }
|
||||
let(:teacher_survey_item_3) { create(:teacher_survey_item, scale: teacher_scale) }
|
||||
let(:student_survey_item_1) { create(:student_survey_item, scale: student_scale) }
|
||||
let(:student_survey_item_2) { create(:student_survey_item, scale: student_scale) }
|
||||
let(:student_survey_item_3) { create(:student_survey_item, scale: student_scale) }
|
||||
let(:student_survey_item_4) { create(:student_survey_item, scale: student_scale) }
|
||||
let(:student_survey_item_5) { create(:student_survey_item, scale: student_scale) }
|
||||
|
||||
before :each do
|
||||
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD,
|
||||
survey_item: teacher_survey_item_1, academic_year:, school:, likert_score: 2)
|
||||
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD,
|
||||
survey_item: teacher_survey_item_2, academic_year:, school:, likert_score: 3)
|
||||
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD,
|
||||
survey_item: teacher_survey_item_3, academic_year:, school:, likert_score: 4)
|
||||
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD,
|
||||
survey_item: student_survey_item_1, academic_year:, school:, likert_score: 1)
|
||||
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD,
|
||||
survey_item: student_survey_item_2, academic_year:, school:, likert_score: 2)
|
||||
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD,
|
||||
survey_item: student_survey_item_3, academic_year:, school:, likert_score: 3)
|
||||
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD,
|
||||
survey_item: student_survey_item_4, academic_year:, school:, likert_score: 4)
|
||||
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD,
|
||||
survey_item: student_survey_item_5, academic_year:, school:, likert_score: 5)
|
||||
end
|
||||
|
||||
it 'returns the average of the likert scores of the measures' do
|
||||
expect(subcategory.score(school:, academic_year:)).to eq 3
|
||||
end
|
||||
|
||||
context 'when other subcategories exist' do
|
||||
before :each do
|
||||
create(:survey_item_response,
|
||||
academic_year:, school:, likert_score: 1)
|
||||
create(:survey_item_response,
|
||||
academic_year:, school:, likert_score: 1)
|
||||
create(:survey_item_response,
|
||||
academic_year:, school:, likert_score: 1)
|
||||
end
|
||||
|
||||
it 'does not affect the score for the original scale' do
|
||||
expect(subcategory.score(school:, academic_year:)).to eq 3
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,337 +0,0 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe SurveyItemResponse, type: :model do
|
||||
let(:school) { create(:school) }
|
||||
let(:ay) { create(:academic_year) }
|
||||
|
||||
describe '.score_for_measure' do
|
||||
let(:measure) { create(:measure) }
|
||||
|
||||
context 'when the measure includes only teacher data' do
|
||||
let(:teacher_survey_item_1) { create(:teacher_survey_item, measure: measure) }
|
||||
let(:teacher_survey_item_2) { create(:teacher_survey_item, measure: measure) }
|
||||
let(:teacher_survey_item_3) { create(:teacher_survey_item, measure: measure) }
|
||||
|
||||
context "and the number of responses for each of the measure's survey items meets the teacher threshold of 17" do
|
||||
before :each do
|
||||
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD,
|
||||
survey_item: teacher_survey_item_1, academic_year: ay, school: school, likert_score: 3)
|
||||
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD,
|
||||
survey_item: teacher_survey_item_2, academic_year: ay, school: school, likert_score: 4)
|
||||
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD,
|
||||
survey_item: teacher_survey_item_3, academic_year: ay, school: school, likert_score: 5)
|
||||
end
|
||||
|
||||
it 'returns the average of the likert scores of the survey items' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).average).to eq 4
|
||||
end
|
||||
|
||||
it 'affirms that the result meets the teacher threshold' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).meets_teacher_threshold?).to be true
|
||||
end
|
||||
|
||||
it 'reports the result does not meeet student threshold' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).meets_student_threshold?).to be false
|
||||
end
|
||||
end
|
||||
|
||||
context "and the average number of responses across the measure's survey items meets the teacher threshold of 17" do
|
||||
before :each do
|
||||
create_list(:survey_item_response, 19, survey_item: teacher_survey_item_1, academic_year: ay, school: school,
|
||||
likert_score: 3)
|
||||
create_list(:survey_item_response, 16, survey_item: teacher_survey_item_2, academic_year: ay, school: school,
|
||||
likert_score: 4)
|
||||
create_list(:survey_item_response, 16, survey_item: teacher_survey_item_3, academic_year: ay, school: school,
|
||||
likert_score: 5)
|
||||
end
|
||||
|
||||
it 'returns the average of the likert scores of the survey items' do
|
||||
average_score = 3.941
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).average).to be_within(0.001).of(average_score)
|
||||
end
|
||||
end
|
||||
|
||||
context "and none of the measure's survey items meets the teacher threshold of 17" do
|
||||
before :each do
|
||||
create_list(:survey_item_response, 16, survey_item: teacher_survey_item_1, academic_year: ay, school: school,
|
||||
likert_score: rand)
|
||||
create_list(:survey_item_response, 16, survey_item: teacher_survey_item_2, academic_year: ay, school: school,
|
||||
likert_score: rand)
|
||||
create_list(:survey_item_response, 16, survey_item: teacher_survey_item_3, academic_year: ay, school: school,
|
||||
likert_score: rand)
|
||||
end
|
||||
|
||||
it 'returns nil' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).average).to be_nil
|
||||
end
|
||||
|
||||
it 'affirms that the result does not meet the threshold' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).meets_teacher_threshold?).to be false
|
||||
end
|
||||
end
|
||||
|
||||
context "and the average number of responses across the measure's survey items does not meet the teacher threshold of 17" do
|
||||
before :each do
|
||||
create_list(:survey_item_response, 18, survey_item: teacher_survey_item_1, academic_year: ay, school: school,
|
||||
likert_score: rand)
|
||||
create_list(:survey_item_response, 16, survey_item: teacher_survey_item_2, academic_year: ay, school: school,
|
||||
likert_score: rand)
|
||||
create_list(:survey_item_response, 16, survey_item: teacher_survey_item_3, academic_year: ay, school: school,
|
||||
likert_score: rand)
|
||||
end
|
||||
|
||||
it 'returns nil' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).average).to be_nil
|
||||
end
|
||||
|
||||
it 'affirms that the result does not meet the threshold' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).meets_teacher_threshold?).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the measure includes only student data' do
|
||||
let(:student_survey_item_1) { create(:student_survey_item, measure: measure) }
|
||||
let(:student_survey_item_2) { create(:student_survey_item, measure: measure) }
|
||||
let(:student_survey_item_3) { create(:student_survey_item, measure: measure) }
|
||||
|
||||
context "and the number of responses for each of the measure's survey items meets the student threshold of 196" do
|
||||
before :each do
|
||||
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD,
|
||||
survey_item: student_survey_item_1, academic_year: ay, school: school, likert_score: 3)
|
||||
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD,
|
||||
survey_item: student_survey_item_2, academic_year: ay, school: school, likert_score: 4)
|
||||
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD,
|
||||
survey_item: student_survey_item_3, academic_year: ay, school: school, likert_score: 5)
|
||||
end
|
||||
|
||||
it 'returns the average of the likert scores of the survey items' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).average).to eq 4
|
||||
end
|
||||
|
||||
it 'affirms that the result meets the student threshold' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).meets_student_threshold?).to be true
|
||||
end
|
||||
it 'notes that the result does not meet the teacher threshold' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).meets_teacher_threshold?).to be false
|
||||
end
|
||||
end
|
||||
|
||||
context "and the average number of responses across the measure's survey items meets the student threshold of 196" do
|
||||
before :each do
|
||||
create_list(:survey_item_response, 200, survey_item: student_survey_item_1, academic_year: ay,
|
||||
school: school, likert_score: 3)
|
||||
create_list(:survey_item_response, 195, survey_item: student_survey_item_2, academic_year: ay,
|
||||
school: school, likert_score: 4)
|
||||
create_list(:survey_item_response, 193, survey_item: student_survey_item_3, academic_year: ay,
|
||||
school: school, likert_score: 5)
|
||||
end
|
||||
|
||||
it 'returns the average of the likert scores of the survey items' do
|
||||
average_score = 3.988
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).average).to be_within(0.001).of(average_score)
|
||||
end
|
||||
end
|
||||
|
||||
context "and none of the measure's survey items meets the student threshold of 196" do
|
||||
before :each do
|
||||
create_list(:survey_item_response, 195, survey_item: student_survey_item_1, academic_year: ay,
|
||||
school: school, likert_score: rand)
|
||||
create_list(:survey_item_response, 195, survey_item: student_survey_item_2, academic_year: ay,
|
||||
school: school, likert_score: rand)
|
||||
create_list(:survey_item_response, 195, survey_item: student_survey_item_3, academic_year: ay,
|
||||
school: school, likert_score: rand)
|
||||
end
|
||||
|
||||
it 'returns nil' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).average).to be_nil
|
||||
end
|
||||
|
||||
it 'affirms that the result does not meet the threshold' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).meets_student_threshold?).to be false
|
||||
end
|
||||
end
|
||||
|
||||
context "and the average number of responses across the measure's survey items does not meet the student threshold of 196" do
|
||||
before :each do
|
||||
create_list(:survey_item_response, 200, survey_item: student_survey_item_1, academic_year: ay,
|
||||
school: school, likert_score: rand)
|
||||
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD,
|
||||
survey_item: student_survey_item_2, academic_year: ay, school: school, likert_score: rand)
|
||||
create_list(:survey_item_response, 191, survey_item: student_survey_item_3, academic_year: ay,
|
||||
school: school, likert_score: rand)
|
||||
end
|
||||
|
||||
it 'returns nil' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).average).to be_nil
|
||||
end
|
||||
|
||||
it 'affirms that the result does not meet the threshold' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).meets_student_threshold?).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the measure includes both teacher and student data' do
|
||||
let(:teacher_survey_item_1) { create(:teacher_survey_item, measure: measure) }
|
||||
let(:student_survey_item_1) { create(:student_survey_item, measure: measure) }
|
||||
|
||||
context 'and there is sufficient teacher data and sufficient student data' do
|
||||
before :each do
|
||||
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD,
|
||||
survey_item: teacher_survey_item_1, academic_year: ay, school: school, likert_score: 5)
|
||||
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD,
|
||||
survey_item: student_survey_item_1, academic_year: ay, school: school, likert_score: 5)
|
||||
end
|
||||
|
||||
it 'returns the average of the likert scores of the survey items' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).average).to eq 5
|
||||
end
|
||||
|
||||
it 'affirms that the result does meet the thresholds' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).meets_teacher_threshold?).to be true
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).meets_student_threshold?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'and there is sufficient teacher data and insufficient student data' do
|
||||
before :each do
|
||||
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD,
|
||||
survey_item: teacher_survey_item_1, academic_year: ay, school: school, likert_score: 5)
|
||||
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD - 1,
|
||||
survey_item: student_survey_item_1, academic_year: ay, school: school, likert_score: 1)
|
||||
end
|
||||
|
||||
it 'returns the average of the likert scores of the teacher survey items' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).average).to eq 5
|
||||
end
|
||||
|
||||
it 'affirms that the result meets the teacher threshold but not the student threshold' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).meets_teacher_threshold?).to be true
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).meets_student_threshold?).to be false
|
||||
end
|
||||
end
|
||||
|
||||
context 'and there is insufficient teacher data and sufficient student data' do
|
||||
before :each do
|
||||
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1,
|
||||
survey_item: teacher_survey_item_1, academic_year: ay, school: school, likert_score: 1)
|
||||
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD,
|
||||
survey_item: student_survey_item_1, academic_year: ay, school: school, likert_score: 5)
|
||||
end
|
||||
|
||||
it 'returns the average of the likert scores of the student survey items' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).average).to eq 5
|
||||
end
|
||||
|
||||
it 'affirms that the result meets the student threshold but not the teacher threshold' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).meets_teacher_threshold?).to be false
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).meets_student_threshold?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'and there is insufficient teacher data and insufficient student data' do
|
||||
before :each do
|
||||
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1,
|
||||
survey_item: teacher_survey_item_1, academic_year: ay, school: school)
|
||||
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD - 1,
|
||||
survey_item: student_survey_item_1, academic_year: ay, school: school)
|
||||
end
|
||||
|
||||
it 'returns nil' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).average).to be_nil
|
||||
end
|
||||
|
||||
it 'affirms that the result does not meet either threshold' do
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).meets_teacher_threshold?).to be false
|
||||
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school,
|
||||
academic_year: ay).meets_student_threshold?).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.score_for_subcategory' do
|
||||
let(:subcategory) { create(:subcategory) }
|
||||
let(:sufficient_measure_1) { create(:measure, subcategory: subcategory) }
|
||||
let(:sufficient_measure_2) { create(:measure, subcategory: subcategory) }
|
||||
let(:insufficient_measure) { create(:measure, subcategory: subcategory) }
|
||||
let(:sufficient_teacher_survey_item) { create(:teacher_survey_item, measure: sufficient_measure_1) }
|
||||
let(:insufficient_teacher_survey_item) { create(:teacher_survey_item, measure: insufficient_measure) }
|
||||
let(:sufficient_student_survey_item) { create(:student_survey_item, measure: sufficient_measure_2) }
|
||||
let(:insufficient_student_survey_item) { create(:student_survey_item, measure: insufficient_measure) }
|
||||
|
||||
before :each do
|
||||
largest_threshold = [SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD,
|
||||
SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD].max
|
||||
create_list(:survey_item_response, largest_threshold, survey_item: sufficient_teacher_survey_item,
|
||||
academic_year: ay, school: school, likert_score: 1)
|
||||
create_list(:survey_item_response, largest_threshold, survey_item: sufficient_student_survey_item,
|
||||
academic_year: ay, school: school, likert_score: 4)
|
||||
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1,
|
||||
survey_item: insufficient_teacher_survey_item, academic_year: ay, school: school, likert_score: 1)
|
||||
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD - 1,
|
||||
survey_item: insufficient_student_survey_item, academic_year: ay, school: school, likert_score: 1)
|
||||
end
|
||||
|
||||
it 'returns the average score of all survey item responses for measures meeting their respective thresholds' do
|
||||
expect(SurveyItemResponse.score_for_subcategory(subcategory: subcategory, school: school,
|
||||
academic_year: ay)).to eq 2.5
|
||||
end
|
||||
end
|
||||
|
||||
describe '.responses_for_measure' do
|
||||
let(:subcategory) { create(:subcategory) }
|
||||
let(:sufficient_measure_1) { create(:measure, subcategory: subcategory) }
|
||||
let(:sufficient_measure_2) { create(:measure, subcategory: subcategory) }
|
||||
let(:insufficient_measure) { create(:measure, subcategory: subcategory) }
|
||||
let(:sufficient_teacher_survey_item) { create(:teacher_survey_item, measure: sufficient_measure_1) }
|
||||
let(:insufficient_teacher_survey_item) { create(:teacher_survey_item, measure: insufficient_measure) }
|
||||
let(:sufficient_student_survey_item) { create(:student_survey_item, measure: sufficient_measure_2) }
|
||||
let(:insufficient_student_survey_item) { create(:student_survey_item, measure: insufficient_measure) }
|
||||
|
||||
before :each do
|
||||
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: sufficient_teacher_survey_item,
|
||||
academic_year: ay, school: school, likert_score: 1)
|
||||
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: sufficient_student_survey_item,
|
||||
academic_year: ay, school: school, likert_score: 4)
|
||||
create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1,
|
||||
survey_item: insufficient_teacher_survey_item, academic_year: ay, school: school, likert_score: 1)
|
||||
create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD - 1,
|
||||
survey_item: insufficient_student_survey_item, academic_year: ay, school: school, likert_score: 1)
|
||||
end
|
||||
|
||||
it 'returns only responses in a measure that meets the low threshold' do
|
||||
expect(SurveyItemResponse.responses_for_measure(measure: sufficient_measure_1, school: school, academic_year: ay).count).to eq SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD
|
||||
expect(SurveyItemResponse.responses_for_measure(measure: sufficient_measure_2, school: school, academic_year: ay).count).to eq SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD
|
||||
expect(SurveyItemResponse.responses_for_measure(measure: insufficient_measure, school: school, academic_year: ay)).to be nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,38 @@
|
||||
require 'rails_helper'
|
||||
RSpec.describe SurveyItem, type: :model do
|
||||
let(:school) { create(:school) }
|
||||
let(:academic_year) { create(:academic_year) }
|
||||
let(:scale) { create(:scale) }
|
||||
|
||||
describe '.score' do
|
||||
let(:teacher_survey_item) { create(:teacher_survey_item, scale:) }
|
||||
|
||||
before :each do
|
||||
create(:survey_item_response,
|
||||
survey_item: teacher_survey_item, academic_year:, school:, likert_score: 3)
|
||||
create(:survey_item_response,
|
||||
survey_item: teacher_survey_item, academic_year:, school:, likert_score: 4)
|
||||
create(:survey_item_response,
|
||||
survey_item: teacher_survey_item, academic_year:, school:, likert_score: 5)
|
||||
end
|
||||
|
||||
it 'returns the average of the likert scores of the survey items' do
|
||||
expect(teacher_survey_item.score(school:, academic_year:)).to eq 4
|
||||
end
|
||||
|
||||
context 'when other scales exist' do
|
||||
before :each do
|
||||
create(:survey_item_response,
|
||||
academic_year:, school:, likert_score: 1)
|
||||
create(:survey_item_response,
|
||||
academic_year:, school:, likert_score: 1)
|
||||
create(:survey_item_response,
|
||||
academic_year:, school:, likert_score: 1)
|
||||
end
|
||||
|
||||
it 'does not affect the score for the original scale' do
|
||||
expect(scale.score(school:, academic_year:)).to eq 4
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in new issue