split 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -3
- data/CHANGELOG.mdown +25 -6
- data/Gemfile +1 -1
- data/README.mdown +137 -52
- data/lib/split.rb +1 -1
- data/lib/split/alternative.rb +54 -26
- data/lib/split/configuration.rb +94 -30
- data/lib/split/dashboard/public/style.css +10 -2
- data/lib/split/dashboard/views/_experiment.erb +31 -22
- data/lib/split/dashboard/views/_experiment_with_goal_header.erb +14 -0
- data/lib/split/dashboard/views/index.erb +8 -1
- data/lib/split/experiment.rb +166 -146
- data/lib/split/helper.rb +33 -23
- data/lib/split/metric.rb +13 -0
- data/lib/split/persistence/cookie_adapter.rb +10 -2
- data/lib/split/trial.rb +18 -12
- data/lib/split/version.rb +3 -3
- data/spec/alternative_spec.rb +121 -78
- data/spec/configuration_spec.rb +92 -4
- data/spec/dashboard_spec.rb +27 -11
- data/spec/experiment_spec.rb +110 -67
- data/spec/helper_spec.rb +287 -104
- data/spec/persistence/cookie_adapter_spec.rb +8 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/trial_spec.rb +10 -8
- data/split.gemspec +1 -1
- metadata +19 -18
data/spec/configuration_spec.rb
CHANGED
@@ -27,9 +27,25 @@ describe Split::Configuration do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
it "should provide a default pattern for robots" do
|
30
|
-
%w[Baidu Gigabot Googlebot libwww-perl lwp-trivial msnbot SiteUptime Slurp WordPress ZIBB ZyBorg].each do |robot|
|
30
|
+
%w[Baidu Gigabot Googlebot libwww-perl lwp-trivial msnbot SiteUptime Slurp WordPress ZIBB ZyBorg YandexBot AdsBot-Google Wget curl bitlybot facebookexternalhit spider].each do |robot|
|
31
31
|
@config.robot_regex.should =~ robot
|
32
32
|
end
|
33
|
+
|
34
|
+
@config.robot_regex.should =~ "EventMachine HttpClient"
|
35
|
+
@config.robot_regex.should =~ "libwww-perl/5.836"
|
36
|
+
@config.robot_regex.should =~ "Pingdom.com_bot_version_1.4_(http://www.pingdom.com)"
|
37
|
+
|
38
|
+
@config.robot_regex.should =~ " - "
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should accept real UAs with the robot regexp" do
|
42
|
+
@config.robot_regex.should_not =~ "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.4) Gecko/20091017 SeaMonkey/2.0"
|
43
|
+
@config.robot_regex.should_not =~ "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; F-6.0SP2-20041109; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 1.1.4322; InfoPath.3)"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should allow adding a bot to the bot list" do
|
47
|
+
@config.bots["newbot"] = "An amazing test bot"
|
48
|
+
@config.robot_regex.should =~ "newbot"
|
33
49
|
end
|
34
50
|
|
35
51
|
it "should use the session adapter for persistence by default" do
|
@@ -43,13 +59,85 @@ describe Split::Configuration do
|
|
43
59
|
@config.metrics.should_not be_nil
|
44
60
|
@config.metrics.keys.should == [:my_metric]
|
45
61
|
end
|
46
|
-
|
62
|
+
|
47
63
|
it "should allow loading of experiment using experment_for" do
|
48
64
|
@config.experiments = {:my_experiment=>
|
49
65
|
{:alternatives=>["control_opt", "other_opt"], :metric=>:my_metric}}
|
50
66
|
@config.experiment_for(:my_experiment).should == {:alternatives=>["control_opt", ["other_opt"]]}
|
51
67
|
end
|
52
|
-
|
68
|
+
|
69
|
+
context "when experiments are defined via YAML" do
|
70
|
+
context "as strings" do
|
71
|
+
context "in a basic configuration" do
|
72
|
+
before do
|
73
|
+
experiments_yaml = <<-eos
|
74
|
+
my_experiment:
|
75
|
+
alternatives:
|
76
|
+
- Control Opt
|
77
|
+
- Alt One
|
78
|
+
- Alt Two
|
79
|
+
resettable: false
|
80
|
+
eos
|
81
|
+
@config.experiments = YAML.load(experiments_yaml)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should normalize experiments' do
|
85
|
+
@config.normalized_experiments.should == {:my_experiment=>{:alternatives=>["Control Opt", ["Alt One", "Alt Two"]]}}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "in a complex configuration" do
|
90
|
+
before do
|
91
|
+
experiments_yaml = <<-eos
|
92
|
+
my_experiment:
|
93
|
+
alternatives:
|
94
|
+
- name: Control Opt
|
95
|
+
percent: 67
|
96
|
+
- name: Alt One
|
97
|
+
percent: 10
|
98
|
+
- name: Alt Two
|
99
|
+
percent: 23
|
100
|
+
resettable: false
|
101
|
+
metric: my_metric
|
102
|
+
another_experiment:
|
103
|
+
alternatives:
|
104
|
+
- a
|
105
|
+
- b
|
106
|
+
eos
|
107
|
+
@config.experiments = YAML.load(experiments_yaml)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should normalize experiments" do
|
111
|
+
@config.normalized_experiments.should == {:my_experiment=>{:alternatives=>[{"Control Opt"=>0.67},
|
112
|
+
[{"Alt One"=>0.1}, {"Alt Two"=>0.23}]]}, :another_experiment=>{:alternatives=>["a", ["b"]]}}
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should recognize metrics" do
|
116
|
+
@config.metrics.should_not be_nil
|
117
|
+
@config.metrics.keys.should == [:my_metric]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "as symbols" do
|
123
|
+
before do
|
124
|
+
experiments_yaml = <<-eos
|
125
|
+
:my_experiment:
|
126
|
+
:alternatives:
|
127
|
+
- Control Opt
|
128
|
+
- Alt One
|
129
|
+
- Alt Two
|
130
|
+
:resettable: false
|
131
|
+
eos
|
132
|
+
@config.experiments = YAML.load(experiments_yaml)
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should normalize experiments" do
|
136
|
+
@config.normalized_experiments.should == {:my_experiment=>{:alternatives=>["Control Opt", ["Alt One", "Alt Two"]]}}
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
53
141
|
it "should normalize experiments" do
|
54
142
|
@config.experiments = {
|
55
143
|
:my_experiment => {
|
@@ -60,7 +148,7 @@ describe Split::Configuration do
|
|
60
148
|
],
|
61
149
|
}
|
62
150
|
}
|
63
|
-
|
151
|
+
|
64
152
|
@config.normalized_experiments.should == {:my_experiment=>{:alternatives=>[{"control_opt"=>0.67}, [{"second_opt"=>0.1}, {"third_opt"=>0.23}]]}}
|
65
153
|
end
|
66
154
|
end
|
data/spec/dashboard_spec.rb
CHANGED
@@ -5,6 +5,22 @@ require 'split/dashboard'
|
|
5
5
|
describe Split::Dashboard do
|
6
6
|
include Rack::Test::Methods
|
7
7
|
|
8
|
+
let(:link_color) {
|
9
|
+
Split::Experiment.find_or_create('link_color', 'blue', 'red')
|
10
|
+
}
|
11
|
+
|
12
|
+
def link(color)
|
13
|
+
Split::Alternative.new(color, 'link_color')
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:red_link) {
|
17
|
+
link("red")
|
18
|
+
}
|
19
|
+
|
20
|
+
let(:blue_link) {
|
21
|
+
link("blue")
|
22
|
+
}
|
23
|
+
|
8
24
|
def app
|
9
25
|
@app ||= Split::Dashboard
|
10
26
|
end
|
@@ -15,33 +31,33 @@ describe Split::Dashboard do
|
|
15
31
|
end
|
16
32
|
|
17
33
|
it "should reset an experiment" do
|
18
|
-
experiment =
|
34
|
+
experiment = link_color
|
19
35
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
blue.participant_count = 6
|
36
|
+
red_link.participant_count = 5
|
37
|
+
blue_link.participant_count = 7
|
38
|
+
experiment.winner = 'blue'
|
24
39
|
|
25
40
|
post '/reset/link_color'
|
26
41
|
|
27
42
|
last_response.should be_redirect
|
28
43
|
|
29
|
-
new_red_count =
|
30
|
-
new_blue_count =
|
44
|
+
new_red_count = red_link.participant_count
|
45
|
+
new_blue_count = blue_link.participant_count
|
31
46
|
|
32
47
|
new_blue_count.should eql(0)
|
33
48
|
new_red_count.should eql(0)
|
49
|
+
experiment.winner.should be_nil
|
34
50
|
end
|
35
51
|
|
36
52
|
it "should delete an experiment" do
|
37
|
-
experiment =
|
53
|
+
experiment = link_color
|
38
54
|
delete '/link_color'
|
39
55
|
last_response.should be_redirect
|
40
56
|
Split::Experiment.find('link_color').should be_nil
|
41
57
|
end
|
42
58
|
|
43
59
|
it "should mark an alternative as the winner" do
|
44
|
-
experiment =
|
60
|
+
experiment = link_color
|
45
61
|
experiment.winner.should be_nil
|
46
62
|
|
47
63
|
post '/link_color', :alternative => 'red'
|
@@ -53,7 +69,7 @@ describe Split::Dashboard do
|
|
53
69
|
it "should display the start date" do
|
54
70
|
experiment_start_time = Time.parse('2011-07-07')
|
55
71
|
Time.stub(:now => experiment_start_time)
|
56
|
-
experiment =
|
72
|
+
experiment = link_color
|
57
73
|
|
58
74
|
get '/'
|
59
75
|
|
@@ -63,7 +79,7 @@ describe Split::Dashboard do
|
|
63
79
|
it "should handle experiments without a start date" do
|
64
80
|
experiment_start_time = Time.parse('2011-07-07')
|
65
81
|
Time.stub(:now => experiment_start_time)
|
66
|
-
experiment =
|
82
|
+
experiment = link_color
|
67
83
|
|
68
84
|
Split.redis.hdel(:experiment_start_times, experiment.name)
|
69
85
|
|
data/spec/experiment_spec.rb
CHANGED
@@ -4,9 +4,24 @@ require 'split/algorithms'
|
|
4
4
|
require 'time'
|
5
5
|
|
6
6
|
describe Split::Experiment do
|
7
|
+
def new_experiment(goals=[])
|
8
|
+
Split::Experiment.new('link_color', :alternatives => ['blue', 'red', 'green'], :goals => goals)
|
9
|
+
end
|
10
|
+
|
11
|
+
def alternative(color)
|
12
|
+
Split::Alternative.new(color, 'link_color')
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:experiment) {
|
16
|
+
new_experiment
|
17
|
+
}
|
18
|
+
|
19
|
+
let(:blue) { alternative("blue") }
|
20
|
+
let(:green) { alternative("green") }
|
21
|
+
|
7
22
|
context "with an experiment" do
|
8
|
-
let(:experiment) { Split::Experiment.new('basket_text', :
|
9
|
-
|
23
|
+
let(:experiment) { Split::Experiment.new('basket_text', :alternatives => ['Basket', "Cart"]) }
|
24
|
+
|
10
25
|
it "should have a name" do
|
11
26
|
experiment.name.should eql('basket_text')
|
12
27
|
end
|
@@ -14,15 +29,15 @@ describe Split::Experiment do
|
|
14
29
|
it "should have alternatives" do
|
15
30
|
experiment.alternatives.length.should be 2
|
16
31
|
end
|
17
|
-
|
32
|
+
|
18
33
|
it "should have alternatives with correct names" do
|
19
34
|
experiment.alternatives.collect{|a| a.name}.should == ['Basket', 'Cart']
|
20
35
|
end
|
21
|
-
|
36
|
+
|
22
37
|
it "should be resettable by default" do
|
23
38
|
experiment.resettable.should be_true
|
24
39
|
end
|
25
|
-
|
40
|
+
|
26
41
|
it "should save to redis" do
|
27
42
|
experiment.save
|
28
43
|
Split.redis.exists('basket_text').should be true
|
@@ -35,10 +50,10 @@ describe Split::Experiment do
|
|
35
50
|
|
36
51
|
Split::Experiment.find('basket_text').start_time.should == experiment_start_time
|
37
52
|
end
|
38
|
-
|
53
|
+
|
39
54
|
it "should save the selected algorithm to redis" do
|
40
55
|
experiment_algorithm = Split::Algorithms::Whiplash
|
41
|
-
experiment.algorithm = experiment_algorithm
|
56
|
+
experiment.algorithm = experiment_algorithm
|
42
57
|
experiment.save
|
43
58
|
|
44
59
|
Split::Experiment.find('basket_text').algorithm.should == experiment_algorithm
|
@@ -60,7 +75,7 @@ describe Split::Experiment do
|
|
60
75
|
Split.redis.exists('basket_text').should be true
|
61
76
|
Split.redis.lrange('basket_text', 0, -1).should eql(['Basket', "Cart"])
|
62
77
|
end
|
63
|
-
|
78
|
+
|
64
79
|
describe 'new record?' do
|
65
80
|
it "should know if it hasn't been saved yet" do
|
66
81
|
experiment.new_record?.should be_true
|
@@ -71,18 +86,19 @@ describe Split::Experiment do
|
|
71
86
|
experiment.new_record?.should be_false
|
72
87
|
end
|
73
88
|
end
|
74
|
-
|
89
|
+
|
75
90
|
describe 'find' do
|
76
91
|
it "should return an existing experiment" do
|
77
92
|
experiment.save
|
78
|
-
Split::Experiment.find('basket_text')
|
93
|
+
experiment = Split::Experiment.find('basket_text')
|
94
|
+
experiment.name.should eql('basket_text')
|
79
95
|
end
|
80
96
|
|
81
97
|
it "should return an existing experiment" do
|
82
98
|
Split::Experiment.find('non_existent_experiment').should be_nil
|
83
99
|
end
|
84
100
|
end
|
85
|
-
|
101
|
+
|
86
102
|
describe 'control' do
|
87
103
|
it 'should be the first alternative' do
|
88
104
|
experiment.save
|
@@ -90,80 +106,74 @@ describe Split::Experiment do
|
|
90
106
|
end
|
91
107
|
end
|
92
108
|
end
|
109
|
+
|
93
110
|
describe 'initialization' do
|
94
111
|
it "should set the algorithm when passed as an option to the initializer" do
|
95
|
-
experiment = Split::Experiment.new('basket_text', :
|
112
|
+
experiment = Split::Experiment.new('basket_text', :alternatives => ['Basket', "Cart"], :algorithm => Split::Algorithms::Whiplash)
|
96
113
|
experiment.algorithm.should == Split::Algorithms::Whiplash
|
97
114
|
end
|
98
|
-
|
115
|
+
|
99
116
|
it "should be possible to make an experiment not resettable" do
|
100
|
-
experiment = Split::Experiment.new('basket_text', :
|
101
|
-
experiment.resettable.should be_false
|
117
|
+
experiment = Split::Experiment.new('basket_text', :alternatives => ['Basket', "Cart"], :resettable => false)
|
118
|
+
experiment.resettable.should be_false
|
102
119
|
end
|
103
120
|
end
|
104
|
-
|
121
|
+
|
105
122
|
describe 'persistent configuration' do
|
106
|
-
|
123
|
+
|
107
124
|
it "should persist resettable in redis" do
|
108
|
-
experiment = Split::Experiment.new('basket_text', :
|
125
|
+
experiment = Split::Experiment.new('basket_text', :alternatives => ['Basket', "Cart"], :resettable => false)
|
109
126
|
experiment.save
|
110
|
-
|
127
|
+
|
111
128
|
e = Split::Experiment.find('basket_text')
|
112
129
|
e.should == experiment
|
113
130
|
e.resettable.should be_false
|
114
|
-
|
131
|
+
|
115
132
|
end
|
116
|
-
|
133
|
+
|
117
134
|
it "should persist algorithm in redis" do
|
118
|
-
experiment = Split::Experiment.new('basket_text', :
|
135
|
+
experiment = Split::Experiment.new('basket_text', :alternatives => ['Basket', "Cart"], :algorithm => Split::Algorithms::Whiplash)
|
119
136
|
experiment.save
|
120
|
-
|
137
|
+
|
121
138
|
e = Split::Experiment.find('basket_text')
|
122
139
|
e.should == experiment
|
123
140
|
e.algorithm.should == Split::Algorithms::Whiplash
|
124
141
|
end
|
125
142
|
end
|
126
143
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
144
|
describe 'deleting' do
|
131
145
|
it 'should delete itself' do
|
132
|
-
experiment = Split::Experiment.new('basket_text', :
|
146
|
+
experiment = Split::Experiment.new('basket_text', :alternatives => [ 'Basket', "Cart"])
|
133
147
|
experiment.save
|
134
148
|
|
135
149
|
experiment.delete
|
136
|
-
Split.redis.exists('
|
137
|
-
Split::Experiment.find('
|
150
|
+
Split.redis.exists('link_color').should be false
|
151
|
+
Split::Experiment.find('link_color').should be_nil
|
138
152
|
end
|
139
153
|
|
140
154
|
it "should increment the version" do
|
141
|
-
experiment = Split::Experiment.find_or_create('link_color', 'blue', 'red', 'green')
|
142
155
|
experiment.version.should eql(0)
|
143
156
|
experiment.delete
|
144
157
|
experiment.version.should eql(1)
|
145
158
|
end
|
146
159
|
end
|
147
160
|
|
161
|
+
|
148
162
|
describe 'winner' do
|
149
163
|
it "should have no winner initially" do
|
150
|
-
experiment = Split::Experiment.find_or_create('link_color', 'blue', 'red')
|
151
164
|
experiment.winner.should be_nil
|
152
165
|
end
|
153
166
|
|
154
167
|
it "should allow you to specify a winner" do
|
155
|
-
experiment
|
168
|
+
experiment.save
|
156
169
|
experiment.winner = 'red'
|
157
|
-
|
158
|
-
experiment = Split::Experiment.find_or_create('link_color', 'blue', 'red')
|
159
170
|
experiment.winner.name.should == 'red'
|
160
171
|
end
|
161
172
|
end
|
162
173
|
|
163
174
|
describe 'reset' do
|
175
|
+
before { experiment.save }
|
164
176
|
it 'should reset all alternatives' do
|
165
|
-
experiment = Split::Experiment.find_or_create('link_color', 'blue', 'red', 'green')
|
166
|
-
green = Split::Alternative.new('green', 'link_color')
|
167
177
|
experiment.winner = 'green'
|
168
178
|
|
169
179
|
experiment.next_alternative.name.should eql('green')
|
@@ -171,14 +181,11 @@ describe Split::Experiment do
|
|
171
181
|
|
172
182
|
experiment.reset
|
173
183
|
|
174
|
-
|
175
|
-
|
176
|
-
reset_green.completed_count.should eql(0)
|
184
|
+
green.participant_count.should eql(0)
|
185
|
+
green.completed_count.should eql(0)
|
177
186
|
end
|
178
187
|
|
179
188
|
it 'should reset the winner' do
|
180
|
-
experiment = Split::Experiment.find_or_create('link_color', 'blue', 'red', 'green')
|
181
|
-
green = Split::Alternative.new('green', 'link_color')
|
182
189
|
experiment.winner = 'green'
|
183
190
|
|
184
191
|
experiment.next_alternative.name.should eql('green')
|
@@ -190,29 +197,28 @@ describe Split::Experiment do
|
|
190
197
|
end
|
191
198
|
|
192
199
|
it "should increment the version" do
|
193
|
-
experiment = Split::Experiment.find_or_create('link_color', 'blue', 'red', 'green')
|
194
200
|
experiment.version.should eql(0)
|
195
201
|
experiment.reset
|
196
202
|
experiment.version.should eql(1)
|
197
203
|
end
|
198
204
|
end
|
199
|
-
|
205
|
+
|
200
206
|
describe 'algorithm' do
|
201
207
|
let(:experiment) { Split::Experiment.find_or_create('link_color', 'blue', 'red', 'green') }
|
202
|
-
|
208
|
+
|
203
209
|
it 'should use the default algorithm if none is specified' do
|
204
210
|
experiment.algorithm.should == Split.configuration.algorithm
|
205
211
|
end
|
206
|
-
|
212
|
+
|
207
213
|
it 'should use the user specified algorithm for this experiment if specified' do
|
208
214
|
experiment.algorithm = Split::Algorithms::Whiplash
|
209
215
|
experiment.algorithm.should == Split::Algorithms::Whiplash
|
210
216
|
end
|
211
217
|
end
|
212
|
-
|
218
|
+
|
213
219
|
describe 'next_alternative' do
|
214
220
|
let(:experiment) { Split::Experiment.find_or_create('link_color', 'blue', 'red', 'green') }
|
215
|
-
|
221
|
+
|
216
222
|
it "should always return the winner if one exists" do
|
217
223
|
green = Split::Alternative.new('green', 'link_color')
|
218
224
|
experiment.winner = 'green'
|
@@ -220,42 +226,42 @@ describe Split::Experiment do
|
|
220
226
|
experiment.next_alternative.name.should eql('green')
|
221
227
|
green.increment_participation
|
222
228
|
|
223
|
-
experiment = Split::Experiment.find_or_create('link_color', 'blue', 'red', 'green')
|
224
229
|
experiment.next_alternative.name.should eql('green')
|
225
230
|
end
|
226
|
-
|
231
|
+
|
227
232
|
it "should use the specified algorithm if a winner does not exist" do
|
228
233
|
Split.configuration.algorithm.should_receive(:choose_alternative).and_return(Split::Alternative.new('green', 'link_color'))
|
229
234
|
experiment.next_alternative.name.should eql('green')
|
230
235
|
end
|
231
236
|
end
|
232
|
-
|
237
|
+
|
233
238
|
describe 'single alternative' do
|
234
239
|
let(:experiment) { Split::Experiment.find_or_create('link_color', 'blue') }
|
235
|
-
|
240
|
+
|
236
241
|
it "should always return the color blue" do
|
237
242
|
experiment.next_alternative.name.should eql('blue')
|
238
|
-
end
|
243
|
+
end
|
239
244
|
end
|
240
245
|
|
241
246
|
describe 'changing an existing experiment' do
|
247
|
+
def same_but_different_alternative
|
248
|
+
Split::Experiment.find_or_create('link_color', 'blue', 'yellow', 'orange')
|
249
|
+
end
|
250
|
+
|
242
251
|
it "should reset an experiment if it is loaded with different alternatives" do
|
243
|
-
experiment
|
244
|
-
blue = Split::Alternative.new('blue', 'link_color')
|
252
|
+
experiment.save
|
245
253
|
blue.participant_count = 5
|
246
|
-
|
247
|
-
same_experiment = Split::Experiment.find_or_create('link_color', 'blue', 'yellow', 'orange')
|
254
|
+
same_experiment = same_but_different_alternative
|
248
255
|
same_experiment.alternatives.map(&:name).should eql(['blue', 'yellow', 'orange'])
|
249
|
-
|
250
|
-
new_blue.participant_count.should eql(0)
|
256
|
+
blue.participant_count.should eql(0)
|
251
257
|
end
|
252
258
|
|
253
259
|
it "should only reset once" do
|
254
|
-
experiment
|
260
|
+
experiment.save
|
255
261
|
experiment.version.should eql(0)
|
256
|
-
same_experiment =
|
262
|
+
same_experiment = same_but_different_alternative
|
257
263
|
same_experiment.version.should eql(1)
|
258
|
-
same_experiment_again =
|
264
|
+
same_experiment_again = same_but_different_alternative
|
259
265
|
same_experiment_again.version.should eql(1)
|
260
266
|
end
|
261
267
|
end
|
@@ -268,18 +274,55 @@ describe Split::Experiment do
|
|
268
274
|
end
|
269
275
|
|
270
276
|
describe 'specifying weights' do
|
271
|
-
|
272
|
-
|
277
|
+
let(:experiment_with_weight) {
|
278
|
+
Split::Experiment.find_or_create('link_color', {'blue' => 1}, {'red' => 2 })
|
279
|
+
}
|
273
280
|
|
274
|
-
|
281
|
+
it "should work for a new experiment" do
|
282
|
+
experiment_with_weight.alternatives.map(&:weight).should == [1, 2]
|
275
283
|
end
|
276
284
|
|
277
285
|
it "should work for an existing experiment" do
|
278
|
-
experiment = Split::Experiment.find_or_create('link_color', 'blue', 'red')
|
279
286
|
experiment.save
|
287
|
+
experiment_with_weight.alternatives.map(&:weight).should == [1, 2]
|
288
|
+
end
|
289
|
+
end
|
280
290
|
|
281
|
-
|
282
|
-
|
291
|
+
describe "specifying goals" do
|
292
|
+
let(:experiment) {
|
293
|
+
new_experiment(["purchase"])
|
294
|
+
}
|
295
|
+
|
296
|
+
context "saving experiment" do
|
297
|
+
def same_but_different_goals
|
298
|
+
Split::Experiment.find_or_create({'link_color' => ["purchase", "refund"]}, 'blue', 'red', 'green')
|
299
|
+
end
|
300
|
+
|
301
|
+
before { experiment.save }
|
302
|
+
|
303
|
+
it "can find existing experiment" do
|
304
|
+
Split::Experiment.find("link_color").name.should eql("link_color")
|
305
|
+
end
|
306
|
+
|
307
|
+
it "should reset an experiment if it is loaded with different goals" do
|
308
|
+
same_experiment = same_but_different_goals
|
309
|
+
Split::Experiment.find("link_color").goals.should == ["purchase", "refund"]
|
310
|
+
end
|
311
|
+
|
312
|
+
end
|
313
|
+
|
314
|
+
it "should have goals" do
|
315
|
+
experiment.goals.should eql(["purchase"])
|
316
|
+
end
|
317
|
+
|
318
|
+
context "find or create experiment" do
|
319
|
+
it "should have correct goals" do
|
320
|
+
experiment = Split::Experiment.find_or_create({'link_color3' => ["purchase", "refund"]}, 'blue', 'red', 'green')
|
321
|
+
experiment.goals.should == ["purchase", "refund"]
|
322
|
+
experiment = Split::Experiment.find_or_create('link_color3', 'blue', 'red', 'green')
|
323
|
+
experiment.goals.should == []
|
324
|
+
end
|
283
325
|
end
|
284
326
|
end
|
327
|
+
|
285
328
|
end
|