Implement correct policy regarding whether there exist sufficient data for a measure

pull/1/head
Alex Basson 4 years ago
parent 7f23cb2d29
commit 2abf2d352a

@ -4,11 +4,19 @@ class Measure < ActiveRecord::Base
has_many :survey_item_responses, through: :survey_items
def teacher_survey_items
@teacher_survey_items ||= survey_items.where("survey_item_id LIKE 't-%'")
end
def student_survey_items
@student_survey_items ||= survey_items.where("survey_item_id LIKE 's-%'")
end
def includes_teacher_survey_items?
survey_items.where("survey_item_id LIKE 't-%'").any?
teacher_survey_items.any?
end
def includes_student_survey_items?
survey_items.where("survey_item_id LIKE 's-%'").any?
student_survey_items.any?
end
end

@ -8,8 +8,8 @@ class SurveyItemResponse < ActiveRecord::Base
scope :for_measures, ->(measures) { joins(:survey_item).where('survey_items.measure_id': measures.map(&:id)) }
scope :for_measure, ->(measure) { joins(:survey_item).where('survey_items.measure_id': measure.id) }
scope :for_teacher_responses_for_measure, ->(measure) { for_measure(measure).where("survey_items.survey_item_id LIKE 't-%'") }
scope :for_student_responses_for_measure, ->(measure) { for_measure(measure).where("survey_items.survey_item_id LIKE 's-%'") }
scope :teacher_responses_for_measure, ->(measure) { for_measure(measure).where("survey_items.survey_item_id LIKE 't-%'") }
scope :student_responses_for_measure, ->(measure) { for_measure(measure).where("survey_items.survey_item_id LIKE 's-%'") }
def self.score_for_measure(measure:, school:, academic_year:)
return nil unless SurveyItemResponse.sufficient_data?(measure: measure, school: school, academic_year: academic_year)
@ -26,11 +26,17 @@ class SurveyItemResponse < ActiveRecord::Base
meets_student_threshold = true
if measure.includes_teacher_survey_items?
meets_teacher_threshold = SurveyItemResponse.for_teacher_responses_for_measure(measure).where(academic_year: academic_year, school: school).count >= TEACHER_RESPONSE_THRESHOLD
teacher_survey_item_responses = SurveyItemResponse.teacher_responses_for_measure(measure).where(academic_year: academic_year, school: school)
average_number_of_survey_item_responses = teacher_survey_item_responses.count / measure.teacher_survey_items.count
meets_teacher_threshold = average_number_of_survey_item_responses >= TEACHER_RESPONSE_THRESHOLD
end
if measure.includes_student_survey_items?
meets_student_threshold = SurveyItemResponse.for_student_responses_for_measure(measure).where(academic_year: academic_year, school: school).count >= STUDENT_RESPONSE_THRESHOLD
student_survey_item_responses = SurveyItemResponse.student_responses_for_measure(measure).where(academic_year: academic_year, school: school)
average_number_of_survey_item_responses = student_survey_item_responses.count / measure.student_survey_items.count
meets_student_threshold = average_number_of_survey_item_responses >= STUDENT_RESPONSE_THRESHOLD
end
meets_teacher_threshold and meets_student_threshold

@ -29,33 +29,33 @@ feature 'School dashboard', type: feature do
let(:password) { 'winchester!' }
before :each do
survey_item_responses = []
survey_items_for_measure_1A_i.each do |survey_item|
200.times do
SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school,
survey_item: survey_item, likert_score: 4
SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD.times do
survey_item_responses << SurveyItemResponse.new(response_id: rand.to_s, academic_year: ay_2020_21, school: school, survey_item: survey_item, likert_score: 4)
end
end
survey_items_for_measure_2A_i.each do |survey_item|
200.times do
SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school,
survey_item: survey_item, likert_score: 5
SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD.times do
survey_item_responses << SurveyItemResponse.new(response_id: rand.to_s, academic_year: ay_2020_21, school: school, survey_item: survey_item, likert_score: 5)
end
end
survey_items_for_measure_4C_i.each do |survey_item|
200.times do
SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school,
survey_item: survey_item, likert_score: 1
SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD.times do
survey_item_responses << SurveyItemResponse.new(response_id: rand.to_s, academic_year: ay_2020_21, school: school, survey_item: survey_item, likert_score: 1)
end
end
survey_items_for_subcategory.each do |survey_item|
200.times do
SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school,
survey_item: survey_item, likert_score: 4
survey_item_responses << SurveyItemResponse.new(response_id: rand.to_s, academic_year: ay_2020_21, school: school, survey_item: survey_item, likert_score: 4)
end
end
SurveyItemResponse.import survey_item_responses
end
scenario 'User authentication fails' do

