active_metric 2.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +5 -0
- data/Rakefile +37 -0
- data/lib/active_metric.rb +38 -0
- data/lib/active_metric/axis.rb +11 -0
- data/lib/active_metric/behavior/calculates_derivative.rb +18 -0
- data/lib/active_metric/behavior/graph_calculation.rb +78 -0
- data/lib/active_metric/calculators/reservoir.rb +81 -0
- data/lib/active_metric/calculators/standard_deviator.rb +39 -0
- data/lib/active_metric/config/initializers/inflections.rb +4 -0
- data/lib/active_metric/graph_view_model.rb +60 -0
- data/lib/active_metric/measurement.rb +13 -0
- data/lib/active_metric/point_series_data.rb +17 -0
- data/lib/active_metric/report.rb +57 -0
- data/lib/active_metric/report_view_model.rb +106 -0
- data/lib/active_metric/sample.rb +148 -0
- data/lib/active_metric/series_data.rb +26 -0
- data/lib/active_metric/stat.rb +72 -0
- data/lib/active_metric/stat_definition.rb +20 -0
- data/lib/active_metric/statistics/defaults.rb +157 -0
- data/lib/active_metric/statistics/standard_deviation.rb +43 -0
- data/lib/active_metric/subject.rb +117 -0
- data/lib/active_metric/version.rb +3 -0
- data/test/active_metric_test.rb +30 -0
- data/test/axis_test.rb +22 -0
- data/test/behavior_tests/calculates_derivative_test.rb +35 -0
- data/test/behavior_tests/graph_calculation_test.rb +68 -0
- data/test/config/mongoid.yml +13 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/test.log +18597 -0
- data/test/graph_view_model_test.rb +92 -0
- data/test/integration_test.rb +149 -0
- data/test/measurement_test.rb +45 -0
- data/test/mongoid_test.rb +24 -0
- data/test/point_series_data_test.rb +27 -0
- data/test/report_test.rb +73 -0
- data/test/report_view_model_test.rb +94 -0
- data/test/reservoir_test.rb +67 -0
- data/test/sample_test.rb +142 -0
- data/test/series_data_test.rb +20 -0
- data/test/standard_deviator_test.rb +45 -0
- data/test/stat_test.rb +222 -0
- data/test/subject_test.rb +22 -0
- data/test/test_helper.rb +76 -0
- metadata +123 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
require_relative "test_helper"
|
2
|
+
|
3
|
+
module ActiveMetric
|
4
|
+
class GraphViewModelTest < ActiveSupport::TestCase
|
5
|
+
|
6
|
+
EULERS_DAY= MONGO_MAX_LIMIT = (1 << 31) - 1
|
7
|
+
|
8
|
+
test "can retrieve series by label" do
|
9
|
+
gvm = GraphViewModel.create
|
10
|
+
gvm.series_data << generate_series_data(5, "first")
|
11
|
+
gvm.series_data << generate_series_data(5, "second")
|
12
|
+
|
13
|
+
series = gvm.series_for("second")
|
14
|
+
|
15
|
+
assert_equal "second", series.label
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
test "size returns 0 if no series_data" do
|
20
|
+
gvm = GraphViewModel.create
|
21
|
+
assert_equal 0, gvm.size
|
22
|
+
end
|
23
|
+
|
24
|
+
test "can create from definitions" do
|
25
|
+
axises_defintions = [{index: 1, label: "second"},
|
26
|
+
{index: 0, label: "first"},
|
27
|
+
{index: 0, label: "actually first"}]
|
28
|
+
options = {name: "test graph"}
|
29
|
+
|
30
|
+
stat_definitions = []
|
31
|
+
stat_definitions << stat_definition(true)
|
32
|
+
stat_definitions << stat_definition(true)
|
33
|
+
stat_definitions << stat_definition(false)
|
34
|
+
|
35
|
+
gvm = GraphViewModel.create_from_meta_data(axises_defintions, stat_definitions, options)
|
36
|
+
|
37
|
+
assert_equal 2, gvm.y_axises.size
|
38
|
+
|
39
|
+
index_zero_axises = gvm.y_axises.select{|axis| axis.index == 0}
|
40
|
+
|
41
|
+
assert_equal 1, index_zero_axises.size
|
42
|
+
assert_equal 0, index_zero_axises.first.index
|
43
|
+
assert_equal "actually first", index_zero_axises.first.label
|
44
|
+
|
45
|
+
assert_equal 2, gvm.series_data.size
|
46
|
+
end
|
47
|
+
|
48
|
+
test "can read y_axises sorted by index" do
|
49
|
+
axises_defintions = [{index: 1, label: "second"},
|
50
|
+
{index: 0, label: "first"},
|
51
|
+
{index: 0, label: "actually first"}]
|
52
|
+
|
53
|
+
gvm = GraphViewModel.create_from_meta_data(axises_defintions, [], {})
|
54
|
+
|
55
|
+
axises = gvm.ordered_y_axises
|
56
|
+
|
57
|
+
assert_equal 2, axises.size
|
58
|
+
|
59
|
+
assert_equal 0, axises.first.index
|
60
|
+
assert_equal "actually first", axises.first.label
|
61
|
+
|
62
|
+
assert_equal 1, axises.second.index
|
63
|
+
assert_equal "second", axises.second.label
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
test "can retrieve partial array" do
|
68
|
+
subject = Subject.create
|
69
|
+
graph_view_model = subject.graph_view_model
|
70
|
+
graph_view_model.series_data << generate_series_data(4)
|
71
|
+
graph_view_model.series_data << generate_series_data(4,"label 2")
|
72
|
+
|
73
|
+
partial_graph = subject.graph_view_model_starting_at(2)
|
74
|
+
|
75
|
+
assert_equal [[2,2],[3,3]], partial_graph.series_data.first.data
|
76
|
+
assert_equal [[2,2],[3,3]], partial_graph.series_data.second.data
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
def generate_series_data(x_count, label = "label")
|
81
|
+
data = []
|
82
|
+
x_count.times {|x| data << [x,x]}
|
83
|
+
PointSeriesData.new(data: data, label: label)
|
84
|
+
end
|
85
|
+
|
86
|
+
def stat_definition(graphable)
|
87
|
+
axis = graphable ? 0 : -1
|
88
|
+
StatDefinition.new(:name_of_stat,Min,"min_name_of_stat",{axis: axis})
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
module ActiveMetric
|
4
|
+
|
5
|
+
class IntegrationTest < ActiveSupport::TestCase
|
6
|
+
|
7
|
+
test "can calculate correct eightieth percentile for subject" do
|
8
|
+
report = Report.create
|
9
|
+
subject = TestSubject.create :report => report
|
10
|
+
subject2 = TestSubject.create :report => report
|
11
|
+
10.times do |value|
|
12
|
+
subject.calculate TestMeasurement.new(:value => 100 - value, :timestamp => value)
|
13
|
+
end
|
14
|
+
10.times do |value|
|
15
|
+
subject2.calculate TestMeasurement.new(:value => 200 - value, :timestamp => value)
|
16
|
+
end
|
17
|
+
subject2.complete
|
18
|
+
subject.complete
|
19
|
+
assert_equal 99, subject.summary.eightieth_value.value
|
20
|
+
assert_equal 199, subject2.summary.eightieth_value.value
|
21
|
+
end
|
22
|
+
|
23
|
+
test "can calculate correct ninety eighth percentile for subject" do
|
24
|
+
report = Report.create
|
25
|
+
subject = TestSubject.create :report => report
|
26
|
+
subject2 = TestSubject.create :report => report
|
27
|
+
5.times do |value|
|
28
|
+
subject.calculate TestMeasurement.new(:value => 100 - value, :timestamp => value)
|
29
|
+
end
|
30
|
+
5.times do |value|
|
31
|
+
subject.calculate TestMeasurement.new(:value => 150 - value, :timestamp => value)
|
32
|
+
end
|
33
|
+
10.times do |value|
|
34
|
+
subject2.calculate TestMeasurement.new(:value => 200 - value, :timestamp => value)
|
35
|
+
end
|
36
|
+
subject2.complete
|
37
|
+
subject.complete
|
38
|
+
assert_equal 150, subject.summary.ninety_eighth_value.value
|
39
|
+
assert_equal 200, subject2.summary.ninety_eighth_value.value
|
40
|
+
end
|
41
|
+
|
42
|
+
test "can calculate correct percentiles with multiple subjects" do
|
43
|
+
report = Report.create
|
44
|
+
subject = TestSubject.create :report => report
|
45
|
+
subject2 = TestSubject.create :report => report
|
46
|
+
5.times do |value|
|
47
|
+
subject.calculate TestMeasurement.new(:value => 100 - value, :timestamp => value)
|
48
|
+
end
|
49
|
+
5.times do |value|
|
50
|
+
subject.calculate TestMeasurement.new(:value => 150 - value, :timestamp => value)
|
51
|
+
end
|
52
|
+
10.times do |value|
|
53
|
+
subject2.calculate TestMeasurement.new(:value => 155 - value, :timestamp => value)
|
54
|
+
end
|
55
|
+
subject2.complete
|
56
|
+
subject.complete
|
57
|
+
|
58
|
+
assert_equal 149, subject.summary.eightieth_value.value
|
59
|
+
assert_equal 150, subject.summary.ninety_eighth_value.value
|
60
|
+
|
61
|
+
assert_equal 154, subject2.summary.eightieth_value.value
|
62
|
+
assert_equal 155, subject2.summary.ninety_eighth_value.value
|
63
|
+
end
|
64
|
+
|
65
|
+
test "can calculate standard deviations" do
|
66
|
+
report = Report.create
|
67
|
+
subject = TestSubject.create :report => report
|
68
|
+
10.times do |value|
|
69
|
+
subject.calculate TestMeasurement.new(:value => 100 - value, :timestamp => value)
|
70
|
+
end
|
71
|
+
|
72
|
+
subject.complete
|
73
|
+
assert_close_to 2.87, subject.summary.standard_deviation_value.value
|
74
|
+
end
|
75
|
+
|
76
|
+
test "summary should update when samples changes" do
|
77
|
+
report = Report.create
|
78
|
+
subject = TestSubject.create :report => report
|
79
|
+
6.times do |value|
|
80
|
+
subject.calculate TestMeasurement.new(:value => value, :timestamp => value)
|
81
|
+
end
|
82
|
+
|
83
|
+
assert_equal 4.0, subject.summary.eightieth_value.value
|
84
|
+
|
85
|
+
subject.calculate TestMeasurement.new(:value => 6, :timestamp => 6)
|
86
|
+
|
87
|
+
assert_equal 4.0, subject.summary.eightieth_value.value
|
88
|
+
end
|
89
|
+
|
90
|
+
test "subjects should delegate to summaries" do
|
91
|
+
report = Report.create
|
92
|
+
subject = TestSubject.create :report => report
|
93
|
+
6.times do |value|
|
94
|
+
subject.calculate TestMeasurement.new(:value => value, :timestamp => value)
|
95
|
+
end
|
96
|
+
|
97
|
+
assert_equal 4.0, subject.eightieth_value
|
98
|
+
assert_equal 4.0, subject.eightieth_value
|
99
|
+
end
|
100
|
+
|
101
|
+
test "subjects should delegate to document before summaries" do
|
102
|
+
report = Report.create
|
103
|
+
subject = TestSubject.create :report => report, :test_field => "subject name"
|
104
|
+
6.times do |value|
|
105
|
+
subject.calculate TestMeasurement.new(:value => value, :timestamp => value)
|
106
|
+
end
|
107
|
+
assert_equal "subject name", subject.test_field
|
108
|
+
assert_equal 4.0, subject.eightieth_value
|
109
|
+
end
|
110
|
+
|
111
|
+
test "subjects should be able to delegate to non stat properties on summary" do
|
112
|
+
report = Report.create
|
113
|
+
subject = TestSubject.create :report => report
|
114
|
+
6.times do |value|
|
115
|
+
subject.calculate TestMeasurement.new(:value => value, :timestamp => value)
|
116
|
+
end
|
117
|
+
assert_equal 5, subject.duration_in_seconds
|
118
|
+
assert_equal 5, subject.duration_in_seconds
|
119
|
+
end
|
120
|
+
|
121
|
+
test "no measurements or interval samples should be in the database" do
|
122
|
+
report = Report.create
|
123
|
+
subject = TestSubject.create :report => report
|
124
|
+
subject2 = TestSubject.create :report => report
|
125
|
+
11.times do |value|
|
126
|
+
subject.calculate TestMeasurement.new(:value => 100 - value, :timestamp => value)
|
127
|
+
end
|
128
|
+
10.times do |value|
|
129
|
+
subject2.calculate TestMeasurement.new(:value => 200 - value, :timestamp => value)
|
130
|
+
end
|
131
|
+
subject2.complete
|
132
|
+
subject.complete
|
133
|
+
assert_equal 90, subject.min_value
|
134
|
+
assert_equal 191, subject2.min_value
|
135
|
+
|
136
|
+
assert_equal 0, ActiveMetric::Measurement.count
|
137
|
+
assert_equal 0, ActiveMetric::Sample.where(:interval.ne => nil).count
|
138
|
+
assert_equal 2, ActiveMetric::Sample.where(:interval => nil).count
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
def assert_within_threshold(threshold, actual, estimated)
|
144
|
+
range_val = actual * threshold
|
145
|
+
range = ((actual - range_val)..(actual + range_val))
|
146
|
+
assert_within_range range, estimated
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
module ActiveMetric
|
4
|
+
|
5
|
+
class MeasurementTest < ActiveSupport::TestCase
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@measurement = TestMeasurement.new
|
9
|
+
end
|
10
|
+
|
11
|
+
test 'can create measurement' do
|
12
|
+
assert @measurement
|
13
|
+
end
|
14
|
+
|
15
|
+
test 'is a mongoid document' do
|
16
|
+
assert @measurement.kind_of? Mongoid::Document
|
17
|
+
end
|
18
|
+
|
19
|
+
test 'time returns datetime in seconds for timestamp' do
|
20
|
+
@measurement.timestamp = 1318338826385
|
21
|
+
assert_equal Time.at(1318338826), @measurement.time
|
22
|
+
end
|
23
|
+
|
24
|
+
test "converts appropriate fields to integer" do
|
25
|
+
assert_saves_as_integer @measurement, :timestamp
|
26
|
+
end
|
27
|
+
|
28
|
+
test "measurements default timestamp to now" do
|
29
|
+
assert @measurement.timestamp
|
30
|
+
sleep(1)
|
31
|
+
measurement2 = TestMeasurement.new
|
32
|
+
assert measurement2.timestamp
|
33
|
+
|
34
|
+
assert_not_equal @measurement.timestamp, measurement2.timestamp
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def assert_saves_as_integer(measurement, field)
|
40
|
+
measurement.send("#{field}=","12345")
|
41
|
+
measurement.save!
|
42
|
+
assert_equal 12345, measurement.send(field)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class MongoidTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
|
6
|
+
test "inherited documents from class dot new dont get a type" do
|
7
|
+
class TopLevel
|
8
|
+
include Mongoid::Document
|
9
|
+
end
|
10
|
+
|
11
|
+
class SecondLevel < TopLevel
|
12
|
+
end
|
13
|
+
|
14
|
+
second_level = SecondLevel.create
|
15
|
+
assert_equal "MongoidTest::SecondLevel", second_level._type
|
16
|
+
|
17
|
+
klass = Class.new(TopLevel)
|
18
|
+
MongoidTest.const_set(:NewKlass, klass)
|
19
|
+
|
20
|
+
new_object = NewKlass.create
|
21
|
+
assert_equal "MongoidTest::NewKlass", new_object._type
|
22
|
+
#assert_equal nil, new_object._type, "Mongoid correctly sets _type on Anonymous Classes now. Go remove the hack in stat: create_custom_stat WRT _type "
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative "test_helper"
|
2
|
+
|
3
|
+
module ActiveMetric
|
4
|
+
class PointSeriesDataTest < ActiveSupport::TestCase
|
5
|
+
|
6
|
+
test "can push and pop atomically" do
|
7
|
+
gvm = GraphViewModel.create
|
8
|
+
psd = PointSeriesData.new(data: [[1,1],[2,2]])
|
9
|
+
gvm.series_data << psd
|
10
|
+
|
11
|
+
psd.pop_data
|
12
|
+
|
13
|
+
assert_equal [[1,1]], psd.data
|
14
|
+
|
15
|
+
psd.push_data([3,3])
|
16
|
+
|
17
|
+
assert_equal [[1,1],[3,3]], psd.data
|
18
|
+
end
|
19
|
+
|
20
|
+
test "can calculate size of data" do
|
21
|
+
psd = PointSeriesData.new(data: [[1,1],[2,2]])
|
22
|
+
|
23
|
+
assert_equal 2, psd.size
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
data/test/report_test.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
module ActiveMetric
|
4
|
+
|
5
|
+
class ReportTest < ActiveSupport::TestCase
|
6
|
+
|
7
|
+
|
8
|
+
test "method missing for subjects" do
|
9
|
+
report = Report.create
|
10
|
+
subjects = 2.times.map {TestSubject.create :report => report}
|
11
|
+
assert_equal subjects, report.test_subjects
|
12
|
+
end
|
13
|
+
|
14
|
+
test "responds properly to method missing if not a subject name" do
|
15
|
+
report = Report.create
|
16
|
+
assert_raises NoMethodError do
|
17
|
+
report.bad_method
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
test "can still use dynamic fields with overwritten method missing" do
|
22
|
+
report = Report.create :some_random_field => "value"
|
23
|
+
assert_equal "value", report.some_random_field
|
24
|
+
end
|
25
|
+
|
26
|
+
test "can still access dynamic fields with subjects in name" do
|
27
|
+
report = Report.create :some_subjects => "value"
|
28
|
+
assert_equal "value", report.some_subjects
|
29
|
+
end
|
30
|
+
|
31
|
+
test "can delete a report" do
|
32
|
+
report = Report.create
|
33
|
+
report.subjects.create
|
34
|
+
|
35
|
+
report.delete
|
36
|
+
|
37
|
+
assert_equal 0, ActiveMetric::Report.count
|
38
|
+
assert_equal 0, ActiveMetric::Subject.count
|
39
|
+
assert_equal 0, ActiveMetric::Sample.count
|
40
|
+
assert_equal 0, ActiveMetric::GraphViewModel.count
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
test "can set display name" do
|
45
|
+
class TestReport < Report
|
46
|
+
|
47
|
+
def set_display_name
|
48
|
+
"Overriden Display Name"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
report = TestReport.create
|
53
|
+
|
54
|
+
assert_equal "Overriden Display Name", report.display_name
|
55
|
+
end
|
56
|
+
|
57
|
+
test "can set display name through attribute" do
|
58
|
+
class TestReport < Report
|
59
|
+
|
60
|
+
def set_display_name
|
61
|
+
"TestReport Display Name"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
report = TestReport.create display_name: "Overriden Display Name"
|
66
|
+
|
67
|
+
assert_equal "Overriden Display Name", report.display_name
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require_relative "test_helper"
|
2
|
+
|
3
|
+
module ActiveMetric
|
4
|
+
class ReportViewModelTest < ActiveSupport::TestCase
|
5
|
+
|
6
|
+
class TestReportViewModel < ActiveMetric::ReportViewModel
|
7
|
+
|
8
|
+
table :table1 do
|
9
|
+
column "header 1", :field1
|
10
|
+
column "header 2", :field2, :precision => 2
|
11
|
+
column "header 3", :field3, :format => :duration_with_format
|
12
|
+
end
|
13
|
+
|
14
|
+
table :table2 do
|
15
|
+
column "header 1", :field1
|
16
|
+
column "header 2", :field2
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
test "can instantiate a view model" do
|
22
|
+
rvm = TestReportViewModel.new
|
23
|
+
rvm.add_table :table1, subjects
|
24
|
+
table = rvm.tables.first
|
25
|
+
|
26
|
+
expected_headers = ["header 1", "header 2", "header 3"]
|
27
|
+
assert_equal expected_headers, table.headers
|
28
|
+
|
29
|
+
expected_cells = ["name",2.8345, 3]
|
30
|
+
expected_cell_options = [{},{:precision =>2},{:format => :duration_with_format}]
|
31
|
+
table.rows.each do |row|
|
32
|
+
assert_equal expected_cells, row.cells.map(&:value)
|
33
|
+
assert_equal expected_cell_options, row.cells.map(&:format_options)
|
34
|
+
assert row.has_series
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
test "cannot add a table that does not exist" do
|
39
|
+
rvm = TestReportViewModel.new
|
40
|
+
assert_raise ReportViewModel::TableDoesNotExist do
|
41
|
+
rvm.add_table :bad_table, subjects
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
test "can have multiple tables" do
|
46
|
+
rvm = TestReportViewModel.new
|
47
|
+
rvm.add_table :table1, subjects
|
48
|
+
rvm.add_table :table2, subjects
|
49
|
+
rvm.add_table :table1, subjects
|
50
|
+
|
51
|
+
table1_headers = ["header 1", "header 2", "header 3"]
|
52
|
+
table2_headers = ["header 1", "header 2"]
|
53
|
+
|
54
|
+
assert_equal table1_headers, rvm.tables[0].headers
|
55
|
+
assert_equal table2_headers, rvm.tables[1].headers
|
56
|
+
assert_equal table1_headers, rvm.tables[2].headers
|
57
|
+
|
58
|
+
table1_data = ["name",2.8345, 3]
|
59
|
+
table2_data = ["name",2.8345]
|
60
|
+
table3_data = ["name",2.8345, 3]
|
61
|
+
|
62
|
+
assert_table_data table1_data, rvm.tables[0]
|
63
|
+
assert_table_data table2_data, rvm.tables[1]
|
64
|
+
assert_table_data table3_data, rvm.tables[2]
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def assert_table_data(data, table)
|
69
|
+
table.rows.each do |row|
|
70
|
+
assert_equal data, row.cells.map(&:value)
|
71
|
+
assert_equal "1", row.row_id
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def subjects
|
76
|
+
subject = create_row_data(field1: "name",
|
77
|
+
field2: 2.8345,
|
78
|
+
field3: 3)
|
79
|
+
|
80
|
+
subject.stubs(:to_param).returns("1")
|
81
|
+
subject.stubs(:has_graph_data).returns(true)
|
82
|
+
[subject]
|
83
|
+
end
|
84
|
+
|
85
|
+
def create_row_data(values)
|
86
|
+
row_data = mock
|
87
|
+
values.each do |key,value|
|
88
|
+
row_data.stubs(key).returns(value)
|
89
|
+
end
|
90
|
+
row_data
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|