modesty 0.1.0

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.
Files changed (130) hide show
  1. data/Gemfile +13 -0
  2. data/Gemfile.lock +18 -0
  3. data/LICENSE +21 -0
  4. data/README.md +121 -0
  5. data/Rakefile +29 -0
  6. data/VERSION +1 -0
  7. data/init.rb +1 -0
  8. data/lib/modesty.rb +26 -0
  9. data/lib/modesty/api.rb +14 -0
  10. data/lib/modesty/core_ext.rb +5 -0
  11. data/lib/modesty/core_ext/array.rb +21 -0
  12. data/lib/modesty/core_ext/fixnum.rb +5 -0
  13. data/lib/modesty/core_ext/hash.rb +39 -0
  14. data/lib/modesty/core_ext/string.rb +9 -0
  15. data/lib/modesty/core_ext/symbol.rb +33 -0
  16. data/lib/modesty/datastore.rb +51 -0
  17. data/lib/modesty/datastore/redis.rb +180 -0
  18. data/lib/modesty/experiment.rb +87 -0
  19. data/lib/modesty/experiment/base.rb +47 -0
  20. data/lib/modesty/experiment/builder.rb +48 -0
  21. data/lib/modesty/experiment/console.rb +4 -0
  22. data/lib/modesty/experiment/data.rb +75 -0
  23. data/lib/modesty/experiment/interface.rb +29 -0
  24. data/lib/modesty/experiment/significance.rb +376 -0
  25. data/lib/modesty/experiment/stats.rb +163 -0
  26. data/lib/modesty/frameworks/rails.rb +27 -0
  27. data/lib/modesty/identity.rb +32 -0
  28. data/lib/modesty/load.rb +80 -0
  29. data/lib/modesty/load/load_experiments.rb +14 -0
  30. data/lib/modesty/load/load_metrics.rb +17 -0
  31. data/lib/modesty/metric.rb +56 -0
  32. data/lib/modesty/metric/base.rb +38 -0
  33. data/lib/modesty/metric/builder.rb +23 -0
  34. data/lib/modesty/metric/data.rb +133 -0
  35. data/modesty.gemspec +192 -0
  36. data/spec/core_ext_spec.rb +17 -0
  37. data/spec/experiment_spec.rb +239 -0
  38. data/spec/identity_spec.rb +161 -0
  39. data/spec/load_spec.rb +87 -0
  40. data/spec/metric_spec.rb +176 -0
  41. data/spec/rails_spec.rb +48 -0
  42. data/spec/redis_spec.rb +29 -0
  43. data/spec/significance_spec.rb +147 -0
  44. data/spec/spec.opts +1 -0
  45. data/test/myapp/config/modesty.yml +9 -0
  46. data/test/myapp/modesty/experiments/cookbook.rb +4 -0
  47. data/test/myapp/modesty/metrics/kitchen_metrics.rb +9 -0
  48. data/test/myapp/modesty/metrics/stove/burner_metrics.rb +2 -0
  49. data/vendor/.piston.yml +8 -0
  50. data/vendor/mock_redis/.gitignore +2 -0
  51. data/vendor/mock_redis/README +8 -0
  52. data/vendor/mock_redis/lib/mock_redis.rb +10 -0
  53. data/vendor/mock_redis/lib/mock_redis/hash.rb +61 -0
  54. data/vendor/mock_redis/lib/mock_redis/list.rb +6 -0
  55. data/vendor/mock_redis/lib/mock_redis/misc.rb +69 -0
  56. data/vendor/mock_redis/lib/mock_redis/set.rb +108 -0
  57. data/vendor/mock_redis/lib/mock_redis/string.rb +32 -0
  58. data/vendor/redis-rb/.gitignore +8 -0
  59. data/vendor/redis-rb/LICENSE +20 -0
  60. data/vendor/redis-rb/README.markdown +129 -0
  61. data/vendor/redis-rb/Rakefile +155 -0
  62. data/vendor/redis-rb/benchmarking/logging.rb +62 -0
  63. data/vendor/redis-rb/benchmarking/pipeline.rb +51 -0
  64. data/vendor/redis-rb/benchmarking/speed.rb +21 -0
  65. data/vendor/redis-rb/benchmarking/suite.rb +24 -0
  66. data/vendor/redis-rb/benchmarking/thread_safety.rb +38 -0
  67. data/vendor/redis-rb/benchmarking/worker.rb +71 -0
  68. data/vendor/redis-rb/examples/basic.rb +15 -0
  69. data/vendor/redis-rb/examples/dist_redis.rb +43 -0
  70. data/vendor/redis-rb/examples/incr-decr.rb +17 -0
  71. data/vendor/redis-rb/examples/list.rb +26 -0
  72. data/vendor/redis-rb/examples/pubsub.rb +31 -0
  73. data/vendor/redis-rb/examples/sets.rb +36 -0
  74. data/vendor/redis-rb/examples/unicorn/config.ru +3 -0
  75. data/vendor/redis-rb/examples/unicorn/unicorn.rb +20 -0
  76. data/vendor/redis-rb/lib/redis.rb +676 -0
  77. data/vendor/redis-rb/lib/redis/client.rb +201 -0
  78. data/vendor/redis-rb/lib/redis/compat.rb +21 -0
  79. data/vendor/redis-rb/lib/redis/connection.rb +134 -0
  80. data/vendor/redis-rb/lib/redis/distributed.rb +526 -0
  81. data/vendor/redis-rb/lib/redis/hash_ring.rb +131 -0
  82. data/vendor/redis-rb/lib/redis/pipeline.rb +13 -0
  83. data/vendor/redis-rb/lib/redis/subscribe.rb +79 -0
  84. data/vendor/redis-rb/redis.gemspec +29 -0
  85. data/vendor/redis-rb/test/commands_on_hashes_test.rb +46 -0
  86. data/vendor/redis-rb/test/commands_on_lists_test.rb +50 -0
  87. data/vendor/redis-rb/test/commands_on_sets_test.rb +78 -0
  88. data/vendor/redis-rb/test/commands_on_sorted_sets_test.rb +109 -0
  89. data/vendor/redis-rb/test/commands_on_strings_test.rb +70 -0
  90. data/vendor/redis-rb/test/commands_on_value_types_test.rb +88 -0
  91. data/vendor/redis-rb/test/connection_handling_test.rb +87 -0
  92. data/vendor/redis-rb/test/db/.gitignore +1 -0
  93. data/vendor/redis-rb/test/distributd_key_tags_test.rb +53 -0
  94. data/vendor/redis-rb/test/distributed_blocking_commands_test.rb +54 -0
  95. data/vendor/redis-rb/test/distributed_commands_on_hashes_test.rb +12 -0
  96. data/vendor/redis-rb/test/distributed_commands_on_lists_test.rb +18 -0
  97. data/vendor/redis-rb/test/distributed_commands_on_sets_test.rb +85 -0
  98. data/vendor/redis-rb/test/distributed_commands_on_strings_test.rb +50 -0
  99. data/vendor/redis-rb/test/distributed_commands_on_value_types_test.rb +73 -0
  100. data/vendor/redis-rb/test/distributed_commands_requiring_clustering_test.rb +141 -0
  101. data/vendor/redis-rb/test/distributed_connection_handling_test.rb +25 -0
  102. data/vendor/redis-rb/test/distributed_internals_test.rb +18 -0
  103. data/vendor/redis-rb/test/distributed_persistence_control_commands_test.rb +24 -0
  104. data/vendor/redis-rb/test/distributed_publish_subscribe_test.rb +90 -0
  105. data/vendor/redis-rb/test/distributed_remote_server_control_commands_test.rb +31 -0
  106. data/vendor/redis-rb/test/distributed_sorting_test.rb +21 -0
  107. data/vendor/redis-rb/test/distributed_test.rb +60 -0
  108. data/vendor/redis-rb/test/distributed_transactions_test.rb +34 -0
  109. data/vendor/redis-rb/test/encoding_test.rb +16 -0
  110. data/vendor/redis-rb/test/helper.rb +86 -0
  111. data/vendor/redis-rb/test/internals_test.rb +27 -0
  112. data/vendor/redis-rb/test/lint/hashes.rb +90 -0
  113. data/vendor/redis-rb/test/lint/internals.rb +53 -0
  114. data/vendor/redis-rb/test/lint/lists.rb +93 -0
  115. data/vendor/redis-rb/test/lint/sets.rb +66 -0
  116. data/vendor/redis-rb/test/lint/sorted_sets.rb +132 -0
  117. data/vendor/redis-rb/test/lint/strings.rb +98 -0
  118. data/vendor/redis-rb/test/lint/value_types.rb +84 -0
  119. data/vendor/redis-rb/test/persistence_control_commands_test.rb +22 -0
  120. data/vendor/redis-rb/test/pipelining_commands_test.rb +78 -0
  121. data/vendor/redis-rb/test/publish_subscribe_test.rb +151 -0
  122. data/vendor/redis-rb/test/redis_mock.rb +64 -0
  123. data/vendor/redis-rb/test/remote_server_control_commands_test.rb +56 -0
  124. data/vendor/redis-rb/test/sorting_test.rb +44 -0
  125. data/vendor/redis-rb/test/test.conf +8 -0
  126. data/vendor/redis-rb/test/thread_safety_test.rb +34 -0
  127. data/vendor/redis-rb/test/transactions_test.rb +91 -0
  128. data/vendor/redis-rb/test/unknown_commands_test.rb +14 -0
  129. data/vendor/redis-rb/test/url_param_test.rb +52 -0
  130. metadata +277 -0