@ -11,15 +11,17 @@ describe SurveyItemResponse, type: :model do
let(:teacher_survey_item_2) { create(:survey_item, survey_item_id: 't-question-2', measure: measure) }
let(:teacher_survey_item_3) { create(:survey_item, survey_item_id: 't-question-3', measure: measure) }
context 'and there is sufficient teacher data' do
context "and the number of responses for each of the measure's survey items meets the teacher threshold of 17" do
before :each do
4.times do
17.times do
create(:survey_item_response, survey_item: teacher_survey_item_1, academic_year: ay, school: school, likert_score: 3)
create(:survey_item_response, survey_item: teacher_survey_item_1, academic_year: ay, school: school, likert_score: 5)
create(:survey_item_response, survey_item: teacher_survey_item_2, academic_year: ay, school: school, likert_score: 3)
create(:survey_item_response, survey_item: teacher_survey_item_2, academic_year: ay, school: school, likert_score: 5)
end
create(:survey_item_response, survey_item: teacher_survey_item_2, academic_year: ay, school: school, likert_score: 4)
17.times do
create(:survey_item_response, survey_item: teacher_survey_item_2, academic_year: ay, school: school, likert_score: 4)
end
17.times do
create(:survey_item_response, survey_item: teacher_survey_item_3, academic_year: ay, school: school, likert_score: 5)
end
end
it 'returns the average of the likert scores of the survey items' do
@ -27,10 +29,53 @@ describe SurveyItemResponse, type: :model do
end
end
context 'and there is insufficient teacher data' do
context "and the average number of responses across the measure's survey items meets the teacher threshold of 17" do
before :each do
(SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1).times do
create(:survey_item_response, survey_item: teacher_survey_item_1, academic_year: ay, school: school)
19.times do
create(:survey_item_response, survey_item: teacher_survey_item_1, academic_year: ay, school: school, likert_score: 3)
end
16.times do
create(:survey_item_response, survey_item: teacher_survey_item_2, academic_year: ay, school: school, likert_score: 4)
end
16.times do
create(:survey_item_response, survey_item: teacher_survey_item_3, academic_year: ay, school: school, likert_score: 5)
end
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)).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
16.times do
create(:survey_item_response, survey_item: teacher_survey_item_1, academic_year: ay, school: school, likert_score: rand)
end
16.times do
create(:survey_item_response, survey_item: teacher_survey_item_2, academic_year: ay, school: school, likert_score: rand)
end
16.times do
create(:survey_item_response, survey_item: teacher_survey_item_3, academic_year: ay, school: school, likert_score: rand)
end
end
it 'returns nil' do
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school, academic_year: ay)).to be_nil
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
18.times do
create(:survey_item_response, survey_item: teacher_survey_item_1, academic_year: ay, school: school, likert_score: rand)
end
16.times do
create(:survey_item_response, survey_item: teacher_survey_item_2, academic_year: ay, school: school, likert_score: rand)
end
16.times do
create(:survey_item_response, survey_item: teacher_survey_item_3, academic_year: ay, school: school, likert_score: rand)
end
end
@ -43,26 +88,73 @@ describe SurveyItemResponse, type: :model do
context 'when the measure includes only student data' do
let(:student_survey_item_1) { create(:survey_item, survey_item_id: 's-question-1', measure: measure) }
let(:student_survey_item_2) { create(:survey_item, survey_item_id: 's-question-2', measure: measure) }
let(:student_survey_item_3) { create(:survey_item, survey_item_id: 's-question-3', measure: measure) }
context 'and there is sufficient student data' do
context "and the number of responses for each of the measure's survey items meets the student threshold of 196" do
before :each do
(SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD/4).times do
create(:survey_item_response, survey_item: student_survey_item_1, academic_year: ay, school: school, likert_score: 1)
create(:survey_item_response, survey_item: student_survey_item_1, academic_year: ay, school: school, likert_score: 5)
create(:survey_item_response, survey_item: student_survey_item_2, academic_year: ay, school: school, likert_score: 1)
create(:survey_item_response, survey_item: student_survey_item_2, academic_year: ay, school: school, likert_score: 5)
196.times do
create(:survey_item_response, survey_item: student_survey_item_1, academic_year: ay, school: school, likert_score: 3)
end
196.times do
create(:survey_item_response, survey_item: student_survey_item_2, academic_year: ay, school: school, likert_score: 4)
end
196.times do
create(:survey_item_response, survey_item: student_survey_item_3, academic_year: ay, school: school, likert_score: 5)
end
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)).to eq 3
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school, academic_year: ay)).to eq 4
end
end
context 'and there insufficient student data' do
context "and the average number of responses across the measure's survey items meets the student threshold of 196" do
before :each do
(SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD - 1).times do
create(:survey_item_response, survey_item: student_survey_item_1, academic_year: ay, school: school)
200.times do
create(:survey_item_response, survey_item: student_survey_item_1, academic_year: ay, school: school, likert_score: 3)
end
195.times do
create(:survey_item_response, survey_item: student_survey_item_2, academic_year: ay, school: school, likert_score: 4)
end
193.times do
create(:survey_item_response, survey_item: student_survey_item_3, academic_year: ay, school: school, likert_score: 5)
end
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)).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
195.times do
create(:survey_item_response, survey_item: student_survey_item_1, academic_year: ay, school: school, likert_score: rand)
end
195.times do
create(:survey_item_response, survey_item: student_survey_item_2, academic_year: ay, school: school, likert_score: rand)
end
195.times do
create(:survey_item_response, survey_item: student_survey_item_3, academic_year: ay, school: school, likert_score: rand)
end
end
it 'returns nil' do
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school, academic_year: ay)).to be_nil
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
200.times do
create(:survey_item_response, survey_item: student_survey_item_1, academic_year: ay, school: school, likert_score: rand)
end
196.times do
create(:survey_item_response, survey_item: student_survey_item_2, academic_year: ay, school: school, likert_score: rand)
end
191.times do
create(:survey_item_response, survey_item: student_survey_item_3, academic_year: ay, school: school, likert_score: rand)
end
end

Loading…
Cancel
Save