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,26 +11,71 @@ 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
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
expect(SurveyItemResponse.score_for_measure(measure: measure, school: school, academic_year: ay)).to eq 4
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