From 2a2777745af69279f3601056e821c0daa61a24ce Mon Sep 17 00:00:00 2001 From: rebuilt Date: Thu, 24 Feb 2022 12:31:21 +0100 Subject: [PATCH] Change the sufficiency threshold from a static number of minimum responses to a minimum response rate of 25 percent --- CHANGELOG.md | 1 + app/controllers/sqm_application_controller.rb | 4 +- app/models/measure.rb | 10 +-- app/models/response_rate.rb | 11 +++ app/models/student_response_rate.rb | 6 +- app/models/subcategory.rb | 16 ++++ app/models/survey_item_response.rb | 4 +- app/models/teacher_response_rate.rb | 6 +- app/presenters/subcategory_presenter.rb | 8 +- doc/architectural_decision_records/3.md | 19 ++++ spec/factories.rb | 8 +- spec/models/legacy/student_spec.rb | 7 -- spec/models/measure_spec.rb | 90 ++++++++++--------- spec/models/response_rate_spec.rb | 77 +++++++--------- spec/models/subcategory_spec.rb | 7 +- spec/presenters/measure_presenter_spec.rb | 3 + spec/presenters/subcategory_presenter_spec.rb | 7 +- spec/system/journey_spec.rb | 28 ++++-- spec/system/sqm_application_spec.rb | 1 + spec/views/categories/show.html.erb_spec.rb | 5 +- 20 files changed, 180 insertions(+), 138 deletions(-) create mode 100644 doc/architectural_decision_records/3.md delete mode 100644 spec/models/legacy/student_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index cc60e9f2..dbcec40e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,3 +27,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Bump ruby version to 3.1.0 - Add previous year data. - Add scale to framework. Calculations for scores bubble up through the framework. +- Change the threshold for sufficiency from a static number of responses to a response rate; from a minimum threshold of 17 teacher responses per survey item in a measure to 25 percent response rate in a subcategory and a minimum of 196 student responses per survey item in a measure to 25 percent response rate in a subcategory. diff --git a/app/controllers/sqm_application_controller.rb b/app/controllers/sqm_application_controller.rb index e0719c0c..6d57366b 100644 --- a/app/controllers/sqm_application_controller.rb +++ b/app/controllers/sqm_application_controller.rb @@ -16,7 +16,9 @@ class SqmApplicationController < ApplicationController @schools = School.includes([:district]).where(district: @district).order(:name) @academic_year = AcademicYear.find_by_range params[:year] @academic_years = AcademicYear.all.order(range: :desc) - @has_empty_dataset = Measure.all.all? do |measure| measure.none_meet_threshold? school: @school, academic_year: @academic_year end + @has_empty_dataset = Measure.all.all? do |measure| + measure.none_meet_threshold? school: @school, academic_year: @academic_year + end end def district_slug diff --git a/app/models/measure.rb b/app/models/measure.rb index ed68b745..4772e064 100644 --- a/app/models/measure.rb +++ b/app/models/measure.rb @@ -83,19 +83,13 @@ class Measure < ActiveRecord::Base def sufficient_student_data?(school:, academic_year:) return false unless includes_student_survey_items? - average_response_count = student_survey_items.map do |survey_item| - survey_item.survey_item_responses.where(school:, academic_year:).count - end.average - average_response_count >= SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD + subcategory.student_response_rate(school:, academic_year:).meets_student_threshold? end def sufficient_teacher_data?(school:, academic_year:) return false unless includes_teacher_survey_items? - average_response_count = teacher_survey_items.map do |survey_item| - survey_item.survey_item_responses.where(school:, academic_year:).count - end.average - average_response_count >= SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD + subcategory.teacher_response_rate(school:, academic_year:).meets_teacher_threshold? end def sufficient_data?(school:, academic_year:) diff --git a/app/models/response_rate.rb b/app/models/response_rate.rb index 22c1b2c5..c6b9ed2a 100644 --- a/app/models/response_rate.rb +++ b/app/models/response_rate.rb @@ -1,4 +1,7 @@ module ResponseRate + TEACHER_RATE_THRESHOLD = 0.25 + STUDENT_RATE_THRESHOLD = 0.25 + def initialize(subcategory:, school:, academic_year:) @subcategory = subcategory @school = school @@ -14,4 +17,12 @@ module ResponseRate (average_responses_per_survey_item / total_possible_responses.to_f * 100).round end + + def meets_student_threshold? + rate >= STUDENT_RATE_THRESHOLD * 100 + end + + def meets_teacher_threshold? + rate >= TEACHER_RATE_THRESHOLD * 100 + end end diff --git a/app/models/student_response_rate.rb b/app/models/student_response_rate.rb index 42cb3a81..44020ba9 100644 --- a/app/models/student_response_rate.rb +++ b/app/models/student_response_rate.rb @@ -4,11 +4,11 @@ class StudentResponseRate private def survey_item_count - @student_survey_item_count ||= @subcategory.measures.map { |measure| measure.student_survey_items.count }.sum + @survey_item_count ||= @subcategory.measures.map { |measure| measure.student_survey_items.count }.sum end def response_count - @student_response_count ||= @subcategory.measures.map do |measure| + @response_count ||= @subcategory.measures.map do |measure| measure.student_survey_items.map do |survey_item| survey_item.survey_item_responses.where(school: @school, academic_year: @academic_year).count end.sum @@ -16,7 +16,7 @@ class StudentResponseRate end def total_possible_responses - @total_possible_student_responses ||= begin + @total_possible_responses ||= begin total_responses = Respondent.where(school: @school, academic_year: @academic_year).first return 0 unless total_responses.present? diff --git a/app/models/subcategory.rb b/app/models/subcategory.rb index d6789d9e..975e9607 100644 --- a/app/models/subcategory.rb +++ b/app/models/subcategory.rb @@ -10,4 +10,20 @@ class Subcategory < ActiveRecord::Base scores = scores.reject(&:nil?) scores.average end + + def student_response_rate(school:, academic_year:) + @student_response_rate ||= Hash.new do |memo| + memo[[school, academic_year]] = StudentResponseRate.new(subcategory: self, school:, academic_year:) + end + + @student_response_rate[[school, academic_year]] + end + + def teacher_response_rate(school:, academic_year:) + @teacher_response_rate ||= Hash.new do |memo| + memo[[school, academic_year]] = TeacherResponseRate.new(subcategory: self, school:, academic_year:) + end + + @teacher_response_rate[[school, academic_year]] + end end diff --git a/app/models/survey_item_response.rb b/app/models/survey_item_response.rb index 03fbd142..8479b5d9 100644 --- a/app/models/survey_item_response.rb +++ b/app/models/survey_item_response.rb @@ -1,6 +1,6 @@ class SurveyItemResponse < ActiveRecord::Base - TEACHER_RESPONSE_THRESHOLD = 17 - STUDENT_RESPONSE_THRESHOLD = 196 + TEACHER_RESPONSE_THRESHOLD = 2 + STUDENT_RESPONSE_THRESHOLD = 2 belongs_to :academic_year belongs_to :school diff --git a/app/models/teacher_response_rate.rb b/app/models/teacher_response_rate.rb index e38d0ef6..97c801f4 100644 --- a/app/models/teacher_response_rate.rb +++ b/app/models/teacher_response_rate.rb @@ -12,11 +12,11 @@ class TeacherResponseRate end def survey_item_count - @teacher_survey_item_count ||= @subcategory.measures.map { |measure| measure.teacher_survey_items.count }.sum + @survey_item_count ||= @subcategory.measures.map { |measure| measure.teacher_survey_items.count }.sum end def response_count - @teacher_response_count ||= @subcategory.measures.map do |measure| + @response_count ||= @subcategory.measures.map do |measure| measure.teacher_survey_items.map do |survey_item| survey_item.survey_item_responses.where(school: @school, academic_year: @academic_year).count end.sum @@ -24,7 +24,7 @@ class TeacherResponseRate end def total_possible_responses - @total_possible_teacher_responses ||= begin + @total_possible_responses ||= begin total_responses = Respondent.where(school: @school, academic_year: @academic_year).first return 0 unless total_responses.present? diff --git a/app/presenters/subcategory_presenter.rb b/app/presenters/subcategory_presenter.rb index 0eb3268d..7667c5c6 100644 --- a/app/presenters/subcategory_presenter.rb +++ b/app/presenters/subcategory_presenter.rb @@ -3,10 +3,6 @@ class SubcategoryPresenter @subcategory = subcategory @academic_year = academic_year @school = school - @student_response_rate = StudentResponseRate.new(subcategory: @subcategory, school: @school, - academic_year: @academic_year) - @teacher_response_rate = TeacherResponseRate.new(subcategory: @subcategory, school: @school, - academic_year: @academic_year) end def id @@ -34,11 +30,11 @@ class SubcategoryPresenter end def student_response_rate - @student_response_rate.rate + @subcategory.student_response_rate(school: @school, academic_year: @academic_year).rate end def teacher_response_rate - @teacher_response_rate.rate + @subcategory.teacher_response_rate(school: @school, academic_year: @academic_year).rate end def admin_collection_rate diff --git a/doc/architectural_decision_records/3.md b/doc/architectural_decision_records/3.md new file mode 100644 index 00000000..41b1aa10 --- /dev/null +++ b/doc/architectural_decision_records/3.md @@ -0,0 +1,19 @@ +# Decision record 3 + +# Change the response rate threshold from a static number to a response rate percentage + +## Status + +Completed + +## Context + +We do not show responses if there is insufficient data. We only show a graph if it's statistically meaningful. Previously, the minimum number of responses was set to 17 per teacher survey item and 196 per student survey item. This was calculated at the measure level. + +## Decision + +We have changed the minumim threshold to be a 25 percent response rate at the subcategory level. + +## Consequences + +This story, in combination with the story for marking short-form only schools, means that small population elementary schools will be able to see the responses visualized on the dashboard where before, that data would have been filtered out. diff --git a/spec/factories.rb b/spec/factories.rb index 26f8795b..219bd86b 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -36,7 +36,7 @@ FactoryBot.define do end after(:create) do |subcategory, evaluator| create_list(:measure, evaluator.measures_count, subcategory:).each do |measure| - scale = create(:scale, measure: measure) + scale = create(:scale, measure:) survey_item = create(:teacher_survey_item, scale:) create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item:) end @@ -59,10 +59,10 @@ FactoryBot.define do measure scale_id { "A Scale #{rand}" } factory :teacher_scale do - scale_id {"t-#{rand}"} + scale_id { "t-#{rand}" } end factory :student_scale do - scale_id {"s-#{rand}"} + scale_id { "s-#{rand}" } end end @@ -102,5 +102,7 @@ FactoryBot.define do factory :respondent do school academic_year + total_students { SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD * 4 } + total_teachers { SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD * 4 } end end diff --git a/spec/models/legacy/student_spec.rb b/spec/models/legacy/student_spec.rb deleted file mode 100644 index e91a0c0b..00000000 --- a/spec/models/legacy/student_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'rails_helper' - -module Legacy - RSpec.describe Student, type: :model do - pending "add some examples to (or delete) #{__FILE__}" - end -end diff --git a/spec/models/measure_spec.rb b/spec/models/measure_spec.rb index 79174e83..19e15121 100644 --- a/spec/models/measure_spec.rb +++ b/spec/models/measure_spec.rb @@ -23,6 +23,10 @@ RSpec.describe Measure, type: :model do let(:teacher_approval_low_benchmark) { 3.2 } let(:teacher_ideal_low_benchmark) { 4.2 } + before do + create(:respondent, school:, academic_year:) + create(:respondent, school:, academic_year:) + end describe 'benchmarks' do context 'when a measure includes only one admin data item' do before do @@ -194,7 +198,7 @@ RSpec.describe Measure, type: :model do let(:teacher_survey_item_2) { create(:teacher_survey_item, scale: teacher_scale) } let(:teacher_survey_item_3) { create(:teacher_survey_item, scale: teacher_scale) } - context "and the number of responses for each of the measure's survey items meets the teacher threshold of 17" do + context "and the number of responses for each of the measure's survey items meets the teacher threshold " do before :each do create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: teacher_survey_item_1, academic_year:, school:, likert_score: 3) @@ -217,14 +221,14 @@ RSpec.describe Measure, type: :model do end end - context "and the average number of responses across the measure's survey items meets the teacher threshold of 17" do + context "and the average number of responses across the measure's survey items meets the teacher threshold " do before :each do - create_list(:survey_item_response, 19, survey_item: teacher_survey_item_1, academic_year:, school:, - likert_score: 3) - create_list(:survey_item_response, 16, survey_item: teacher_survey_item_2, academic_year:, school:, - likert_score: 4) - create_list(:survey_item_response, 16, survey_item: teacher_survey_item_3, academic_year:, school:, - likert_score: 5) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD + 1, survey_item: teacher_survey_item_1, academic_year:, school:, + likert_score: 3) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: teacher_survey_item_2, academic_year:, school:, + likert_score: 4) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1, 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 @@ -233,14 +237,14 @@ RSpec.describe Measure, type: :model do end end - context "and none of the measure's survey items meets the teacher threshold of 17" do + context "and none of the measure's survey items meets the teacher threshold " do before :each do - create_list(:survey_item_response, 16, survey_item: teacher_survey_item_1, academic_year:, school:, - likert_score: rand) - create_list(:survey_item_response, 16, survey_item: teacher_survey_item_2, academic_year:, school:, - likert_score: rand) - create_list(:survey_item_response, 16, survey_item: teacher_survey_item_3, academic_year:, school:, - likert_score: rand) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1, survey_item: teacher_survey_item_1, academic_year:, school:, + likert_score: rand) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1, survey_item: teacher_survey_item_2, academic_year:, school:, + likert_score: rand) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1, survey_item: teacher_survey_item_3, academic_year:, school:, + likert_score: rand) end it 'returns nil' do @@ -252,14 +256,14 @@ RSpec.describe Measure, type: :model do end end - context "and the average number of responses across the measure's survey items does not meet the teacher threshold of 17" do + context "and the average number of responses across the measure's survey items does not meet the teacher threshold " do before :each do - create_list(:survey_item_response, 18, survey_item: teacher_survey_item_1, academic_year:, school:, - likert_score: rand) - create_list(:survey_item_response, 16, survey_item: teacher_survey_item_2, academic_year:, school:, - likert_score: rand) - create_list(:survey_item_response, 16, survey_item: teacher_survey_item_3, academic_year:, school:, - likert_score: rand) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: teacher_survey_item_1, academic_year:, school:, + likert_score: rand) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1, survey_item: teacher_survey_item_2, academic_year:, school:, + likert_score: rand) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1, survey_item: teacher_survey_item_3, academic_year:, school:, + likert_score: rand) end it 'returns nil' do @@ -277,7 +281,7 @@ RSpec.describe Measure, type: :model do let(:student_survey_item_2) { create(:student_survey_item, scale: student_scale) } let(:student_survey_item_3) { create(:student_survey_item, scale: student_scale) } - context "and the number of responses for each of the measure's survey items meets the student threshold of 196" do + context "and the number of responses for each of the measure's survey items meets the student threshold " do before :each do create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: student_survey_item_1, academic_year:, school:, likert_score: 3) @@ -299,14 +303,14 @@ RSpec.describe Measure, type: :model do end end - context "and the average number of responses across the measure's survey items meets the student threshold of 196" do + context "and the average number of responses across the measure's survey items meets the student threshold " do before :each do - create_list(:survey_item_response, 200, survey_item: student_survey_item_1, academic_year:, - school:, likert_score: 3) - create_list(:survey_item_response, 195, survey_item: student_survey_item_2, academic_year:, - school:, likert_score: 4) - create_list(:survey_item_response, 193, survey_item: student_survey_item_3, academic_year:, - school:, likert_score: 5) + create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD + 1, survey_item: student_survey_item_1, academic_year:, + school:, likert_score: 3) + create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: student_survey_item_2, academic_year:, + school:, likert_score: 4) + create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD - 1, survey_item: student_survey_item_3, academic_year:, + school:, likert_score: 5) end it 'returns the average of the likert scores of the survey items' do @@ -315,14 +319,14 @@ RSpec.describe Measure, type: :model do end end - context "and none of the measure's survey items meets the student threshold of 196" do + context "and none of the measure's survey items meets the student threshold " do before :each do - create_list(:survey_item_response, 195, survey_item: student_survey_item_1, academic_year:, - school:, likert_score: rand) - create_list(:survey_item_response, 195, survey_item: student_survey_item_2, academic_year:, - school:, likert_score: rand) - create_list(:survey_item_response, 195, survey_item: student_survey_item_3, academic_year:, - school:, likert_score: rand) + create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD - 1, survey_item: student_survey_item_1, academic_year:, + school:, likert_score: rand) + create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD - 1, survey_item: student_survey_item_2, academic_year:, + school:, likert_score: rand) + create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD - 1, survey_item: student_survey_item_3, academic_year:, + school:, likert_score: rand) end it 'returns nil' do @@ -334,14 +338,14 @@ RSpec.describe Measure, type: :model do end end - context "and the average number of responses across the measure's survey items does not meet the student threshold of 196" do + context "and the average number of responses across the measure's survey items does not meet the student threshold " do before :each do - create_list(:survey_item_response, 200, survey_item: student_survey_item_1, academic_year:, - school:, likert_score: rand) - create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, + create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD - 1, survey_item: student_survey_item_1, academic_year:, + school:, likert_score: rand) + create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD - 1, survey_item: student_survey_item_2, academic_year:, school:, likert_score: rand) - create_list(:survey_item_response, 191, survey_item: student_survey_item_3, academic_year:, - school:, likert_score: rand) + create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: student_survey_item_3, academic_year:, + school:, likert_score: rand) end it 'returns nil' do diff --git a/spec/models/response_rate_spec.rb b/spec/models/response_rate_spec.rb index ae5fefd1..36b8e83a 100644 --- a/spec/models/response_rate_spec.rb +++ b/spec/models/response_rate_spec.rb @@ -2,103 +2,86 @@ require 'rails_helper' describe ResponseRate, type: :model do let(:school) { create(:school) } - let(:ay) { create(:academic_year) } + let(:academic_year) { create(:academic_year) } let(:survey_respondents) do - create(:respondent, school: school, total_students: SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, - total_teachers: SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, academic_year: ay) + create(:respondent, school:, academic_year:) end describe StudentResponseRate do let(:subcategory) { create(:subcategory) } - let(:sufficient_measure_1) { create(:measure, subcategory: subcategory) } + let(:sufficient_measure_1) { create(:measure, subcategory:) } let(:sufficient_scale_1) { create(:scale, measure: sufficient_measure_1) } - let(:sufficient_measure_2) { create(:measure, subcategory: subcategory) } + let(:sufficient_measure_2) { create(:measure, subcategory:) } let(:sufficient_scale_2) { create(:scale, measure: sufficient_measure_2) } - let(:insufficient_measure) { create(:measure, subcategory: subcategory) } - let(:insufficient_scale) { create(:scale, measure: insufficient_measure) } let(:sufficient_teacher_survey_item) { create(:teacher_survey_item, scale: sufficient_scale_1) } let(:sufficient_student_survey_item_1) { create(:student_survey_item, scale: sufficient_scale_1) } - let(:insufficient_teacher_survey_item) { create(:teacher_survey_item, scale: insufficient_scale) } let(:sufficient_student_survey_item_2) { create(:student_survey_item, scale: sufficient_scale_2) } - let(:insufficient_student_survey_item) { create(:student_survey_item, scale: insufficient_scale) } before :each do survey_respondents create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: sufficient_teacher_survey_item, - academic_year: ay, school: school, likert_score: 1) + academic_year:, school:, likert_score: 1) create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: sufficient_student_survey_item_1, - academic_year: ay, school: school, likert_score: 4) - create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD + 1, survey_item: sufficient_student_survey_item_2, - 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) + academic_year:, school:, likert_score: 4) + create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: sufficient_student_survey_item_2, + academic_year:, school:, likert_score: 4) end context 'when the average number of student responses per question in a subcategory is equal to the student response threshold' do it 'returns 100 percent' do - expect(StudentResponseRate.new(subcategory: subcategory, school: school, - academic_year: ay).rate).to eq 100 + expect(StudentResponseRate.new(subcategory:, school:, + academic_year:).rate).to eq 25 end end end describe TeacherResponseRate do let(:subcategory) { create(:subcategory) } - let(:sufficient_measure_1) { create(:measure, subcategory: subcategory) } + let(:sufficient_measure_1) { create(:measure, subcategory:) } let(:sufficient_scale_1) { create(:scale, measure: sufficient_measure_1) } - let(:sufficient_measure_2) { create(:measure, subcategory: subcategory) } + let(:sufficient_measure_2) { create(:measure, subcategory:) } let(:sufficient_scale_2) { create(:scale, measure: sufficient_measure_2) } - let(:insufficient_measure) { create(:measure, subcategory: subcategory) } - let(:insufficient_scale) { create(:scale, measure: insufficient_measure) } let(:sufficient_teacher_survey_item_1) { create(:teacher_survey_item, scale: sufficient_scale_1) } let(:sufficient_teacher_survey_item_2) { create(:teacher_survey_item, scale: sufficient_scale_1) } let(:sufficient_teacher_survey_item_3) { create(:teacher_survey_item, scale: sufficient_scale_1) } let(:sufficient_student_survey_item_1) { create(:student_survey_item, scale: sufficient_scale_1) } - let(:insufficient_teacher_survey_item) { create(:teacher_survey_item, scale: insufficient_scale) } - let(:insufficient_student_survey_item) { create(:student_survey_item, scale: insufficient_scale) } before :each do survey_respondents create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: sufficient_teacher_survey_item_1, - academic_year: ay, school: school, likert_score: 1) - create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD + 1, survey_item: sufficient_teacher_survey_item_2, - academic_year: ay, school: school, likert_score: 1) + academic_year:, school:, likert_score: 1) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: sufficient_teacher_survey_item_2, + academic_year:, school:, likert_score: 1) create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: sufficient_student_survey_item_1, - 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) + academic_year:, school:, likert_score: 4) end - context 'when the average number of teacher responses per question in a subcategory is equal to the total possible responses' do - it 'returns 100 percent' do - expect(TeacherResponseRate.new(subcategory: subcategory, school: school, - academic_year: ay).rate).to eq 100 + context 'when the average number of teacher responses per question in a subcategory is at the threshold' do + it 'returns 25 percent' do + expect(TeacherResponseRate.new(subcategory:, school:, + academic_year:).rate).to eq 25 end end - context 'when the average number of teacher responses is 77.9, the response rate averages up to 78 percent' do + context 'when the teacher response rate is not a whole number. eg 29.166%' do before do - create_list(:survey_item_response, 2, survey_item: sufficient_teacher_survey_item_3, - academic_year: ay, school: school, likert_score: 1) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD + 1, survey_item: sufficient_teacher_survey_item_3, + academic_year:, school:, likert_score: 1) end - it 'returns 10 percent' do - expect(TeacherResponseRate.new(subcategory: subcategory, school: school, - academic_year: ay).rate).to eq 78 + it 'it will return the nearest whole number' do + expect(TeacherResponseRate.new(subcategory:, school:, + academic_year:).rate).to eq 29 end end context 'when the average number of teacher responses is greater than the total possible responses' do before do - create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD + 1, survey_item: sufficient_teacher_survey_item_3, - academic_year: ay, school: school, likert_score: 1) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD * 11, survey_item: sufficient_teacher_survey_item_3, + academic_year:, school:, likert_score: 1) end it 'returns 100 percent' do - expect(TeacherResponseRate.new(subcategory: subcategory, school: school, - academic_year: ay).rate).to eq 100 + expect(TeacherResponseRate.new(subcategory:, school:, + academic_year:).rate).to eq 100 end end end diff --git a/spec/models/subcategory_spec.rb b/spec/models/subcategory_spec.rb index 549d7bff..c9c71de3 100644 --- a/spec/models/subcategory_spec.rb +++ b/spec/models/subcategory_spec.rb @@ -4,10 +4,13 @@ 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(:measure_1) { create(:measure, subcategory:) } let(:teacher_scale) { create(:teacher_scale, measure: measure_1) } - let(:measure_2) { create(:measure, subcategory: subcategory) } + let(:measure_2) { create(:measure, subcategory:) } let(:student_scale) { create(:student_scale, measure: measure_2) } + before do + create(:respondent, school:, academic_year:) + end describe '.score' do let(:teacher_survey_item_1) { create(:teacher_survey_item, scale: teacher_scale) } diff --git a/spec/presenters/measure_presenter_spec.rb b/spec/presenters/measure_presenter_spec.rb index b130272f..aaa274c3 100644 --- a/spec/presenters/measure_presenter_spec.rb +++ b/spec/presenters/measure_presenter_spec.rb @@ -8,6 +8,9 @@ describe MeasurePresenter do let(:student_scale) { create(:student_scale, measure:) } let(:admin_scale) { create(:scale, measure:) } let(:measure_presenter) { MeasurePresenter.new(measure:, academic_year:, school:) } + before do + create(:respondent, school:, academic_year:) + end it 'returns the id of the measure' do expect(measure_presenter.id).to eq 'measure-id' diff --git a/spec/presenters/subcategory_presenter_spec.rb b/spec/presenters/subcategory_presenter_spec.rb index 1dbb1602..7e8ac00c 100644 --- a/spec/presenters/subcategory_presenter_spec.rb +++ b/spec/presenters/subcategory_presenter_spec.rb @@ -7,8 +7,7 @@ describe SubcategoryPresenter do create(:subcategory, name: 'A great subcategory', subcategory_id: 'A', description: 'A great description') end let(:survey_respondents) do - create(:respondent, school:, total_students: SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, - total_teachers: 10.0, academic_year:) + create(:respondent, school:, academic_year:) end let(:subcategory_presenter) do survey_respondents @@ -68,11 +67,11 @@ describe SubcategoryPresenter do end it 'returns the student response rate' do - expect(subcategory_presenter.student_response_rate).to eq 100.0 + expect(subcategory_presenter.student_response_rate).to eq 25 end it 'returns the teacher response rate' do - expect(subcategory_presenter.teacher_response_rate).to eq 100 + expect(subcategory_presenter.teacher_response_rate).to eq 50 end it 'returns the admin collection rate' do diff --git a/spec/system/journey_spec.rb b/spec/system/journey_spec.rb index baf98cad..39bca07f 100644 --- a/spec/system/journey_spec.rb +++ b/spec/system/journey_spec.rb @@ -9,30 +9,36 @@ describe 'District Admin', js: true do let(:category) { Category.find_by_name('Teachers & Leadership') } let(:subcategory) { Subcategory.find_by_name('Teachers & The Teaching Environment') } let(:measures_for_subcategory) { Measure.where(subcategory:) } - let(:scales_for_subcategory) {Scale.where(measure: measures_for_subcategory)} + let(:scales_for_subcategory) { Scale.where(measure: measures_for_subcategory) } let(:survey_items_for_subcategory) { SurveyItem.where(scale: scales_for_subcategory) } let(:measure_1A_i) { Measure.find_by_measure_id('1A-i') } let(:measure_2A_i) { Measure.find_by_measure_id('2A-i') } + let(:measure_2A_ii) { Measure.find_by_measure_id('2A-ii') } let(:measure_4C_i) { Measure.find_by_measure_id('4C-i') } let(:measure_with_no_survey_responses) { Measure.find_by_measure_id('3A-i') } - let(:survey_item_1_for_measure_1A_i) { SurveyItem.create scale: measure_1A_i.scales.first, survey_item_id: rand.to_s } - let(:survey_item_2_for_measure_1A_i) { SurveyItem.create scale: measure_1A_i.scales.first, survey_item_id: rand.to_s } - let(:survey_items_for_measure_1A_i) { measure_1A_i.survey_items } let(:survey_items_for_measure_2A_i) { measure_2A_i.survey_items } + let(:survey_items_for_measure_2A_ii) { measure_2A_ii.survey_items } let(:survey_items_for_measure_4C_i) { measure_4C_i.survey_items } let(:ay_2020_21) { AcademicYear.find_by_range '2020-21' } - let(:ay_2019_20) { AcademicYear.find_by_range '2019-20' } + # let(:ay_2019_20) { AcademicYear.find_by_range '2019-20' } let(:username) { 'winchester' } let(:password) { 'winchester!' } + let(:respondents) do + respondents = Respondent.where(school:).first + respondents.total_students = 8 + respondents.total_teachers = 8 + respondents.save + end before :each do Rails.application.load_seed + respondents survey_item_responses = [] survey_items_for_measure_1A_i.each do |survey_item| @@ -49,6 +55,13 @@ describe 'District Admin', js: true do end end + survey_items_for_measure_2A_ii.each do |survey_item| + SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD.times do + survey_item_responses << SurveyItemResponse.new(response_id: rand.to_s, academic_year: ay_2020_21, + school:, survey_item:, likert_score: 5) + end + end + survey_items_for_measure_4C_i.each do |survey_item| SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD.times do survey_item_responses << SurveyItemResponse.new(response_id: rand.to_s, academic_year: ay_2020_21, @@ -57,7 +70,7 @@ describe 'District Admin', js: true do end survey_items_for_subcategory.each do |survey_item| - 200.times do + 2.times do survey_item_responses << SurveyItemResponse.new(response_id: rand.to_s, academic_year: ay_2020_21, school:, survey_item:, likert_score: 4) end @@ -108,6 +121,7 @@ end def district_admin_sees_student_physical_safety expect(page).to have_text('Student Physical Safety') + expect(page).to have_css("[data-for-measure-id='2A-i'][width='40.0%'][x='60%']") end @@ -159,7 +173,7 @@ def district_admin_sees_overview_content district_admin_sees_student_physical_safety district_admin_sees_problem_solving_emphasis - page.assert_selector('.measure-row-bar', count: 5) + page.assert_selector('.measure-row-bar', count: 6) end def district_admin_sees_browse_content diff --git a/spec/system/sqm_application_spec.rb b/spec/system/sqm_application_spec.rb index 1d20c885..8b0ec019 100644 --- a/spec/system/sqm_application_spec.rb +++ b/spec/system/sqm_application_spec.rb @@ -11,6 +11,7 @@ describe 'SQM Application' do before :each do driven_by :rack_test page.driver.browser.basic_authorize(username, password) + create(:respondent, school:, academic_year:) end context 'when no measures meet their threshold' do diff --git a/spec/views/categories/show.html.erb_spec.rb b/spec/views/categories/show.html.erb_spec.rb index 3e508745..569c1ef2 100644 --- a/spec/views/categories/show.html.erb_spec.rb +++ b/spec/views/categories/show.html.erb_spec.rb @@ -10,8 +10,8 @@ describe 'categories/show' do subcategory1 = create(:subcategory, category:, name: 'A subcategory', description: 'Some description of the subcategory') - subcategory2 = create(:subcategory_with_measures, category:, name: 'Another subcategory', - description: 'Another description of the subcategory') + subcategory2 = create(:subcategory, category:, name: 'Another subcategory', + description: 'Another description of the subcategory') measure1 = create(:measure, subcategory: subcategory1) scale1 = create(:student_scale, measure: measure1) @@ -44,6 +44,7 @@ describe 'categories/show' do assign :academic_year, academic_year assign :academic_years, [academic_year] + create(:respondent, school:, academic_year:) render end