split 0.5.0 → 0.6.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.
- 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
|