Browse files

Implement summary by day, add lots of RDoc, and remove unnecessary co…

…lumns from display
  • Loading branch information...
1 parent e14026a commit bccc8e1ba39ca14dc8af920d68e2f13916e337b3 @njonsson committed Jul 15, 2009
View
21 app/controllers/measurements_controller.rb
@@ -3,6 +3,9 @@
# Handles requests for Measurement resources.
class MeasurementsController < ApplicationController
+ # Handles requests:
+ # * GET /measurements/index
+ # * GET /measurements/index.xml
def index
@measurements = Measurement.paginate(options_for_paginate)
@@ -16,10 +19,26 @@ def index
end
end
+ # Handles requests:
+ # * GET /measurements/summary-by-day
+ # * GET /measurements/summary-by-day.xml
+ def summary_by_day
+ @dailies = Daily.paginate(options_for_paginate)
+
+ if request.xhr?
+ render :partial => 'dailies', :object => @dailies
+ return
+ end
+
+ respond_to do |format|
+ format.html # summary_by_day.html.haml
+ end
+ end
+
private
def options_for_paginate
- options = HashWithIndifferentAccess.new(:page => 1, :per_page => 20)
+ options = HashWithIndifferentAccess.new(:page => 1)
options.merge(params.slice(:page, :per_page)).symbolize_keys
end
View
40 app/helpers/measurements_helper.rb
@@ -3,13 +3,51 @@
# Provides view helpers to MeasurementsController views.
module MeasurementsHelper
+ # Returns the text for the Average Measurement in Time Slot column header.
+ def average_measurement_in_time_slot_column_header
+ average_something_in_time_slot_column_header 'Measurement'
+ end
+
+ # Returns the text for the Average Skew in Time Slot column header.
+ def average_skew_in_time_slot_column_header
+ average_something_in_time_slot_column_header 'Skew'
+ end
+
+ # Returns the text for the Date/Time column header.
def date_time_column_header
header = ''
if @measurements.any? { |m| m.approximate_time? }
- header << content_tag(:span, '(≈ Approximate) ', :class => 'approximate')
+ header = append_approximate_parenthesis(header)
end
header << 'Date/Time'
header
end
+ # Returns _risk_grade_, marked up in HTML.
+ def formatted_risk_grade(risk_grade)
+ letter_grade, plus_or_minus = risk_grade.split('')
+ return letter_grade unless plus_or_minus
+ content = "#{letter_grade}#{plus_or_minus.gsub '-', '&ndash;'}"
+ plus_or_minus_title = {'+' => 'plus', '-' => 'minus'}
+ content_tag :abbr,
+ content,
+ :title => "#{letter_grade}-#{plus_or_minus_title[plus_or_minus]}"
+ end
+
+private
+
+ def append_approximate_parenthesis(text)
+ text + content_tag(:span, '(≈&nbsp;Approximate) ', :class => 'approximate')
+ end
+
+ # Returns the text for the Average Measurement in Time Slot column header.
+ def average_something_in_time_slot_column_header(something)
+ header = "Average #{something} in "
+ if @dailies.any?(&:contains_approximate_times?)
+ header = append_approximate_parenthesis(header)
+ end
+ header << 'Time Slot'
+ header
+ end
+
end
View
66 app/models/aggregate.rb
@@ -3,6 +3,8 @@
# Represents a set of aggregate Measurement statistics.
class Aggregate < ActiveRecord::Base
+ TIME_SLOTS = %w(a b c d e f) #:nodoc:
+
abstract_class = true
attr_protected :id, :type, :created_at, :updated_at
@@ -26,33 +28,61 @@ class Aggregate < ActiveRecord::Base
validates_numericality_of :average_skew,
:greater_than_or_equal_to => 0,
:allow_blank => true
- %w(a b c d e f).each do |time_slot|
- validates_numericality_of :"average_value_in_time_slot_#{time_slot}",
+ TIME_SLOTS.each do |time_slot|
+ validates_numericality_of "average_value_in_time_slot_#{time_slot}",
:greater_than => 0,
:allow_blank => true
- validates_numericality_of :"average_skew_in_time_slot_#{time_slot}",
+ validates_numericality_of "average_skew_in_time_slot_#{time_slot}",
:greater_than_or_equal_to => 0,
:allow_blank => true
end
validates_length_of :notes, :maximum => 255, :allow_blank => true
default_scope :order => 'type, period_ends_on DESC'
- def measured_slots_count
- %w(a b c d e f).inject([]) do |result, time_slot|
- result + [send(:"average_value_in_time_slot_#{time_slot}")]
+ # Returns <tt>:critical</tt>, <tt>:moderate</tt> or +nil+ according to the
+ # severity of Aggregate#average_skew.
+ def average_skew_severity
+ Severity.of_skew average_skew
+ end
+
+ # Returns <tt>:critical</tt>, <tt>:moderate</tt> or +nil+ according to the
+ # severity of Aggregate#maximum_value.
+ def maximum_value_severity
+ Severity.of_skew Measurement.skew_of(maximum_value)
+ end
+
+ # Returns <tt>:critical</tt>, <tt>:moderate</tt> or +nil+ according to the
+ # severity of Aggregate#minimum_value.
+ def minimum_value_severity
+ Severity.of_skew Measurement.skew_of(minimum_value)
+ end
+
+ # Returns the number of measurements in the
+ # <i>average_value_in_time_slot_*</i> attributes.
+ def measured_time_slots_count
+ TIME_SLOTS.inject([]) do |result, time_slot|
+ result + [send("average_value_in_time_slot_#{time_slot}")]
end.compact.length
end
- def measured_slots_count_severity
- Severity.of_measured_slots_count measured_slots_count
+ # Returns <tt>:critical</tt>, <tt>:moderate</tt> or +nil+ according to the
+ # severity of Aggregate#measured_time_slots_count.
+ def measured_time_slots_count_severity
+ Severity.of_measured_time_slots_count measured_time_slots_count
end
+ # Returns the calculated "risk skew" of an Aggregate. This number greater than
+ # or equal to 0.0 represents how far from the ideal the Aggregate is. A number
+ # indicates higher risk.
def risk_index
- [(((weighted_average_skew * 15.0) + (5.0 - measured_slots_count)) / 3.0),
+ [(((weighted_average_skew * 15.0) + (5.0 - measured_time_slots_count)) /
+ 3.0),
0].max
end
+ # Returns a letter grade associated with Aggregate#risk_index. The grade is
+ # between "A+" and "F", depending on how far that number is from 0.0.
def risk_grade
rounded_risk_index = risk_index.round(6)
return 'A+' if (rounded_risk_index < 0.333333)
@@ -70,17 +100,31 @@ def risk_grade
'F'
end
+ # Returns <tt>:critical</tt>, <tt>:moderate</tt> or +nil+ according to the
+ # severity of Aggregate#risk_index.
def risk_severity
Severity.of_risk_index risk_index
end
+ TIME_SLOTS.each do |time_slot|
+ define_method "severity_of_average_skew_in_time_slot_#{time_slot}" do
+ skew = send("average_skew_in_time_slot_#{time_slot}")
+ return nil unless skew
+ Severity.of_skew skew
+ end
+ end
+
+ # Returns the arithmetic mean of the <i>average_value_in_time_slot_*</i>
+ # attributes.
def weighted_average_skew
- skews = %w(a b c d e f).collect do |time_slot|
- send :"average_skew_in_time_slot_#{time_slot}"
+ skews = TIME_SLOTS.collect do |time_slot|
+ send "average_skew_in_time_slot_#{time_slot}"
end.compact
Math.mean *skews
end
+ # Returns <tt>:critical</tt>, <tt>:moderate</tt> or +nil+ according to the
+ # severity of Aggregate#weighted_average_skew.
def weighted_average_skew_severity
Severity.of_skew weighted_average_skew
end
View
6 app/models/daily.rb
@@ -2,4 +2,10 @@
# Represents a set of daily aggregate Measurement statistics.
class Daily < Aggregate
+
+ # Returns the default page size for Daily.paginate results.
+ def self.per_page
+ 25
+ end
+
end
View
75 app/models/measurement.rb
@@ -3,54 +3,78 @@
# Represents an individual glucose measurement.
class Measurement < ActiveRecord::Base
+ class << self
+
+ # Returns the default page size for Daily.paginate results.
+ def per_page
+ 25
+ end
+
+ # Returns the calculated "skew" of the specified glucose _value_. This number
+ # between 0.0 and 1.0 represents how far from the ideal _value_ is, either
+ # high or low. A higher skew indicates higher risk.
+ def skew_of(value)
+ 1.0 - ((value / 100.0) ** ((value <= 100.0) ? 1.0 : -1.0))
+ end
+
+ end
+
attr_accessible :at, :approximate_time, :value, :notes
validates_presence_of :at, :value
validates_uniqueness_of :at, :allow_blank => true
validates_numericality_of :value, :greater_than => 0, :allow_blank => true
validates_length_of :notes, :maximum => 255, :allow_blank => true
- before_save :set_adjusted_date_and_time_slot_and_skew
+ before_save :set_adjusted_date_and_time_slot, :set_skew
after_save :recreate_daily_aggregate
default_scope :order => 'at DESC'
+ # Returns <tt>:critical</tt>, <tt>:moderate</tt> or +nil+ according to the
+ # severity of Measurement#skew.
def severity
Severity.of_skew skew
end
private
+ def calculate_average(attribute, adjusted_date, time_slot)
+ Measurement.average attribute,
+ :conditions => {:adjusted_date => adjusted_date,
+ :time_slot => time_slot}
+ end
+
def recreate_daily_aggregate
Daily.delete_all({:period_ends_on => adjusted_date})
days_measurements = Measurement.find(:all,
:conditions => {:adjusted_date => adjusted_date},
:order => 'at')
values = days_measurements.collect(&:value)
- Daily.create! :period_ends_on => adjusted_date,
- :contains_approximate_times => days_measurements.any?(&:approximate_time?),
- :average_value => Math.mean(*values),
- :standard_deviation_of_value => Math.stddevp(*values),
- :maximum_value => values.max,
- :minimum_value => values.min,
- :average_skew => Measurement.average(:skew, :conditions => {:adjusted_date => adjusted_date}),
- :average_value_in_time_slot_a => Measurement.average(:value, :conditions => {:adjusted_date => adjusted_date, :time_slot => 'a'}),
- :average_value_in_time_slot_b => Measurement.average(:value, :conditions => {:adjusted_date => adjusted_date, :time_slot => 'b'}),
- :average_value_in_time_slot_c => Measurement.average(:value, :conditions => {:adjusted_date => adjusted_date, :time_slot => 'c'}),
- :average_value_in_time_slot_d => Measurement.average(:value, :conditions => {:adjusted_date => adjusted_date, :time_slot => 'd'}),
- :average_value_in_time_slot_e => Measurement.average(:value, :conditions => {:adjusted_date => adjusted_date, :time_slot => 'e'}),
- :average_value_in_time_slot_f => Measurement.average(:value, :conditions => {:adjusted_date => adjusted_date, :time_slot => 'f'}),
- :average_skew_in_time_slot_a => Measurement.average(:skew, :conditions => {:adjusted_date => adjusted_date, :time_slot => 'a'}),
- :average_skew_in_time_slot_b => Measurement.average(:skew, :conditions => {:adjusted_date => adjusted_date, :time_slot => 'b'}),
- :average_skew_in_time_slot_c => Measurement.average(:skew, :conditions => {:adjusted_date => adjusted_date, :time_slot => 'c'}),
- :average_skew_in_time_slot_d => Measurement.average(:skew, :conditions => {:adjusted_date => adjusted_date, :time_slot => 'd'}),
- :average_skew_in_time_slot_e => Measurement.average(:skew, :conditions => {:adjusted_date => adjusted_date, :time_slot => 'e'}),
- :average_skew_in_time_slot_f => Measurement.average(:skew, :conditions => {:adjusted_date => adjusted_date, :time_slot => 'f'}),
- :notes => days_measurements.collect(&:notes).compact.join("\n\n")
+ all_notes = days_measurements.collect(&:notes).compact
+ if all_notes.empty?
+ all_notes = nil
+ else
+ all_notes = all_notes.join("\n\n")
+ end
+ averages_attributes = Aggregate::TIME_SLOTS.inject(HashWithIndifferentAccess.new) do |result,
+ time_slot|
+ result["average_value_in_time_slot_#{time_slot}"] = calculate_average(:value, adjusted_date, time_slot)
+ result["average_skew_in_time_slot_#{time_slot}"] = calculate_average(:skew, adjusted_date, time_slot)
+ result
+ end
+ Daily.create! averages_attributes.merge(:period_ends_on => adjusted_date,
+ :contains_approximate_times => days_measurements.any?(&:approximate_time?),
+ :average_value => Math.mean(*values),
+ :standard_deviation_of_value => Math.stddevp(*values),
+ :maximum_value => values.max,
+ :minimum_value => values.min,
+ :average_skew => Measurement.average(:skew, :conditions => {:adjusted_date => adjusted_date}),
+ :notes => all_notes)
end
- def set_adjusted_date_and_time_slot_and_skew
+ def set_adjusted_date_and_time_slot
case self.at.hour
when (0...5)
self.time_slot = 'g'
@@ -77,7 +101,12 @@ def set_adjusted_date_and_time_slot_and_skew
self.time_slot = 'g'
self.adjusted_date = at.to_date
end
- self.skew = 1.0 - ((value / 100.0) ** ((value <= 100.0) ? 1.0 : -1.0));
+ self
+ end
+
+ def set_skew
+ self.skew = Measurement.skew_of(value)
+ self
end
end
View
10 app/models/severity.rb
@@ -6,11 +6,11 @@ module Severity
class << self
# Returns <tt>:critical</tt>, <tt>:moderate</tt> or +nil+ according to the
- # severity of _measured_slots_count_.
- def of_measured_slots_count(measured_slots_count)
- rounded_measured_slots_count = measured_slots_count.to_f.round(6)
- return nil if (rounded_measured_slots_count > 4.0)
- return :moderate if (rounded_measured_slots_count >= 3.5)
+ # severity of _measured_time_slots_count_.
+ def of_measured_time_slots_count(measured_time_slots_count)
+ rounded_measured_time_slots_count = measured_time_slots_count.to_f.round(6)
+ return nil if (rounded_measured_time_slots_count > 4.0)
+ return :moderate if (rounded_measured_time_slots_count >= 3.5)
:critical
end
View
89 app/views/measurements/_dailies.html.haml
@@ -0,0 +1,89 @@
+/ BEGIN measurements/_dailies.html.haml
+
+%table
+ %thead
+ %tr
+ %th{'align' => 'right', 'rowspan' => '2', 'valign' => 'bottom'}<
+ Period Ends
+
+ %th{'align' => 'center', 'colspan' => '4', 'valign' => 'bottom'}<
+ Statistics on Measurements
+
+ %th{'align' => 'center', 'colspan' => '6', 'valign' => 'bottom'}<
+ = average_measurement_in_time_slot_column_header
+
+ %th{'align' => 'right', 'rowspan' => '2', 'valign' => 'bottom'}<
+ Time Slots Measured
+
+ %th{'align' => 'center', 'colspan' => '2', 'valign' => 'bottom'}<
+ Risk
+
+ %th{'align' => 'left', 'rowspan' => '2', 'valign' => 'bottom'}<
+ Notes
+
+ %tr
+ %th{'align' => 'right', 'valign' => 'bottom'}<
+ Average
+
+ %th{'align' => 'right', 'valign' => 'bottom'}<
+ Standard Deviation
+
+ %th{'align' => 'right', 'valign' => 'bottom'}<
+ Maximum
+
+ %th{'align' => 'right', 'valign' => 'bottom'}<
+ Minimum
+
+ - Aggregate::TIME_SLOTS.each do |slot|
+ %th{'align' => 'right', 'valign' => 'bottom'}<
+ = slot
+
+ %th{'align' => 'right', 'valign' => 'bottom'}<
+ Index
+
+ %th{'align' => 'center', 'valign' => 'bottom'}<
+ Grade
+
+ %tbody
+ - @dailies.each do |m|
+ %tr{'class' => m.contains_approximate_times? ? 'approximate' : nil}
+ %td.nowrap{'align' => 'right', 'valign' => 'top'}<
+ = m.period_ends_on.to_formatted_s(:html)
+
+ %td{'align' => 'right', 'class' => m.average_skew_severity, 'title' => m.average_skew_severity, 'valign' => 'top'}<
+ = m.average_value.round
+
+ %td{'align' => 'right', 'class' => m.average_skew_severity, 'title' => m.average_skew_severity, 'valign' => 'top'}<
+ = m.standard_deviation_of_value.round(1)
+
+ %td{'align' => 'right', 'class' => m.maximum_value_severity, 'title' => m.maximum_value_severity, 'valign' => 'top'}<
+ = m.maximum_value.round
+
+ %td{'align' => 'right', 'class' => m.minimum_value_severity, 'title' => m.minimum_value_severity, 'valign' => 'top'}<
+ = m.minimum_value.round
+
+ - Aggregate::TIME_SLOTS.each do |slot|
+ - value = m.send(:"average_value_in_time_slot_#{slot}")
+ %td{'align' => 'right', 'class' => m.send(:"severity_of_average_skew_in_time_slot_#{slot}"), 'title' => m.send(:"severity_of_average_skew_in_time_slot_#{slot}"), 'valign' => 'top'}<
+ = "#{value && m.contains_approximate_times? ? '≈&nbsp;' : nil}#{value ? value.round : nil}"
+
+ %td{'align' => 'right', 'class' => m.measured_time_slots_count_severity, 'title' => m.measured_time_slots_count_severity, 'valign' => 'top'}<
+ = m.measured_time_slots_count
+
+ %td{'align' => 'right', 'class' => m.risk_severity, 'title' => m.risk_severity, 'valign' => 'top'}<
+ %b<
+ = m.risk_index.round(1)
+
+ %td{'align' => 'center', 'class' => m.risk_severity, 'title' => m.risk_severity, 'valign' => 'top'}<
+ %b<
+ = formatted_risk_grade(m.risk_grade)
+
+ - if m.notes
+ %td{'valign' => 'top'}
+ = simple_format(h(m.notes))
+ - else
+ %td{'valign' => 'top'}
+
+= will_paginate @dailies
+
+/ END measurements/_dailies.html.haml
View
12 app/views/measurements/_measurements.html.haml
@@ -15,30 +15,24 @@
%th{'align' => 'right', 'valign' => 'bottom'}<
Value
- %th{'align' => 'right', 'valign' => 'bottom'}<
- Skew
-
%th{'align' => 'left', 'valign' => 'bottom'}<
Notes
%tbody
- @measurements.each do |m|
%tr{'class' => m.approximate_time? ? 'approximate' : nil}
- %td.datetime{'align' => 'right', 'valign' => 'top'}<
- = "#{m.approximate_time ? '≈ ' : nil}#{m.at.to_formatted_s :html}"
+ %td.nowrap{'align' => 'right', 'valign' => 'top'}<
+ = "#{m.approximate_time? ? '≈&nbsp;' : nil}#{m.at.to_formatted_s :html}"
%td{'align' => 'right', 'valign' => 'top'}<
= m.adjusted_date.to_formatted_s(:html)
%td{'align' => 'center', 'valign' => 'top'}<
= m.time_slot
- %td{'align' => 'right', 'class' => m.severity, 'valign' => 'top'}<
+ %td{'align' => 'right', 'class' => m.severity, 'title' => m.severity, 'valign' => 'top'}<
= m.value.round
- %td{'align' => 'right', 'class' => m.severity, 'valign' => 'top'}<
- = m.skew.round(1)
-
- if m.notes
%td{'valign' => 'top'}
= simple_format(h(m.notes))
View
15 app/views/measurements/summary_by_day.html.haml
@@ -0,0 +1,15 @@
+/ BEGIN measurements/summary_by_day.html.haml
+
+- content_for :page_title do
+ Measurement Summary by Day
+
+%h1<
+ Measurement Summary by Day
+
+.content
+ = render :partial => 'dailies', :object => 'dailies'
+
+- content_for :additional_javascripts do
+ = javascript_include_tag 'measurements/pagination.js'
+
+/ END measurements/summary_by_day.html.haml
View
3 config/routes.rb
@@ -35,7 +35,8 @@
# See how all your routes lay out with "rake routes"
- map.resources :measurements
+ map.summary_by_day ':controller/summary-by-day', :action => 'summary_by_day'
+ map.resources :measurements, :collection => {'summary_by_day' => :get}
# Install the default routes as the lowest priority.
# Note: These default routes make all actions in every controller accessible via GET requests. You should
View
BIN public/images/background.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
46 public/stylesheets/general.css
@@ -1,13 +1,19 @@
body {
- font-family: Arial, sans-serif;
- margin: 2em;
+ background-image: url(/images/background.jpg);
+ font-family: Arial, sans-serif;
+ font-size: 90%;
+ margin: 2em;
}
h1, h2, h3, h4, h5, h6, strong, b { font-weight: bold; }
h1, h2, h3, h4, h5, h6 { margin: 0.5em 0; }
-h1 { font-size: 185%; }
+h1 {
+ font-size: 150%;
+ letter-spacing: 0.25em;
+ text-transform: uppercase;
+}
h2 { font-size: 170%; }
@@ -43,24 +49,44 @@ ol li { list-style: decimal inside; }
ul li { list-style: disc outside; }
+table {
+ background-color: white;
+ background-image: none;
+ border: 2px solid dimgray;
+}
+
+caption { padding: 0.5em; }
+
th, td {
- border: 1px solid lightgrey;
- margin: 0.25em;
- padding: 0.25em;
+ border: 1px solid #cccccc;
+ margin: 1px;
+ padding: 0 0.25em;
}
-td.datetime { white-space: nowrap; }
+thead th { border-bottom: 1px solid dimgray; }
+
+a { color: dimgray; }
+
+.nowrap { white-space: nowrap; }
.approximate { font-style: italic; }
+caption.approximate { text-align: right; }
+
.pagination { margin-top: 1em; }
-.moderate { background-color: #ffffaa; }
+.moderate {
+ background-color: #fee774;
+ border-color: #cdad56;
+}
-.critical { background-color: #ffaaaa; }
+.critical {
+ background-color: #fea8a8;
+ border-color: #f47878;
+}
.pagination a { padding: 0.5em; }
.pagination a:hover {
- background-color: lightgrey;
+ font-weight: bold;
}
View
73 test/functional/measurements_controller_test.rb
@@ -3,16 +3,16 @@
class MeasurementsControllerTest < ActionController::TestCase
def setup
- create_measurements! 21
+ Measurement.stubs(:per_page).returns 1
+ create_measurements! 2
end
test 'should handle GET index.html as expected' do
assert_no_difference %w(Measurement.count Aggregate.count) do
get :index
assert_template 'index.html.haml'
assert_equal({}, flash)
- assert_equal Measurement.paginate(:page => 1, :per_page => 20),
- assigns(:measurements)
+ assert_equal Measurement.paginate(:page => 1), assigns(:measurements)
end
end
@@ -21,17 +21,16 @@ def setup
get :index, 'page' => '2'
assert_template 'index.html.haml'
assert_equal({}, flash)
- assert_equal Measurement.paginate(:page => 2, :per_page => 20),
- assigns(:measurements)
+ assert_equal Measurement.paginate(:page => 2), assigns(:measurements)
end
end
test "should handle GET index.html with 'per_page' parameter as expected" do
assert_no_difference %w(Measurement.count Aggregate.count) do
- get :index, 'per_page' => '2'
+ get :index, 'per_page' => '1'
assert_template 'index.html.haml'
assert_equal({}, flash)
- assert_equal Measurement.paginate(:page => 1, :per_page => 2),
+ assert_equal Measurement.paginate(:page => 1, :per_page => 1),
assigns(:measurements)
end
end
@@ -41,8 +40,7 @@ def setup
xhr :get, :index
assert_template '_measurements.html.haml'
assert_equal({}, flash)
- assert_equal Measurement.paginate(:page => 1, :per_page => 20),
- assigns(:measurements)
+ assert_equal Measurement.paginate(:page => 1), assigns(:measurements)
end
end
@@ -51,8 +49,7 @@ def setup
xhr :get, :index, 'page' => '2'
assert_template '_measurements.html.haml'
assert_equal({}, flash)
- assert_equal Measurement.paginate(:page => 2, :per_page => 20),
- assigns(:measurements)
+ assert_equal Measurement.paginate(:page => 2), assigns(:measurements)
end
end
@@ -66,4 +63,58 @@ def setup
end
end
+ test 'should handle GET summary_by_day.html as expected' do
+ assert_no_difference %w(Measurement.count Aggregate.count) do
+ get :summary_by_day
+ assert_template 'summary_by_day.html.haml'
+ assert_equal({}, flash)
+ assert_equal Daily.paginate(:page => 1), assigns(:dailies)
+ end
+ end
+
+ test "should handle GET summary_by_day.html with 'page' parameter as expected" do
+ assert_no_difference %w(Measurement.count Aggregate.count) do
+ get :summary_by_day, 'page' => '2'
+ assert_template 'summary_by_day.html.haml'
+ assert_equal({}, flash)
+ assert_equal Daily.paginate(:page => 2), assigns(:dailies)
+ end
+ end
+
+ test "should handle GET summary_by_day.html with 'per_page' parameter as expected" do
+ assert_no_difference %w(Measurement.count Aggregate.count) do
+ get :summary_by_day, 'per_page' => '2'
+ assert_template 'summary_by_day.html.haml'
+ assert_equal({}, flash)
+ assert_equal Daily.paginate(:page => 1, :per_page => 2), assigns(:dailies)
+ end
+ end
+
+ test 'should handle XHR GET summary_by_day.html as expected' do
+ assert_no_difference %w(Measurement.count Aggregate.count) do
+ xhr :get, :summary_by_day
+ assert_template '_dailies.html.haml'
+ assert_equal({}, flash)
+ assert_equal Daily.paginate(:page => 1), assigns(:dailies)
+ end
+ end
+
+ test "should handle XHR GET summary_by_day.html with 'page' parameter as expected" do
+ assert_no_difference %w(Measurement.count Aggregate.count) do
+ xhr :get, :summary_by_day, 'page' => '2'
+ assert_template '_dailies.html.haml'
+ assert_equal({}, flash)
+ assert_equal Daily.paginate(:page => 2), assigns(:dailies)
+ end
+ end
+
+ test "should handle XHR GET summary_by_day.html with 'per_page' parameter as expected" do
+ assert_no_difference %w(Measurement.count Aggregate.count) do
+ xhr :get, :summary_by_day, 'per_page' => '2'
+ assert_template '_dailies.html.haml'
+ assert_equal({}, flash)
+ assert_equal Daily.paginate(:page => 1, :per_page => 2), assigns(:dailies)
+ end
+ end
+
end
View
39 test/unit/daily_test.rb
@@ -3,6 +3,17 @@
module DailyTest
+ class TimeSlots < ActiveSupport::TestCase
+
+ test 'should have the expected time slots' do
+ assert_equal %w(a b c d e f),
+ Aggregate::TIME_SLOTS,
+ 'Aggregate::TIME_SLOTS must be in synch with the logic of ' +
+ 'Measurement#set_adjusted_date_and_time_slot'
+ end
+
+ end
+
class MissingRequiredAttributes < ActiveSupport::TestCase
def setup
@@ -556,9 +567,9 @@ class Protections < ActiveSupport::TestCase
test 'should not protect contains_approximate_times' do
assert_equal true,
- Daily.new(:contains_approximate_times => true).contains_approximate_times
+ Daily.new(:contains_approximate_times => true).contains_approximate_times?
assert_equal false,
- Daily.new(:contains_approximate_times => false).contains_approximate_times
+ Daily.new(:contains_approximate_times => false).contains_approximate_times?
end
test 'should not protect average_value' do
@@ -667,12 +678,12 @@ def setup
:average_skew_in_time_slot_e => 0.1)
end
- test 'should return 3 when sent measured_slots_count' do
- assert_equal 3, @daily.measured_slots_count
+ test 'should return 3 when sent measured_time_slots_count' do
+ assert_equal 3, @daily.measured_time_slots_count
end
- test 'should return :critical when sent measured_slots_count_severity' do
- assert_equal :critical, @daily.measured_slots_count_severity
+ test 'should return :critical when sent measured_time_slots_count_severity' do
+ assert_equal :critical, @daily.measured_time_slots_count_severity
end
test 'should return expected number when sent weighted_average_skew' do
@@ -706,12 +717,12 @@ def setup
:average_skew_in_time_slot_f => 0.4)
end
- test 'should return 4 when sent measured_slots_count' do
- assert_equal 4, @daily.measured_slots_count
+ test 'should return 4 when sent measured_time_slots_count' do
+ assert_equal 4, @daily.measured_time_slots_count
end
- test 'should return :moderate when sent measured_slots_count_severity' do
- assert_equal :moderate, @daily.measured_slots_count_severity
+ test 'should return :moderate when sent measured_time_slots_count_severity' do
+ assert_equal :moderate, @daily.measured_time_slots_count_severity
end
test 'should return expected number when sent weighted_average_skew' do
@@ -747,12 +758,12 @@ def setup
:average_skew_in_time_slot_f => 0.7)
end
- test 'should return 5 when sent measured_slots_count' do
- assert_equal 5, @daily.measured_slots_count
+ test 'should return 5 when sent measured_time_slots_count' do
+ assert_equal 5, @daily.measured_time_slots_count
end
- test 'should return nil when sent measured_slots_count_severity' do
- assert_nil @daily.measured_slots_count_severity
+ test 'should return nil when sent measured_time_slots_count_severity' do
+ assert_nil @daily.measured_time_slots_count_severity
end
test 'should return expected number when sent weighted_average_skew' do
View
72 test/unit/helpers/measurements_helper_test.rb
@@ -2,6 +2,56 @@
module MeasurementsHelperTest
+ class AverageMeasurementInTimeSlotColumnHeader < ActionView::TestCase
+
+ include MeasurementsHelper
+
+ test 'should return expected text when @dailies is empty' do
+ @dailies = []
+ assert_equal 'Average Measurement in Time Slot',
+ average_measurement_in_time_slot_column_header
+ end
+
+ test 'should return expected text when @dailies contains no approximate times' do
+ @dailies = [stub(:contains_approximate_times? => false)]
+ assert_equal 'Average Measurement in Time Slot',
+ average_measurement_in_time_slot_column_header
+ end
+
+ test 'should return expected text when @dailies contains both an approximate time and an exact time' do
+ @dailies = [stub(:contains_approximate_times? => true),
+ stub(:contains_approximate_times? => false)]
+ assert_equal 'Average Measurement in <span class="approximate">(≈&nbsp;Approximate) </span>Time Slot',
+ average_measurement_in_time_slot_column_header
+ end
+
+ end
+
+ class AverageSkewInTimeSlotColumnHeader < ActionView::TestCase
+
+ include MeasurementsHelper
+
+ test 'should return expected text when @dailies is empty' do
+ @dailies = []
+ assert_equal 'Average Skew in Time Slot',
+ average_skew_in_time_slot_column_header
+ end
+
+ test 'should return expected text when @dailies contains no approximate times' do
+ @dailies = [stub(:contains_approximate_times? => false)]
+ assert_equal 'Average Skew in Time Slot',
+ average_skew_in_time_slot_column_header
+ end
+
+ test 'should return expected text when @dailies contains both an approximate time and an exact time' do
+ @dailies = [stub(:contains_approximate_times? => true),
+ stub(:contains_approximate_times? => false)]
+ assert_equal 'Average Skew in <span class="approximate">(≈&nbsp;Approximate) </span>Time Slot',
+ average_skew_in_time_slot_column_header
+ end
+
+ end
+
class DateTimeColumnHeader < ActionView::TestCase
include MeasurementsHelper
@@ -19,10 +69,30 @@ class DateTimeColumnHeader < ActionView::TestCase
test 'should return expected text when @measurements contains both an approximate time and an exact time' do
@measurements = [stub(:approximate_time? => true),
stub(:approximate_time? => false)]
- assert_equal '<span class="approximate">(≈ Approximate) </span>Date/Time',
+ assert_equal '<span class="approximate">(≈&nbsp;Approximate) </span>Date/Time',
date_time_column_header
end
end
+ class FormattedRiskGrade < ActionView::TestCase
+
+ include MeasurementsHelper
+
+ test 'should return unaltered grade when sent "A"' do
+ assert_equal 'A', formatted_risk_grade('A')
+ end
+
+ test 'should return HTML-formatted grade when sent "B-"' do
+ assert_equal '<abbr title="B-minus">B&ndash;</abbr>',
+ formatted_risk_grade('B-')
+ end
+
+ test 'should return HTML-formatted grade when sent "C+"' do
+ assert_equal '<abbr title="C-plus">C+</abbr>',
+ formatted_risk_grade('C+')
+ end
+
+ end
+
end
View
326 test/unit/measurement_test.rb
@@ -2,6 +2,36 @@
module MeasurementTest
+ module ClassMethods
+
+ class SkewOf < ActiveSupport::TestCase
+
+ test 'should return 0.5 when sent with 50' do
+ assert_equal 0.5, Measurement.skew_of(50)
+ end
+
+ test 'should return 0.2 when sent with 80' do
+ assert_in_delta 0.2, Measurement.skew_of(80), 0.000001
+ end
+
+ test 'should return 0.0 when sent with 100' do
+ actual = Measurement.skew_of(100)
+ assert_equal 0.0, actual
+ assert_instance_of Float, actual
+ end
+
+ test 'should return 0.2 when sent with 125' do
+ assert_in_delta 0.2, Measurement.skew_of(125), 0.000001
+ end
+
+ test 'should return 0.5 when sent with 200' do
+ assert_equal 0.5, Measurement.skew_of(200)
+ end
+
+ end
+
+ end
+
class MissingAtAndValue < ActiveSupport::TestCase
def setup
@@ -363,227 +393,183 @@ def setup
end
- module SkewAndSeverity
+ class Save < ActiveSupport::TestCase
- class With50Value < ActiveSupport::TestCase
+ class WithAssortedDatesAndValues < ActiveSupport::TestCase
- def setup
- @measurement = Measurement.create!(:at => '2009-01-01 12:00',
- :value => 50)
+ def do_create_measurements
+ @skews = []
+ @skews << Measurement.create!(:at => '2009-06-26 08:00',
+ :value => 70,
+ :notes => 'Foo').skew
+ @skews << Measurement.create!(:at => '2009-06-26 16:00',
+ :value => 120,
+ :notes => 'Bar').skew
+ @skews << Measurement.create!(:at => '2009-06-27 08:00',
+ :value => 80,
+ :approximate_time => true,
+ :notes => 'Baz').skew
+ @skews << Measurement.create!(:at => '2009-06-27 16:00',
+ :value => 115).skew
end
- test 'should set skew to 0.5 when saved' do
- assert_equal 0.5, @measurement.skew
+ test 'should create the expected number of Daily Aggregate records' do
+ assert_difference %w(Aggregate.count Daily.count), 2 do
+ do_create_measurements
+ end
end
- test 'should return :critical when sent severity' do
- assert_equal :critical, @measurement.severity
+ test 'should create expected Daily records with the expected period_ends_on values' do
+ do_create_measurements
+ assert_equal [Date.parse('2009-06-27'), Date.parse('2009-06-26')],
+ Daily.all.collect(&:period_ends_on)
end
- end
-
- class With80Value < ActiveSupport::TestCase
+ test 'should create expected Daily records with the expected contains_approximate_times values' do
+ do_create_measurements
+ assert_equal [true, false],
+ Daily.all.collect(&:contains_approximate_times)
+ end
- def setup
- @measurement = Measurement.create!(:at => '2009-01-01 12:00',
- :value => 80)
+ test 'should create expected Daily records with the expected average_value values' do
+ do_create_measurements
+ assert_equal [Math.mean(80, 115), Math.mean(70, 120)],
+ Daily.all.collect(&:average_value)
end
- test 'should set skew to 0.2 when saved' do
- assert_in_delta 0.2, @measurement.skew, 0.00000001
+ test 'should create expected Daily records with the expected standard_deviation_of_value values' do
+ do_create_measurements
+ assert_equal [Math.stddevp(80, 115), Math.stddevp(70, 120)],
+ Daily.all.collect(&:standard_deviation_of_value)
end
- test 'should return :moderate when sent severity' do
- assert_equal :moderate, @measurement.severity
+ test 'should create expected Daily records with the expected maximum_value values' do
+ do_create_measurements
+ assert_equal [115, 120], Daily.all.collect(&:maximum_value)
end
- end
-
- class With100Value < ActiveSupport::TestCase
+ test 'should create expected Daily records with the expected minimum_value values' do
+ do_create_measurements
+ assert_equal [80, 70], Daily.all.collect(&:minimum_value)
+ end
- def setup
- @measurement = Measurement.create!(:at => '2009-01-01 12:00',
- :value => 100)
+ test 'should create expected Daily records with the expected average_skew values' do
+ do_create_measurements
+ assert_equal [Math.mean(*@skews[2..3]).round(6),
+ Math.mean(*@skews[0..1]).round(6)],
+ Daily.all.collect { |d| d.average_skew.round 6 }
end
- test 'should set skew to 0.0 when saved' do
- actual = @measurement.skew
- assert_equal 0.0, actual
- assert_instance_of Float, actual
+ test 'should create expected Daily records with the expected average_value_in_time_slot_a values' do
+ do_create_measurements
+ assert_equal [nil, nil],
+ Daily.all.collect(&:average_value_in_time_slot_a)
end
- test 'should return nil when sent severity' do
- assert_nil @measurement.severity
+ test 'should create expected Daily records with the expected average_value_in_time_slot_b values' do
+ do_create_measurements
+ assert_equal [80, 70], Daily.all.collect(&:average_value_in_time_slot_b)
end
- end
-
- class With125Value < ActiveSupport::TestCase
+ test 'should create expected Daily records with the expected average_value_in_time_slot_c values' do
+ do_create_measurements
+ assert_equal [nil, nil],
+ Daily.all.collect(&:average_value_in_time_slot_c)
+ end
- def setup
- @measurement = Measurement.create!(:at => '2009-01-01 12:00',
- :value => 125)
+ test 'should create expected Daily records with the expected average_value_in_time_slot_d values' do
+ do_create_measurements
+ assert_equal [115, 120],
+ Daily.all.collect(&:average_value_in_time_slot_d)
end
- test 'should set skew to 0.2 when saved' do
- assert_in_delta 0.2, @measurement.skew, 0.00000001
+ test 'should create expected Daily records with the expected average_value_in_time_slot_e values' do
+ do_create_measurements
+ assert_equal [nil, nil],
+ Daily.all.collect(&:average_value_in_time_slot_e)
end
- test 'should return :moderate when sent severity' do
- assert_equal :moderate, @measurement.severity
+ test 'should create expected Daily records with the expected average_value_in_time_slot_f values' do
+ do_create_measurements
+ assert_equal [nil, nil],
+ Daily.all.collect(&:average_value_in_time_slot_f)
end
- end
-
- class With200Value < ActiveSupport::TestCase
+ test 'should create expected Daily records with the expected average_skew_in_time_slot_a values' do
+ do_create_measurements
+ assert_equal [nil, nil],
+ Daily.all.collect(&:average_skew_in_time_slot_a)
+ end
- def setup
- @measurement = Measurement.create!(:at => '2009-01-01 12:00',
- :value => 200)
+ test 'should create expected Daily records with the expected average_skew_in_time_slot_b values' do
+ do_create_measurements
+ assert_equal [@skews[2].round(6), @skews[0].round(6)],
+ Daily.all.collect { |d| d.average_skew_in_time_slot_b.round 6 }
end
- test 'should set skew to 0.5 when saved' do
- assert_equal 0.5, @measurement.skew
+ test 'should create expected Daily records with the expected average_skew_in_time_slot_c values' do
+ do_create_measurements
+ assert_equal [nil, nil],
+ Daily.all.collect(&:average_skew_in_time_slot_c)
end
- test 'should return :critical when sent severity' do
- assert_equal :critical, @measurement.severity
+ test 'should create expected Daily records with the expected average_skew_in_time_slot_d values' do
+ do_create_measurements
+ assert_equal [@skews[3].round(6), @skews[1].round(6)],
+ Daily.all.collect { |d| d.average_skew_in_time_slot_d.round 6 }
end
- end
-
- end
-
- class WithAssortedDatesAndValues < ActiveSupport::TestCase
-
- def do_create_measurements
- @skews = []
- @skews << Measurement.create!(:at => '2009-06-26 08:00',
- :value => 70,
- :notes => 'Foo').skew
- @skews << Measurement.create!(:at => '2009-06-26 16:00',
- :value => 120,
- :notes => 'Bar').skew
- @skews << Measurement.create!(:at => '2009-06-27 08:00',
- :value => 80,
- :approximate_time => true,
- :notes => 'Baz').skew
- @skews << Measurement.create!(:at => '2009-06-27 16:00',
- :value => 115).skew
- end
-
- test 'should create the expected number of Daily Aggregate records' do
- assert_difference %w(Aggregate.count Daily.count), 2 do
+ test 'should create expected Daily records with the expected average_skew_in_time_slot_e values' do
do_create_measurements
+ assert_equal [nil, nil],
+ Daily.all.collect(&:average_skew_in_time_slot_e)
end
+
+ test 'should create expected Daily records with the expected average_skew_in_time_slot_f values' do
+ do_create_measurements
+ assert_equal [nil, nil],
+ Daily.all.collect(&:average_skew_in_time_slot_f)
+ end
+
+ test 'should create expected Daily records with the expected notes values' do
+ do_create_measurements
+ assert_equal ["Baz", "Foo\n\nBar"], Daily.all.collect(&:notes)
+ end
+
end
- test 'should create expected Daily records with the expected period_ends_on values' do
- do_create_measurements
- assert_equal [Date.parse('2009-06-27'), Date.parse('2009-06-26')],
- Daily.all.collect(&:period_ends_on)
- end
-
- test 'should create expected Daily records with the expected contains_approximate_times values' do
- do_create_measurements
- assert_equal [true, false],
- Daily.all.collect(&:contains_approximate_times)
- end
-
- test 'should create expected Daily records with the expected average_value values' do
- do_create_measurements
- assert_equal [Math.mean(80, 115), Math.mean(70, 120)],
- Daily.all.collect(&:average_value)
- end
-
- test 'should create expected Daily records with the expected standard_deviation_of_value values' do
- do_create_measurements
- assert_equal [Math.stddevp(80, 115), Math.stddevp(70, 120)],
- Daily.all.collect(&:standard_deviation_of_value)
- end
-
- test 'should create expected Daily records with the expected maximum_value values' do
- do_create_measurements
- assert_equal [115, 120], Daily.all.collect(&:maximum_value)
- end
-
- test 'should create expected Daily records with the expected minimum_value values' do
- do_create_measurements
- assert_equal [80, 70], Daily.all.collect(&:minimum_value)
- end
-
- test 'should create expected Daily records with the expected average_skew values' do
- do_create_measurements
- assert_equal [Math.mean(*@skews[2..3]).round(6),
- Math.mean(*@skews[0..1]).round(6)],
- Daily.all.collect { |d| d.average_skew.round 6 }
- end
-
- test 'should create expected Daily records with the expected average_value_in_time_slot_a values' do
- do_create_measurements
- assert_equal [nil, nil], Daily.all.collect(&:average_value_in_time_slot_a)
- end
-
- test 'should create expected Daily records with the expected average_value_in_time_slot_b values' do
- do_create_measurements
- assert_equal [80, 70], Daily.all.collect(&:average_value_in_time_slot_b)
- end
-
- test 'should create expected Daily records with the expected average_value_in_time_slot_c values' do
- do_create_measurements
- assert_equal [nil, nil], Daily.all.collect(&:average_value_in_time_slot_c)
- end
-
- test 'should create expected Daily records with the expected average_value_in_time_slot_d values' do
- do_create_measurements
- assert_equal [115, 120], Daily.all.collect(&:average_value_in_time_slot_d)
- end
-
- test 'should create expected Daily records with the expected average_value_in_time_slot_e values' do
- do_create_measurements
- assert_equal [nil, nil], Daily.all.collect(&:average_value_in_time_slot_e)
- end
-
- test 'should create expected Daily records with the expected average_value_in_time_slot_f values' do
- do_create_measurements
- assert_equal [nil, nil], Daily.all.collect(&:average_value_in_time_slot_f)
- end
-
- test 'should create expected Daily records with the expected average_skew_in_time_slot_a values' do
- do_create_measurements
- assert_equal [nil, nil], Daily.all.collect(&:average_skew_in_time_slot_a)
+ def setup
+ @measurement = Measurement.new(:at => '2009-07-06 21:11', :value => 123)
+ Measurement.stubs(:skew_of).returns 0.123456
end
- test 'should create expected Daily records with the expected average_skew_in_time_slot_b values' do
- do_create_measurements
- assert_equal [@skews[2].round(6), @skews[0].round(6)],
- Daily.all.collect { |d| d.average_skew_in_time_slot_b.round 6 }
+ test 'should call Measurement.skew_of with value' do
+ Measurement.expects(:skew_of).with(123).returns 0.123456
+ @measurement.save
end
- test 'should create expected Daily records with the expected average_skew_in_time_slot_c values' do
- do_create_measurements
- assert_equal [nil, nil], Daily.all.collect(&:average_skew_in_time_slot_c)
+ test 'should set skew to the return value of Measurement.skew_of' do
+ @measurement.save
+ assert_equal 0.123456, @measurement.skew
end
- test 'should create expected Daily records with the expected average_skew_in_time_slot_d values' do
- do_create_measurements
- assert_equal [@skews[3].round(6), @skews[1].round(6)],
- Daily.all.collect { |d| d.average_skew_in_time_slot_d.round 6 }
- end
+ end
+
+ class Severity_ < ActiveSupport::TestCase
- test 'should create expected Daily records with the expected average_skew_in_time_slot_e values' do
- do_create_measurements
- assert_equal [nil, nil], Daily.all.collect(&:average_skew_in_time_slot_e)
+ def setup
+ @measurement = Measurement.new
+ @measurement.stubs(:skew).returns :a_skew
+ Severity.stubs(:of_skew).returns :a_severity
end
- test 'should create expected Daily records with the expected average_skew_in_time_slot_f values' do
- do_create_measurements
- assert_equal [nil, nil], Daily.all.collect(&:average_skew_in_time_slot_f)
+ test 'should call Severity.of_skew with skew' do
+ Severity.expects(:of_skew).with :a_skew
+ @measurement.severity
end
- test 'should create expected Daily records with the expected notes values' do
- do_create_measurements
- assert_equal ["Baz", "Foo\n\nBar"], Daily.all.collect(&:notes)
+ test 'should return the return value of Severity.of_skew' do
+ assert_equal :a_severity, @measurement.severity
end
end

0 comments on commit bccc8e1

Please sign in to comment.