@@ -0,0 +1,161 @@
1
+ require 'modesty'
2
+
3
+ describe Modesty, "Working with identities" do
4
+ before :each do
5
+ @id = rand 10**10
6
+ end
7
+
8
+ it "can make an identity" do
9
+ Modesty.identify! @id
10
+ Modesty.identity.should == @id
11
+ end
12
+
13
+ it "can identify as nil" do
14
+ Modesty.identify! nil
15
+ Modesty.identity.should be_nil
16
+ end
17
+
18
+ it "can't identify as anything other than a Fixnum or nil." do
19
+ lambda do
20
+ Modesty.identify! "foo"
21
+ end.should raise_error(Modesty::IdentityError)
22
+ end
23
+
24
+ after :all do
25
+ Modesty.instance_variable_set("@identity", nil)
26
+ end
27
+ end
28
+
29
+ describe Modesty, "contextual identity" do
30
+ before :each do
31
+ Modesty.experiments.clear
32
+ Modesty.metrics.clear
33
+ Modesty.data.flushdb
34
+
35
+ Modesty.new_metric :donation_amount do |m|
36
+ m.submetric :birthday_wish
37
+ end
38
+ Modesty.new_metric :donation
39
+ Modesty.new_metric :creation
40
+
41
+ Modesty.new_experiment :creation_page do |e|
42
+ e.metric :creation
43
+ e.metric :donation, :as => :creator
44
+ e.metric :donation_amount, :as => :creator
45
+ end
46
+ @e = Modesty.experiments[:creation_page]
47
+ Modesty.identify! nil
48
+
49
+ @e.chooses :experiment, :for => 500
50
+ @e.chooses :control, :for => 600
51
+ @e.chooses :experiment, :for => 700
52
+ @group_exp = Modesty.metrics[:donation_amount/:creation_page/:experiment]
53
+ @group_ctrl = Modesty.metrics[:donation_amount/:creation_page/:control]
54
+ end
55
+
56
+ it "leaves the other metrics alone" do
57
+ Modesty.with_identity 700 do
58
+ @e.group.should == :experiment
59
+ Modesty.track! :creation
60
+ end
61
+
62
+ m = Modesty.metrics[:creation/:creation_page/:experiment]
63
+ m.distribution.should == {1 => 1}
64
+ end
65
+
66
+ it "expects a passed-in identity for the specified metrics" do
67
+ Modesty.identify! 700
68
+ lambda do
69
+ Modesty.track! :donation
70
+ end.should raise_error(Modesty::IdentityError)
71
+ end
72
+
73
+ it "aggregates counts by the contextual identity's experiment group" do
74
+ Modesty.with_identity 600 do
75
+ lambda do
76
+ #user 600 donated 10 bucks to user 700's birthday wish!
77
+ Modesty.track! :donation_amount, 10, :with => {:creator => 700}
78
+ end.should_not raise_error
79
+ end
80
+ @group_exp.distribution.should == {10 => 1}
81
+ @group_ctrl.distribution.should == {}
82
+
83
+ @e.chooses :experiment, :for => 500
84
+ #user 500 donated 2000 to 600's wish
85
+ Modesty.with_identity 500 do
86
+ Modesty.track! :donation_amount, 2000, :with => {:creator => 600}
87
+ end
88
+
89
+ @group_exp.distribution.should == {10 => 1}
90
+ @group_ctrl.distribution.should == {2000 => 1}
91
+ end
92
+
93
+ describe "with some data" do
94
+ before :each do
95
+ Modesty.data.flushdb
96
+
97
+ # users 500 and 700 hit the experiment
98
+ @e.chooses :experiment, :for => 700
99
+ @e.chooses :control, :for => 500
100
+
101
+ # user 600, who is in the control group, donates $45 to user 700's wish
102
+ Modesty.with_identity 600 do
103
+ Modesty.track! :donation_amount, 45, :with => {:creator => 700}
104
+ end
105
+
106
+ # user 500, who is in the experiment group, donates $30 to user 700's wish
107
+ Modesty.with_identity 500 do
108
+ Modesty.track! :donation_amount/:birthday_wish, 30, :with => {:creator => 700}
109
+ end
110
+
111
+ # a guest donates $15 to user 700's wish
112
+ Modesty.with_identity nil do
113
+ Modesty.track! :donation_amount, 15, :with => {:creator => 700}
114
+ end
115
+ end
116
+
117
+ it "knows its experiment" do
118
+ @group_exp.experiment.should == @e
119
+ end
120
+
121
+ it "aggregates work" do
122
+ @group_exp.aggregate_by(:creators).should == {700 => 90}
123
+ @group_ctrl.aggregate_by(:creators).should == {}
124
+ end
125
+
126
+ it "distributions work" do
127
+ @group_exp.distribution_by(:creator).should == {90 => 1}
128
+ @group_ctrl.distribution_by(:creator).should == {}
129
+ end
130
+
131
+ it "defaults to the given param as identity" do
132
+ @group_exp.aggregate.should == @group_exp.aggregate_by(:creator)
133
+ @group_exp.distribution.should == @group_exp.distribution_by(:creator)
134
+ end
135
+
136
+ it "all, unique, and unidentified_users work" do
137
+ @group_exp.all(:creators).should == [700]
138
+ @group_exp.all(:users).sort.should == [500, 600]
139
+ @group_exp.data.unidentified_users.should == 1
140
+ end
141
+
142
+ it "aggregates and distributes on the experiment" do
143
+ @e.aggregates(:donation_amount).should == {
144
+ :experiment => {
145
+ 700 => 90
146
+ },
147
+ :control => {
148
+ 500 => 0,
149
+ }
150
+ }
151
+ @e.distributions(:donation_amount).should == {
152
+ :experiment => {
153
+ 90 => 1,
154
+ },
155
+ :control => {
156
+ 0 => 1
157
+ }
158
+ }
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,87 @@
1
+ require 'modesty'
2
+
3
+ describe "the config file" do
4
+ before :all do
5
+ Modesty.root = File.join(
6
+ Modesty::TEST,
7
+ 'myapp',
8
+ 'modesty'
9
+ )
10
+ Modesty.environment = 'test'
11
+ Modesty.load_config!
12
+ end
13
+
14
+ it "can set the metrics directory" do
15
+ Modesty.metrics_dir.should ==
16
+ File.expand_path(
17
+ File.join(
18
+ File.dirname(__FILE__),
19
+ "../test/myapp/modesty/metrics"
20
+ )
21
+ )
22
+ end
23
+
24
+ after :all do
25
+ Modesty.root = nil
26
+ end
27
+ end
28
+
29
+ describe "loading metrics" do
30
+ before :all do
31
+ Modesty.root = File.join(
32
+ Modesty::TEST,
33
+ 'myapp'
34
+ )
35
+
36
+ Modesty.environment = 'test'
37
+ Modesty.metrics.clear
38
+ end
39
+
40
+ it "can load metrics" do
41
+ lambda do
42
+ Modesty.load_all_metrics!
43
+ end.should_not raise_error
44
+ end
45
+
46
+ it "doesn't try to load directories" do
47
+ lambda do
48
+ Modesty.load_all_metrics!
49
+ end.should_not raise_error(Errno::EISDIR)
50
+ end
51
+
52
+ it "actually loads the metrics" do
53
+ [
54
+ :baked_goods,
55
+ :baked_goods/:cookies,
56
+ :baked_goods/:brownies,
57
+ :baked_goods/:cake,
58
+ :baked_goods/:cake/:chocolate,
59
+ :baked_goods/:cake/:ice_cream,
60
+ ].each do |m|
61
+ Modesty.metrics.should include m
62
+ end
63
+ end
64
+
65
+ after :all do
66
+ Modesty.root = nil
67
+ end
68
+ end
69
+
70
+ describe "Loading experiments" do
71
+ before :all do
72
+ Modesty.environment = 'test'
73
+ Modesty.metrics.clear
74
+ Modesty.experiments.clear
75
+ Modesty.load_all_metrics!
76
+ end
77
+
78
+ it "can load experiments" do
79
+ lambda do
80
+ Modesty.load_all_experiments!
81
+ end.should_not raise_error
82
+ end
83
+
84
+ it "actually loads experiments" do
85
+ Modesty.experiments.should include :cookbook
86
+ end
87
+ end
@@ -0,0 +1,176 @@
1
+ require 'modesty'
2
+
3
+ describe Modesty::Metric, "Creating Metrics" do
4
+ before :each do
5
+ Modesty.set_store :redis, :mock => true
6
+ Modesty.metrics.clear
7
+ end
8
+
9
+ it "can create a metric without a block" do
10
+ m = Modesty.new_metric(:foo)
11
+ m.slug.should == :foo
12
+ Modesty.metrics[:foo].should == m
13
+ end
14
+
15
+ it "can create a metric with a block" do
16
+ m = Modesty.new_metric :foo do |m|
17
+ m.description "Foo"
18
+ end
19
+ m.slug.should == :foo
20
+ m.description.should == "Foo"
21
+ Modesty.metrics[:foo].should == m
22
+ end
23
+
24
+ it "can create submetrics" do
25
+ Modesty.new_metric :foo do |foo|
26
+ foo.description "Foo"
27
+
28
+ foo.submetric :bar do |bar|
29
+ bar.description "Bar"
30
+
31
+ bar.submetric :baz do |baz|
32
+ baz.description "Baz"
33
+ end
34
+ end
35
+ end
36
+
37
+ Modesty.metrics.should include :foo
38
+ Modesty.metrics.should include :foo/:bar
39
+ Modesty.metrics.should include :foo/:bar/:baz
40
+
41
+ Modesty.metrics[:foo].parent.should == nil
42
+ Modesty.metrics[:foo/:bar].parent.should_not == nil
43
+ Modesty.metrics[:foo/:bar].parent.slug.should == :foo
44
+ Modesty.metrics[:foo/:bar/:baz].parent.should_not == nil
45
+ Modesty.metrics[:foo/:bar/:baz].parent.slug.should == :foo/:bar
46
+ end
47
+ end
48
+
49
+ describe Modesty::Metric, "Tracking Metrics" do
50
+ before :each do
51
+ Modesty.set_store :redis, :mock => true
52
+ Modesty.data.flushdb
53
+ Modesty.metrics.clear
54
+ Modesty.new_metric :foo do |foo|
55
+ foo.description "Foo"
56
+
57
+ foo.submetric :bar do |bar|
58
+ bar.description "Bar"
59
+
60
+ bar.submetric :baz do |baz|
61
+ baz.description "Baz"
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ it "can track a metric" do
68
+ (1..100).each do |i|
69
+ lambda { Modesty.track! :foo }.should_not raise_error
70
+ Modesty.metrics[:foo].count.to_i.should == i
71
+ end
72
+ end
73
+
74
+ it "can track a metric with a count" do
75
+ (1..100).each do |i|
76
+ lambda { Modesty.track! :foo, 3 }.should_not raise_error
77
+ Modesty.metrics[:foo].count.to_i.should == i*3
78
+ end
79
+ end
80
+
81
+ it "can fetch a metric for a date" do
82
+ now = Time.now
83
+ Time.stub!(:now).and_return(now-1.day)
84
+ 25.times {|i| Modesty.track! :foo}
85
+ Modesty.metrics[:foo].count((now-1.day).to_date).should == 25
86
+ end
87
+
88
+ it "can fetch a metric over a date range" do
89
+ now = Time.now
90
+ Time.stub!(:now).and_return(now-1.day)
91
+ 25.times {|i| Modesty.track! :foo}
92
+ Time.stub!(:now).and_return(now)
93
+ 50.times {|i| Modesty.track! :foo}
94
+ Modesty.metrics[:foo].count((now-1.day).to_date..(now.to_date)).should == [25, 50]
95
+ end
96
+
97
+ it "can fetch a metric over a date range as array" do
98
+ now = Time.now
99
+ Time.stub!(:now).and_return(now-1.day)
100
+ 25.times {|i| Modesty.track! :foo}
101
+ Time.stub!(:now).and_return(now)
102
+ 50.times {|i| Modesty.track! :foo}
103
+ Modesty.metrics[:foo].count((now-1.day).to_date, now.to_date).should == [25, 50]
104
+ end
105
+
106
+ it "can track one submetric" do
107
+ (1..100).each do |i|
108
+ lambda { Modesty.track! :foo/:bar }.should_not raise_error
109
+ Modesty.metrics[:foo].count.to_i.should == i
110
+ Modesty.metrics[:foo/:bar].count.to_i.should == i
111
+ Modesty.metrics[:foo/:bar/:baz].count.to_i.should == 0
112
+ end
113
+ end
114
+
115
+ it "can track more than one submetric" do
116
+ (1..100).each do |i|
117
+ lambda { Modesty.track! :foo/:bar/:baz }.should_not raise_error
118
+ Modesty.metrics[:foo].count.to_i.should == i
119
+ Modesty.metrics[:foo/:bar].count.to_i.should == i
120
+ Modesty.metrics[:foo/:bar/:baz].count.to_i.should == i
121
+ end
122
+ end
123
+
124
+ describe "can track with custom data" do
125
+ before :each do
126
+ @m = Modesty.metrics[:foo/:bar]
127
+ lambda do
128
+ Modesty.track! :foo/:bar, :with => {:zing => 56, :user => 1}
129
+ end.should_not raise_error
130
+ @m.unique(:zings).should == 1
131
+ @m.all(:zings).should include 56
132
+
133
+ lambda do
134
+ Modesty.track! :foo/:bar, :with => {:zing => 97, :user => 2}, :count => 4
135
+ end.should_not raise_error
136
+ @m.unique(:zings).should == 2
137
+ @m.all(:zings).should include 97
138
+
139
+ lambda do
140
+ Modesty.track! :foo/:bar, 7, :with => {:zing => 97}
141
+ end.should_not raise_error
142
+ end
143
+
144
+ it "and count unique" do
145
+ @m.unique(:zings).should == 2
146
+ @m.unique(:zings, :all).should == 2
147
+ end
148
+
149
+ it "and bucket by dates" do
150
+ @m.unique(:zings, Date.parse('1/1/2002')).should == 0
151
+ end
152
+
153
+ it "and count all" do
154
+ @m.all(:zings).count.should == 2
155
+ end
156
+
157
+
158
+ it "and keep an aggregate by users" do
159
+ @m.aggregate.should == {1 => 1, 2 => 4}
160
+ end
161
+
162
+ it "and keep a distribution by users" do
163
+ @m.distribution.should == {1 => 1, 4 => 1}
164
+ @m.distribution(:all).should == {1 => 1, 4 => 1}
165
+ end
166
+
167
+ it "and keep an aggregate by custom data" do
168
+ @m.aggregate_by(:zings).should == {56 => 1, 97 => 11}
169
+ end
170
+
171
+ it "and keep a distribution by custom data" do
172
+ @m.distribution_by(:zings).should == {1 => 1, 11 => 1}
173
+ end
174
+
175
+ end
176
+ end
@@ -0,0 +1,48 @@
1
+ require 'modesty'
2
+
3
+ describe "bootstrap" do
4
+ before :all do
5
+ Modesty.data.flushdb
6
+ Modesty.metrics.clear
7
+ Modesty.experiments.clear
8
+
9
+ unless defined? Rails
10
+ class Rails
11
+ def self.root
12
+ File.join(
13
+ File.expand_path(File.dirname(__FILE__)),
14
+ '../test/myapp'
15
+ )
16
+ end
17
+
18
+ def self.configuration
19
+ self
20
+ end
21
+
22
+ def self.env
23
+ 'test'
24
+ end
25
+
26
+ def self.after_initialize
27
+ yield
28
+ end
29
+ end
30
+ end
31
+
32
+ require 'modesty/frameworks/rails'
33
+ end
34
+
35
+ it "bootstraps Redis" do
36
+ Modesty.data.store.should be_an_instance_of Redis
37
+ Modesty.data.store.client.port.should == 6379
38
+ Modesty.data.store.client.host.should == 'localhost'
39
+ end
40
+
41
+ it "loads metrics" do
42
+ Modesty.metrics.keys.should include :baked_goods
43
+ end
44
+
45
+ it "loads experiments" do
46
+ Modesty.experiments.keys.should include :cookbook
47
+ end
48
+ end