split 4.0.1 → 4.0.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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +6 -3
- data/.rubocop.yml +2 -5
- data/CHANGELOG.md +23 -0
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +2 -1
- data/README.md +4 -2
- data/Rakefile +4 -5
- data/gemfiles/5.2.gemfile +1 -3
- data/gemfiles/6.0.gemfile +1 -3
- data/gemfiles/6.1.gemfile +1 -3
- data/gemfiles/7.0.gemfile +2 -3
- data/lib/split/algorithms/block_randomization.rb +5 -6
- data/lib/split/algorithms/whiplash.rb +16 -18
- data/lib/split/algorithms.rb +22 -0
- data/lib/split/alternative.rb +21 -22
- data/lib/split/cache.rb +0 -1
- data/lib/split/combined_experiments_helper.rb +4 -4
- data/lib/split/configuration.rb +83 -84
- data/lib/split/dashboard/helpers.rb +6 -7
- data/lib/split/dashboard/pagination_helpers.rb +53 -54
- data/lib/split/dashboard/public/style.css +5 -2
- data/lib/split/dashboard/views/index.erb +19 -4
- data/lib/split/dashboard.rb +29 -23
- data/lib/split/encapsulated_helper.rb +4 -6
- data/lib/split/experiment.rb +84 -88
- data/lib/split/experiment_catalog.rb +6 -5
- data/lib/split/extensions/string.rb +1 -1
- data/lib/split/goals_collection.rb +8 -10
- data/lib/split/helper.rb +19 -19
- data/lib/split/metric.rb +4 -5
- data/lib/split/persistence/cookie_adapter.rb +44 -47
- data/lib/split/persistence/dual_adapter.rb +7 -8
- data/lib/split/persistence/redis_adapter.rb +2 -3
- data/lib/split/persistence/session_adapter.rb +0 -2
- data/lib/split/persistence.rb +4 -4
- data/lib/split/redis_interface.rb +1 -2
- data/lib/split/trial.rb +23 -24
- data/lib/split/user.rb +12 -13
- data/lib/split/version.rb +1 -1
- data/lib/split/zscore.rb +1 -3
- data/lib/split.rb +26 -25
- data/spec/algorithms/block_randomization_spec.rb +6 -5
- data/spec/algorithms/weighted_sample_spec.rb +6 -5
- data/spec/algorithms/whiplash_spec.rb +4 -5
- data/spec/alternative_spec.rb +35 -36
- data/spec/cache_spec.rb +15 -19
- data/spec/combined_experiments_helper_spec.rb +18 -17
- data/spec/configuration_spec.rb +32 -38
- data/spec/dashboard/pagination_helpers_spec.rb +69 -67
- data/spec/dashboard/paginator_spec.rb +10 -9
- data/spec/dashboard_helpers_spec.rb +19 -18
- data/spec/dashboard_spec.rb +67 -35
- data/spec/encapsulated_helper_spec.rb +12 -14
- data/spec/experiment_catalog_spec.rb +14 -13
- data/spec/experiment_spec.rb +121 -123
- data/spec/goals_collection_spec.rb +17 -15
- data/spec/helper_spec.rb +379 -382
- data/spec/metric_spec.rb +14 -14
- data/spec/persistence/cookie_adapter_spec.rb +23 -8
- data/spec/persistence/dual_adapter_spec.rb +71 -71
- data/spec/persistence/redis_adapter_spec.rb +25 -26
- data/spec/persistence/session_adapter_spec.rb +2 -3
- data/spec/persistence_spec.rb +1 -2
- data/spec/redis_interface_spec.rb +16 -14
- data/spec/spec_helper.rb +15 -13
- data/spec/split_spec.rb +11 -11
- data/spec/support/cookies_mock.rb +1 -2
- data/spec/trial_spec.rb +61 -60
- data/spec/user_spec.rb +36 -36
- data/split.gemspec +20 -20
- metadata +7 -10
- data/.rubocop_todo.yml +0 -226
- data/Appraisals +0 -19
- data/gemfiles/5.0.gemfile +0 -9
- data/gemfiles/5.1.gemfile +0 -9
data/spec/helper_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
require "spec_helper"
|
3
4
|
|
4
5
|
# TODO change some of these tests to use Rack::Test
|
5
6
|
|
@@ -7,156 +8,156 @@ describe Split::Helper do
|
|
7
8
|
include Split::Helper
|
8
9
|
|
9
10
|
let(:experiment) {
|
10
|
-
Split::ExperimentCatalog.find_or_create(
|
11
|
+
Split::ExperimentCatalog.find_or_create("link_color", "blue", "red")
|
11
12
|
}
|
12
13
|
|
13
14
|
describe "ab_test" do
|
14
15
|
it "should not raise an error when passed strings for alternatives" do
|
15
|
-
expect
|
16
|
+
expect { ab_test("xyz", "1", "2", "3") }.not_to raise_error
|
16
17
|
end
|
17
18
|
|
18
19
|
it "should not raise an error when passed an array for alternatives" do
|
19
|
-
expect
|
20
|
+
expect { ab_test("xyz", ["1", "2", "3"]) }.not_to raise_error
|
20
21
|
end
|
21
22
|
|
22
23
|
it "should raise the appropriate error when passed integers for alternatives" do
|
23
|
-
expect
|
24
|
+
expect { ab_test("xyz", 1, 2, 3) }.to raise_error(ArgumentError)
|
24
25
|
end
|
25
26
|
|
26
27
|
it "should raise the appropriate error when passed symbols for alternatives" do
|
27
|
-
expect
|
28
|
+
expect { ab_test("xyz", :a, :b, :c) }.to raise_error(ArgumentError)
|
28
29
|
end
|
29
30
|
|
30
31
|
it "should not raise error when passed an array for goals" do
|
31
|
-
expect
|
32
|
+
expect { ab_test({ "link_color" => ["purchase", "refund"] }, "blue", "red") }.not_to raise_error
|
32
33
|
end
|
33
34
|
|
34
35
|
it "should not raise error when passed just one goal" do
|
35
|
-
expect
|
36
|
+
expect { ab_test({ "link_color" => "purchase" }, "blue", "red") }.not_to raise_error
|
36
37
|
end
|
37
38
|
|
38
39
|
it "raises an appropriate error when processing combined expirements" do
|
39
40
|
Split.configuration.experiments = {
|
40
|
-
:
|
41
|
-
:
|
42
|
-
:
|
43
|
-
:
|
41
|
+
combined_exp_1: {
|
42
|
+
alternatives: [ { name: "control", percent: 50 }, { name: "test-alt", percent: 50 } ],
|
43
|
+
metric: :my_metric,
|
44
|
+
combined_experiments: [:combined_exp_1_sub_1]
|
44
45
|
}
|
45
46
|
}
|
46
|
-
Split::ExperimentCatalog.find_or_create(
|
47
|
-
expect
|
47
|
+
Split::ExperimentCatalog.find_or_create("combined_exp_1")
|
48
|
+
expect { ab_test("combined_exp_1") }.to raise_error(Split::InvalidExperimentsFormatError)
|
48
49
|
end
|
49
50
|
|
50
51
|
it "should assign a random alternative to a new user when there are an equal number of alternatives assigned" do
|
51
|
-
ab_test(
|
52
|
-
expect([
|
52
|
+
ab_test("link_color", "blue", "red")
|
53
|
+
expect(["red", "blue"]).to include(ab_user["link_color"])
|
53
54
|
end
|
54
55
|
|
55
56
|
it "should increment the participation counter after assignment to a new user" do
|
56
|
-
previous_red_count = Split::Alternative.new(
|
57
|
-
previous_blue_count = Split::Alternative.new(
|
57
|
+
previous_red_count = Split::Alternative.new("red", "link_color").participant_count
|
58
|
+
previous_blue_count = Split::Alternative.new("blue", "link_color").participant_count
|
58
59
|
|
59
|
-
ab_test(
|
60
|
+
ab_test("link_color", "blue", "red")
|
60
61
|
|
61
|
-
new_red_count = Split::Alternative.new(
|
62
|
-
new_blue_count = Split::Alternative.new(
|
62
|
+
new_red_count = Split::Alternative.new("red", "link_color").participant_count
|
63
|
+
new_blue_count = Split::Alternative.new("blue", "link_color").participant_count
|
63
64
|
|
64
65
|
expect((new_red_count + new_blue_count)).to eq(previous_red_count + previous_blue_count + 1)
|
65
66
|
end
|
66
67
|
|
67
|
-
it
|
68
|
-
ab_test(
|
69
|
-
e = Split::ExperimentCatalog.find_or_create(
|
70
|
-
expect
|
68
|
+
it "should not increment the counter for an experiment that the user is not participating in" do
|
69
|
+
ab_test("link_color", "blue", "red")
|
70
|
+
e = Split::ExperimentCatalog.find_or_create("button_size", "small", "big")
|
71
|
+
expect {
|
71
72
|
# User shouldn't participate in this second experiment
|
72
|
-
ab_test(
|
73
|
-
}
|
73
|
+
ab_test("button_size", "small", "big")
|
74
|
+
}.not_to change { e.participant_count }
|
74
75
|
end
|
75
76
|
|
76
|
-
it
|
77
|
-
e = Split::ExperimentCatalog.find_or_create(
|
78
|
-
e.winner =
|
79
|
-
expect
|
80
|
-
a = ab_test(
|
81
|
-
expect(a).to eq(
|
82
|
-
}
|
77
|
+
it "should not increment the counter for an ended experiment" do
|
78
|
+
e = Split::ExperimentCatalog.find_or_create("button_size", "small", "big")
|
79
|
+
e.winner = "small"
|
80
|
+
expect {
|
81
|
+
a = ab_test("button_size", "small", "big")
|
82
|
+
expect(a).to eq("small")
|
83
|
+
}.not_to change { e.participant_count }
|
83
84
|
end
|
84
85
|
|
85
|
-
it
|
86
|
+
it "should not increment the counter for an not started experiment" do
|
86
87
|
expect(Split.configuration).to receive(:start_manually).and_return(true)
|
87
|
-
e = Split::ExperimentCatalog.find_or_create(
|
88
|
-
expect
|
89
|
-
a = ab_test(
|
90
|
-
expect(a).to eq(
|
91
|
-
}
|
88
|
+
e = Split::ExperimentCatalog.find_or_create("button_size", "small", "big")
|
89
|
+
expect {
|
90
|
+
a = ab_test("button_size", "small", "big")
|
91
|
+
expect(a).to eq("small")
|
92
|
+
}.not_to change { e.participant_count }
|
92
93
|
end
|
93
94
|
|
94
95
|
it "should return the given alternative for an existing user" do
|
95
|
-
expect(ab_test(
|
96
|
+
expect(ab_test("link_color", "blue", "red")).to eq ab_test("link_color", "blue", "red")
|
96
97
|
end
|
97
98
|
|
98
|
-
it
|
99
|
+
it "should always return the winner if one is present" do
|
99
100
|
experiment.winner = "orange"
|
100
101
|
|
101
|
-
expect(ab_test(
|
102
|
+
expect(ab_test("link_color", "blue", "red")).to eq("orange")
|
102
103
|
end
|
103
104
|
|
104
105
|
it "should allow the alternative to be forced by passing it in the params" do
|
105
106
|
# ?ab_test[link_color]=blue
|
106
|
-
@params = {
|
107
|
+
@params = { "ab_test" => { "link_color" => "blue" } }
|
107
108
|
|
108
|
-
alternative = ab_test(
|
109
|
-
expect(alternative).to eq(
|
109
|
+
alternative = ab_test("link_color", "blue", "red")
|
110
|
+
expect(alternative).to eq("blue")
|
110
111
|
|
111
|
-
alternative = ab_test(
|
112
|
-
expect(alternative).to eq(
|
112
|
+
alternative = ab_test("link_color", { "blue" => 1 }, "red" => 5)
|
113
|
+
expect(alternative).to eq("blue")
|
113
114
|
|
114
|
-
@params = {
|
115
|
+
@params = { "ab_test" => { "link_color" => "red" } }
|
115
116
|
|
116
|
-
alternative = ab_test(
|
117
|
-
expect(alternative).to eq(
|
117
|
+
alternative = ab_test("link_color", "blue", "red")
|
118
|
+
expect(alternative).to eq("red")
|
118
119
|
|
119
|
-
alternative = ab_test(
|
120
|
-
expect(alternative).to eq(
|
120
|
+
alternative = ab_test("link_color", { "blue" => 5 }, "red" => 1)
|
121
|
+
expect(alternative).to eq("red")
|
121
122
|
end
|
122
123
|
|
123
124
|
it "should not allow an arbitrary alternative" do
|
124
|
-
@params = {
|
125
|
-
alternative = ab_test(
|
126
|
-
expect(alternative).to eq(
|
125
|
+
@params = { "ab_test" => { "link_color" => "pink" } }
|
126
|
+
alternative = ab_test("link_color", "blue")
|
127
|
+
expect(alternative).to eq("blue")
|
127
128
|
end
|
128
129
|
|
129
130
|
it "should not store the split when a param forced alternative" do
|
130
|
-
@params = {
|
131
|
+
@params = { "ab_test" => { "link_color" => "blue" } }
|
131
132
|
expect(ab_user).not_to receive(:[]=)
|
132
|
-
ab_test(
|
133
|
+
ab_test("link_color", "blue", "red")
|
133
134
|
end
|
134
135
|
|
135
136
|
it "SPLIT_DISABLE query parameter should also force the alternative (uses control)" do
|
136
|
-
@params = {
|
137
|
-
alternative = ab_test(
|
138
|
-
expect(alternative).to eq(
|
139
|
-
alternative = ab_test(
|
140
|
-
expect(alternative).to eq(
|
141
|
-
alternative = ab_test(
|
142
|
-
expect(alternative).to eq(
|
143
|
-
alternative = ab_test(
|
144
|
-
expect(alternative).to eq(
|
137
|
+
@params = { "SPLIT_DISABLE" => "true" }
|
138
|
+
alternative = ab_test("link_color", "blue", "red")
|
139
|
+
expect(alternative).to eq("blue")
|
140
|
+
alternative = ab_test("link_color", { "blue" => 1 }, "red" => 5)
|
141
|
+
expect(alternative).to eq("blue")
|
142
|
+
alternative = ab_test("link_color", "red", "blue")
|
143
|
+
expect(alternative).to eq("red")
|
144
|
+
alternative = ab_test("link_color", { "red" => 5 }, "blue" => 1)
|
145
|
+
expect(alternative).to eq("red")
|
145
146
|
end
|
146
147
|
|
147
148
|
it "should not store the split when Split generically disabled" do
|
148
|
-
@params = {
|
149
|
+
@params = { "SPLIT_DISABLE" => "true" }
|
149
150
|
expect(ab_user).not_to receive(:[]=)
|
150
|
-
ab_test(
|
151
|
+
ab_test("link_color", "blue", "red")
|
151
152
|
end
|
152
153
|
|
153
154
|
context "when store_override is set" do
|
154
155
|
before { Split.configuration.store_override = true }
|
155
156
|
|
156
157
|
it "should store the forced alternative" do
|
157
|
-
@params = {
|
158
|
-
expect(ab_user).to receive(:[]=).with(
|
159
|
-
ab_test(
|
158
|
+
@params = { "ab_test" => { "link_color" => "blue" } }
|
159
|
+
expect(ab_user).to receive(:[]=).with("link_color", "blue")
|
160
|
+
ab_test("link_color", "blue", "red")
|
160
161
|
end
|
161
162
|
end
|
162
163
|
|
@@ -164,35 +165,35 @@ describe Split::Helper do
|
|
164
165
|
before { Split.configuration.on_trial_choose = :some_method }
|
165
166
|
it "should call the method" do
|
166
167
|
expect(self).to receive(:some_method)
|
167
|
-
ab_test(
|
168
|
+
ab_test("link_color", "blue", "red")
|
168
169
|
end
|
169
170
|
end
|
170
171
|
|
171
172
|
it "should allow passing a block" do
|
172
|
-
alt = ab_test(
|
173
|
-
ret = ab_test(
|
173
|
+
alt = ab_test("link_color", "blue", "red")
|
174
|
+
ret = ab_test("link_color", "blue", "red") { |alternative| "shared/#{alternative}" }
|
174
175
|
expect(ret).to eq("shared/#{alt}")
|
175
176
|
end
|
176
177
|
|
177
178
|
it "should allow the share of visitors see an alternative to be specified" do
|
178
|
-
ab_test(
|
179
|
-
expect([
|
179
|
+
ab_test("link_color", { "blue" => 0.8 }, { "red" => 20 })
|
180
|
+
expect(["red", "blue"]).to include(ab_user["link_color"])
|
180
181
|
end
|
181
182
|
|
182
183
|
it "should allow alternative weighting interface as a single hash" do
|
183
|
-
ab_test(
|
184
|
-
experiment = Split::ExperimentCatalog.find(
|
185
|
-
expect(experiment.alternatives.map(&:name)).to eq([
|
186
|
-
expect(experiment.alternatives.collect{|a| a.weight}).to match_array([0.01, 0.2])
|
184
|
+
ab_test("link_color", { "blue" => 0.01 }, "red" => 0.2)
|
185
|
+
experiment = Split::ExperimentCatalog.find("link_color")
|
186
|
+
expect(experiment.alternatives.map(&:name)).to eq(["blue", "red"])
|
187
|
+
expect(experiment.alternatives.collect { |a| a.weight }).to match_array([0.01, 0.2])
|
187
188
|
end
|
188
189
|
|
189
190
|
it "should only let a user participate in one experiment at a time" do
|
190
|
-
link_color = ab_test(
|
191
|
-
ab_test(
|
192
|
-
expect(ab_user[
|
193
|
-
big = Split::Alternative.new(
|
191
|
+
link_color = ab_test("link_color", "blue", "red")
|
192
|
+
ab_test("button_size", "small", "big")
|
193
|
+
expect(ab_user["link_color"]).to eq(link_color)
|
194
|
+
big = Split::Alternative.new("big", "button_size")
|
194
195
|
expect(big.participant_count).to eq(0)
|
195
|
-
small = Split::Alternative.new(
|
196
|
+
small = Split::Alternative.new("small", "button_size")
|
196
197
|
expect(small.participant_count).to eq(0)
|
197
198
|
end
|
198
199
|
|
@@ -200,179 +201,177 @@ describe Split::Helper do
|
|
200
201
|
Split.configure do |config|
|
201
202
|
config.allow_multiple_experiments = true
|
202
203
|
end
|
203
|
-
link_color = ab_test(
|
204
|
-
button_size = ab_test(
|
205
|
-
expect(ab_user[
|
206
|
-
expect(ab_user[
|
207
|
-
button_size_alt = Split::Alternative.new(button_size,
|
204
|
+
link_color = ab_test("link_color", "blue", "red")
|
205
|
+
button_size = ab_test("button_size", "small", "big")
|
206
|
+
expect(ab_user["link_color"]).to eq(link_color)
|
207
|
+
expect(ab_user["button_size"]).to eq(button_size)
|
208
|
+
button_size_alt = Split::Alternative.new(button_size, "button_size")
|
208
209
|
expect(button_size_alt.participant_count).to eq(1)
|
209
210
|
end
|
210
211
|
|
211
212
|
context "with allow_multiple_experiments = 'control'" do
|
212
213
|
it "should let a user participate in many experiment with one non-'control' alternative" do
|
213
214
|
Split.configure do |config|
|
214
|
-
config.allow_multiple_experiments =
|
215
|
+
config.allow_multiple_experiments = "control"
|
215
216
|
end
|
216
217
|
groups = 100.times.map do |n|
|
217
|
-
ab_test("test#{n}".to_sym, {
|
218
|
+
ab_test("test#{n}".to_sym, { "control" => (100 - n) }, { "test#{n}-alt" => n })
|
218
219
|
end
|
219
220
|
|
220
221
|
experiments = ab_user.active_experiments
|
221
222
|
expect(experiments.size).to be > 1
|
222
223
|
|
223
|
-
count_control = experiments.values.count { |g| g ==
|
224
|
+
count_control = experiments.values.count { |g| g == "control" }
|
224
225
|
expect(count_control).to eq(experiments.size - 1)
|
225
226
|
|
226
|
-
count_alts = groups.count { |g| g !=
|
227
|
+
count_alts = groups.count { |g| g != "control" }
|
227
228
|
expect(count_alts).to eq(1)
|
228
229
|
end
|
229
230
|
|
230
231
|
context "when user already has experiment" do
|
231
|
-
let(:mock_user){ Split::User.new(self, {
|
232
|
+
let(:mock_user) { Split::User.new(self, { "test_0" => "test-alt" }) }
|
232
233
|
|
233
234
|
before do
|
234
235
|
Split.configure do |config|
|
235
|
-
config.allow_multiple_experiments =
|
236
|
+
config.allow_multiple_experiments = "control"
|
236
237
|
end
|
237
238
|
|
238
|
-
Split::ExperimentCatalog.find_or_initialize(
|
239
|
-
Split::ExperimentCatalog.find_or_initialize(
|
239
|
+
Split::ExperimentCatalog.find_or_initialize("test_0", "control", "test-alt").save
|
240
|
+
Split::ExperimentCatalog.find_or_initialize("test_1", "control", "test-alt").save
|
240
241
|
end
|
241
242
|
|
242
243
|
it "should restore previously selected alternative" do
|
243
244
|
expect(ab_user.active_experiments.size).to eq 1
|
244
|
-
expect(ab_test(:test_0, {
|
245
|
-
expect(ab_test(:test_0, {
|
245
|
+
expect(ab_test(:test_0, { "control" => 100 }, { "test-alt" => 1 })).to eq "test-alt"
|
246
|
+
expect(ab_test(:test_0, { "control" => 1 }, { "test-alt" => 100 })).to eq "test-alt"
|
246
247
|
end
|
247
248
|
|
248
249
|
it "should select the correct alternatives after experiment resets" do
|
249
250
|
experiment = Split::ExperimentCatalog.find(:test_0)
|
250
251
|
experiment.reset
|
251
|
-
mock_user[experiment.key] =
|
252
|
+
mock_user[experiment.key] = "test-alt"
|
252
253
|
|
253
254
|
expect(ab_user.active_experiments.size).to eq 1
|
254
|
-
expect(ab_test(:test_0, {
|
255
|
-
expect(ab_test(:test_0, {
|
255
|
+
expect(ab_test(:test_0, { "control" => 100 }, { "test-alt" => 1 })).to eq "test-alt"
|
256
|
+
expect(ab_test(:test_0, { "control" => 0 }, { "test-alt" => 100 })).to eq "test-alt"
|
256
257
|
end
|
257
258
|
|
258
259
|
it "lets override existing choice" do
|
259
260
|
pending "this requires user store reset on first call not depending on whelther it is current trial"
|
260
|
-
@params = {
|
261
|
+
@params = { "ab_test" => { "test_1" => "test-alt" } }
|
261
262
|
|
262
|
-
expect(ab_test(:test_0, {
|
263
|
-
expect(ab_test(:test_1, {
|
263
|
+
expect(ab_test(:test_0, { "control" => 0 }, { "test-alt" => 100 })).to eq "control"
|
264
|
+
expect(ab_test(:test_1, { "control" => 100 }, { "test-alt" => 1 })).to eq "test-alt"
|
264
265
|
end
|
265
|
-
|
266
266
|
end
|
267
|
-
|
268
267
|
end
|
269
268
|
|
270
269
|
it "should not over-write a finished key when an experiment is on a later version" do
|
271
270
|
experiment.increment_version
|
272
|
-
ab_user = { experiment.key =>
|
271
|
+
ab_user = { experiment.key => "blue", experiment.finished_key => true }
|
273
272
|
finished_session = ab_user.dup
|
274
|
-
ab_test(
|
273
|
+
ab_test("link_color", "blue", "red")
|
275
274
|
expect(ab_user).to eq(finished_session)
|
276
275
|
end
|
277
276
|
end
|
278
277
|
|
279
|
-
describe
|
280
|
-
context
|
278
|
+
describe "metadata" do
|
279
|
+
context "is defined" do
|
281
280
|
before do
|
282
281
|
Split.configuration.experiments = {
|
283
|
-
:
|
284
|
-
:
|
285
|
-
:
|
286
|
-
:
|
282
|
+
my_experiment: {
|
283
|
+
alternatives: ["one", "two"],
|
284
|
+
resettable: false,
|
285
|
+
metadata: { "one" => "Meta1", "two" => "Meta2" }
|
287
286
|
}
|
288
287
|
}
|
289
288
|
end
|
290
289
|
|
291
|
-
it
|
292
|
-
@params = {
|
293
|
-
expect(ab_test(
|
294
|
-
expect(ab_test(
|
290
|
+
it "should be passed to helper block" do
|
291
|
+
@params = { "ab_test" => { "my_experiment" => "two" } }
|
292
|
+
expect(ab_test("my_experiment")).to eq "two"
|
293
|
+
expect(ab_test("my_experiment") do |alternative, meta|
|
295
294
|
meta
|
296
|
-
end).to eq(
|
295
|
+
end).to eq("Meta2")
|
297
296
|
end
|
298
297
|
|
299
|
-
it
|
298
|
+
it "should pass control metadata helper block if library disabled" do
|
300
299
|
Split.configure do |config|
|
301
300
|
config.enabled = false
|
302
301
|
end
|
303
302
|
|
304
|
-
expect(ab_test(
|
305
|
-
expect(ab_test(
|
303
|
+
expect(ab_test("my_experiment")).to eq "one"
|
304
|
+
expect(ab_test("my_experiment") do |_, meta|
|
306
305
|
meta
|
307
|
-
end).to eq(
|
306
|
+
end).to eq("Meta1")
|
308
307
|
end
|
309
308
|
end
|
310
309
|
|
311
|
-
context
|
310
|
+
context "is not defined" do
|
312
311
|
before do
|
313
312
|
Split.configuration.experiments = {
|
314
|
-
:
|
315
|
-
:
|
316
|
-
:
|
317
|
-
:
|
313
|
+
my_experiment: {
|
314
|
+
alternatives: ["one", "two"],
|
315
|
+
resettable: false,
|
316
|
+
metadata: nil
|
318
317
|
}
|
319
318
|
}
|
320
319
|
end
|
321
320
|
|
322
|
-
it
|
323
|
-
expect(ab_test(
|
321
|
+
it "should be passed to helper block" do
|
322
|
+
expect(ab_test("my_experiment") do |alternative, meta|
|
324
323
|
meta
|
325
324
|
end).to eq({})
|
326
325
|
end
|
327
326
|
|
328
|
-
it
|
327
|
+
it "should pass control metadata helper block if library disabled" do
|
329
328
|
Split.configure do |config|
|
330
329
|
config.enabled = false
|
331
330
|
end
|
332
331
|
|
333
|
-
expect(ab_test(
|
332
|
+
expect(ab_test("my_experiment") do |_, meta|
|
334
333
|
meta
|
335
334
|
end).to eq({})
|
336
335
|
end
|
337
336
|
end
|
338
337
|
end
|
339
338
|
|
340
|
-
describe
|
341
|
-
context
|
339
|
+
describe "ab_finished" do
|
340
|
+
context "for an experiment that the user participates in" do
|
342
341
|
before(:each) do
|
343
|
-
@experiment_name =
|
344
|
-
@alternatives = [
|
342
|
+
@experiment_name = "link_color"
|
343
|
+
@alternatives = ["blue", "red"]
|
345
344
|
@experiment = Split::ExperimentCatalog.find_or_create(@experiment_name, *@alternatives)
|
346
345
|
@alternative_name = ab_test(@experiment_name, *@alternatives)
|
347
346
|
@previous_completion_count = Split::Alternative.new(@alternative_name, @experiment_name).completed_count
|
348
347
|
end
|
349
348
|
|
350
|
-
it
|
349
|
+
it "should increment the counter for the completed alternative" do
|
351
350
|
ab_finished(@experiment_name)
|
352
351
|
new_completion_count = Split::Alternative.new(@alternative_name, @experiment_name).completed_count
|
353
352
|
expect(new_completion_count).to eq(@previous_completion_count + 1)
|
354
353
|
end
|
355
354
|
|
356
355
|
it "should set experiment's finished key if reset is false" do
|
357
|
-
ab_finished(@experiment_name, {:
|
356
|
+
ab_finished(@experiment_name, { reset: false })
|
358
357
|
expect(ab_user[@experiment.key]).to eq(@alternative_name)
|
359
358
|
expect(ab_user[@experiment.finished_key]).to eq(true)
|
360
359
|
end
|
361
360
|
|
362
|
-
it
|
363
|
-
2.times { ab_finished(@experiment_name, {:
|
361
|
+
it "should not increment the counter if reset is false and the experiment has been already finished" do
|
362
|
+
2.times { ab_finished(@experiment_name, { reset: false }) }
|
364
363
|
new_completion_count = Split::Alternative.new(@alternative_name, @experiment_name).completed_count
|
365
364
|
expect(new_completion_count).to eq(@previous_completion_count + 1)
|
366
365
|
end
|
367
366
|
|
368
|
-
it
|
369
|
-
e = Split::ExperimentCatalog.find_or_create(
|
370
|
-
e.winner =
|
371
|
-
a = ab_test(
|
372
|
-
expect(a).to eq(
|
373
|
-
expect
|
374
|
-
ab_finished(
|
375
|
-
}
|
367
|
+
it "should not increment the counter for an ended experiment" do
|
368
|
+
e = Split::ExperimentCatalog.find_or_create("button_size", "small", "big")
|
369
|
+
e.winner = "small"
|
370
|
+
a = ab_test("button_size", "small", "big")
|
371
|
+
expect(a).to eq("small")
|
372
|
+
expect {
|
373
|
+
ab_finished("button_size")
|
374
|
+
}.not_to change { Split::Alternative.new(a, "button_size").completed_count }
|
376
375
|
end
|
377
376
|
|
378
377
|
it "should clear out the user's participation from their session" do
|
@@ -383,7 +382,7 @@ describe Split::Helper do
|
|
383
382
|
|
384
383
|
it "should not clear out the users session if reset is false" do
|
385
384
|
expect(ab_user[@experiment.key]).to eq(@alternative_name)
|
386
|
-
ab_finished(@experiment_name, {:
|
385
|
+
ab_finished(@experiment_name, { reset: false })
|
387
386
|
expect(ab_user[@experiment.key]).to eq(@alternative_name)
|
388
387
|
expect(ab_user[@experiment.finished_key]).to eq(true)
|
389
388
|
end
|
@@ -418,46 +417,46 @@ describe Split::Helper do
|
|
418
417
|
end
|
419
418
|
end
|
420
419
|
|
421
|
-
context
|
420
|
+
context "for an experiment that the user is excluded from" do
|
422
421
|
before do
|
423
|
-
alternative = ab_test(
|
424
|
-
expect(Split::Alternative.new(alternative,
|
425
|
-
alternative = ab_test(
|
426
|
-
expect(Split::Alternative.new(alternative,
|
422
|
+
alternative = ab_test("link_color", "blue", "red")
|
423
|
+
expect(Split::Alternative.new(alternative, "link_color").participant_count).to eq(1)
|
424
|
+
alternative = ab_test("button_size", "small", "big")
|
425
|
+
expect(Split::Alternative.new(alternative, "button_size").participant_count).to eq(0)
|
427
426
|
end
|
428
427
|
|
429
|
-
it
|
428
|
+
it "should not increment the completed counter" do
|
430
429
|
# So, user should be participating in the link_color experiment and
|
431
430
|
# receive the control for button_size. As the user is not participating in
|
432
431
|
# the button size experiment, finishing it should not increase the
|
433
432
|
# completion count for that alternative.
|
434
|
-
expect
|
435
|
-
ab_finished(
|
436
|
-
}
|
433
|
+
expect {
|
434
|
+
ab_finished("button_size")
|
435
|
+
}.not_to change { Split::Alternative.new("small", "button_size").completed_count }
|
437
436
|
end
|
438
437
|
end
|
439
438
|
|
440
|
-
context
|
439
|
+
context "for an experiment that the user does not participate in" do
|
441
440
|
before do
|
442
|
-
Split::ExperimentCatalog.find_or_create(:not_started_experiment,
|
441
|
+
Split::ExperimentCatalog.find_or_create(:not_started_experiment, "control", "alt")
|
443
442
|
end
|
444
|
-
it
|
443
|
+
it "should not raise an exception" do
|
445
444
|
expect { ab_finished(:not_started_experiment) }.not_to raise_exception
|
446
445
|
end
|
447
446
|
|
448
|
-
it
|
449
|
-
expect { ab_finished(:not_started_experiment, reset: false) }.not_to change { ab_user.keys}.from([])
|
447
|
+
it "should not change the user state when reset is false" do
|
448
|
+
expect { ab_finished(:not_started_experiment, reset: false) }.not_to change { ab_user.keys }.from([])
|
450
449
|
end
|
451
450
|
|
452
|
-
it
|
451
|
+
it "should not change the user state when reset is true" do
|
453
452
|
expect(self).not_to receive(:reset!)
|
454
453
|
ab_finished(:not_started_experiment)
|
455
454
|
end
|
456
455
|
|
457
|
-
it
|
456
|
+
it "should not increment the completed counter" do
|
458
457
|
ab_finished(:not_started_experiment)
|
459
|
-
expect(Split::Alternative.new(
|
460
|
-
expect(Split::Alternative.new(
|
458
|
+
expect(Split::Alternative.new("control", :not_started_experiment).completed_count).to eq(0)
|
459
|
+
expect(Split::Alternative.new("alt", :not_started_experiment).completed_count).to eq(0)
|
461
460
|
end
|
462
461
|
end
|
463
462
|
end
|
@@ -465,9 +464,9 @@ describe Split::Helper do
|
|
465
464
|
context "finished with config" do
|
466
465
|
it "passes reset option" do
|
467
466
|
Split.configuration.experiments = {
|
468
|
-
:
|
469
|
-
:
|
470
|
-
:
|
467
|
+
my_experiment: {
|
468
|
+
alternatives: ["one", "two"],
|
469
|
+
resettable: false,
|
471
470
|
}
|
472
471
|
}
|
473
472
|
alternative = ab_test(:my_experiment)
|
@@ -483,11 +482,11 @@ describe Split::Helper do
|
|
483
482
|
before { Split.configuration.experiments = {} }
|
484
483
|
before { expect(Split::Alternative).to receive(:new).at_least(1).times.and_call_original }
|
485
484
|
|
486
|
-
def should_finish_experiment(experiment_name, should_finish=true)
|
485
|
+
def should_finish_experiment(experiment_name, should_finish = true)
|
487
486
|
alts = Split.configuration.experiments[experiment_name][:alternatives]
|
488
487
|
experiment = Split::ExperimentCatalog.find_or_create(experiment_name, *alts)
|
489
488
|
alt_name = ab_user[experiment.key] = alts.first
|
490
|
-
alt = double(
|
489
|
+
alt = double("alternative")
|
491
490
|
expect(alt).to receive(:name).at_most(1).times.and_return(alt_name)
|
492
491
|
expect(Split::Alternative).to receive(:new).at_most(1).times.with(alt_name, experiment_name.to_s).and_return(alt)
|
493
492
|
if should_finish
|
@@ -499,8 +498,8 @@ describe Split::Helper do
|
|
499
498
|
|
500
499
|
it "completes the test" do
|
501
500
|
Split.configuration.experiments[:my_experiment] = {
|
502
|
-
:
|
503
|
-
:
|
501
|
+
alternatives: [ "control_opt", "other_opt" ],
|
502
|
+
metric: :my_metric
|
504
503
|
}
|
505
504
|
should_finish_experiment :my_experiment
|
506
505
|
ab_finished :my_metric
|
@@ -508,17 +507,17 @@ describe Split::Helper do
|
|
508
507
|
|
509
508
|
it "completes all relevant tests" do
|
510
509
|
Split.configuration.experiments = {
|
511
|
-
:
|
512
|
-
:
|
513
|
-
:
|
510
|
+
exp_1: {
|
511
|
+
alternatives: [ "1-1", "1-2" ],
|
512
|
+
metric: :my_metric
|
514
513
|
},
|
515
|
-
:
|
516
|
-
:
|
517
|
-
:
|
514
|
+
exp_2: {
|
515
|
+
alternatives: [ "2-1", "2-2" ],
|
516
|
+
metric: :another_metric
|
518
517
|
},
|
519
|
-
:
|
520
|
-
:
|
521
|
-
:
|
518
|
+
exp_3: {
|
519
|
+
alternatives: [ "3-1", "3-2" ],
|
520
|
+
metric: :my_metric
|
522
521
|
},
|
523
522
|
}
|
524
523
|
should_finish_experiment :exp_1
|
@@ -529,10 +528,10 @@ describe Split::Helper do
|
|
529
528
|
|
530
529
|
it "passes reset option" do
|
531
530
|
Split.configuration.experiments = {
|
532
|
-
:
|
533
|
-
:
|
534
|
-
:
|
535
|
-
:
|
531
|
+
my_exp: {
|
532
|
+
alternatives: ["one", "two"],
|
533
|
+
metric: :my_metric,
|
534
|
+
resettable: false,
|
536
535
|
}
|
537
536
|
}
|
538
537
|
alternative_name = ab_test(:my_exp)
|
@@ -545,199 +544,197 @@ describe Split::Helper do
|
|
545
544
|
|
546
545
|
it "passes through options" do
|
547
546
|
Split.configuration.experiments = {
|
548
|
-
:
|
549
|
-
:
|
550
|
-
:
|
547
|
+
my_exp: {
|
548
|
+
alternatives: ["one", "two"],
|
549
|
+
metric: :my_metric,
|
551
550
|
}
|
552
551
|
}
|
553
552
|
alternative_name = ab_test(:my_exp)
|
554
553
|
exp = Split::ExperimentCatalog.find :my_exp
|
555
554
|
|
556
|
-
ab_finished :my_metric, :
|
555
|
+
ab_finished :my_metric, reset: false
|
557
556
|
expect(ab_user[exp.key]).to eq(alternative_name)
|
558
557
|
expect(ab_user[exp.finished_key]).to be_truthy
|
559
558
|
end
|
560
559
|
end
|
561
560
|
|
562
|
-
describe
|
563
|
-
it
|
564
|
-
alternative_name = ab_test(
|
561
|
+
describe "conversions" do
|
562
|
+
it "should return a conversion rate for an alternative" do
|
563
|
+
alternative_name = ab_test("link_color", "blue", "red")
|
565
564
|
|
566
|
-
previous_convertion_rate = Split::Alternative.new(alternative_name,
|
565
|
+
previous_convertion_rate = Split::Alternative.new(alternative_name, "link_color").conversion_rate
|
567
566
|
expect(previous_convertion_rate).to eq(0.0)
|
568
567
|
|
569
|
-
ab_finished(
|
568
|
+
ab_finished("link_color")
|
570
569
|
|
571
|
-
new_convertion_rate = Split::Alternative.new(alternative_name,
|
570
|
+
new_convertion_rate = Split::Alternative.new(alternative_name, "link_color").conversion_rate
|
572
571
|
expect(new_convertion_rate).to eq(1.0)
|
573
572
|
end
|
574
573
|
end
|
575
574
|
|
576
|
-
describe
|
577
|
-
it
|
578
|
-
alternative = ab_test(
|
575
|
+
describe "active experiments" do
|
576
|
+
it "should show an active test" do
|
577
|
+
alternative = ab_test("def", "4", "5", "6")
|
579
578
|
expect(active_experiments.count).to eq 1
|
580
579
|
expect(active_experiments.first[0]).to eq "def"
|
581
580
|
expect(active_experiments.first[1]).to eq alternative
|
582
581
|
end
|
583
582
|
|
584
|
-
it
|
585
|
-
alternative = ab_test(
|
586
|
-
ab_finished(
|
583
|
+
it "should show a finished test" do
|
584
|
+
alternative = ab_test("def", "4", "5", "6")
|
585
|
+
ab_finished("def", { reset: false })
|
587
586
|
expect(active_experiments.count).to eq 1
|
588
587
|
expect(active_experiments.first[0]).to eq "def"
|
589
588
|
expect(active_experiments.first[1]).to eq alternative
|
590
589
|
end
|
591
590
|
|
592
|
-
it
|
591
|
+
it "should show an active test when an experiment is on a later version" do
|
593
592
|
experiment.reset
|
594
593
|
expect(experiment.version).to eq(1)
|
595
|
-
ab_test(
|
594
|
+
ab_test("link_color", "blue", "red")
|
596
595
|
expect(active_experiments.count).to eq 1
|
597
596
|
expect(active_experiments.first[0]).to eq "link_color"
|
598
597
|
end
|
599
598
|
|
600
|
-
it
|
599
|
+
it "should show versioned tests properly" do
|
601
600
|
10.times { experiment.reset }
|
602
601
|
|
603
|
-
alternative = ab_test(experiment.name,
|
602
|
+
alternative = ab_test(experiment.name, "blue", "red")
|
604
603
|
ab_finished(experiment.name, reset: false)
|
605
604
|
|
606
605
|
expect(experiment.version).to eq(10)
|
607
606
|
expect(active_experiments.count).to eq 1
|
608
|
-
expect(active_experiments).to eq({
|
607
|
+
expect(active_experiments).to eq({ "link_color" => alternative })
|
609
608
|
end
|
610
609
|
|
611
|
-
it
|
610
|
+
it "should show multiple tests" do
|
612
611
|
Split.configure do |config|
|
613
612
|
config.allow_multiple_experiments = true
|
614
613
|
end
|
615
|
-
alternative = ab_test(
|
616
|
-
another_alternative = ab_test(
|
614
|
+
alternative = ab_test("def", "4", "5", "6")
|
615
|
+
another_alternative = ab_test("ghi", "7", "8", "9")
|
617
616
|
expect(active_experiments.count).to eq 2
|
618
|
-
expect(active_experiments[
|
619
|
-
expect(active_experiments[
|
617
|
+
expect(active_experiments["def"]).to eq alternative
|
618
|
+
expect(active_experiments["ghi"]).to eq another_alternative
|
620
619
|
end
|
621
620
|
|
622
|
-
it
|
621
|
+
it "should not show tests with winners" do
|
623
622
|
Split.configure do |config|
|
624
623
|
config.allow_multiple_experiments = true
|
625
624
|
end
|
626
|
-
e = Split::ExperimentCatalog.find_or_create(
|
627
|
-
e.winner =
|
628
|
-
ab_test(
|
629
|
-
another_alternative = ab_test(
|
625
|
+
e = Split::ExperimentCatalog.find_or_create("def", "4", "5", "6")
|
626
|
+
e.winner = "4"
|
627
|
+
ab_test("def", "4", "5", "6")
|
628
|
+
another_alternative = ab_test("ghi", "7", "8", "9")
|
630
629
|
expect(active_experiments.count).to eq 1
|
631
630
|
expect(active_experiments.first[0]).to eq "ghi"
|
632
631
|
expect(active_experiments.first[1]).to eq another_alternative
|
633
632
|
end
|
634
633
|
end
|
635
634
|
|
636
|
-
describe
|
635
|
+
describe "when user is a robot" do
|
637
636
|
before(:each) do
|
638
|
-
@request = OpenStruct.new(:
|
637
|
+
@request = OpenStruct.new(user_agent: "Googlebot/2.1 (+http://www.google.com/bot.html)")
|
639
638
|
end
|
640
639
|
|
641
|
-
describe
|
642
|
-
it
|
643
|
-
alternative = ab_test(
|
640
|
+
describe "ab_test" do
|
641
|
+
it "should return the control" do
|
642
|
+
alternative = ab_test("link_color", "blue", "red")
|
644
643
|
expect(alternative).to eq experiment.control.name
|
645
644
|
end
|
646
645
|
|
647
|
-
it
|
648
|
-
ab_test(
|
649
|
-
expect(Split::Experiment.new(
|
646
|
+
it "should not create a experiment" do
|
647
|
+
ab_test("link_color", "blue", "red")
|
648
|
+
expect(Split::Experiment.new("link_color")).to be_a_new_record
|
650
649
|
end
|
651
650
|
|
652
651
|
it "should not increment the participation count" do
|
652
|
+
previous_red_count = Split::Alternative.new("red", "link_color").participant_count
|
653
|
+
previous_blue_count = Split::Alternative.new("blue", "link_color").participant_count
|
653
654
|
|
654
|
-
|
655
|
-
previous_blue_count = Split::Alternative.new('blue', 'link_color').participant_count
|
655
|
+
ab_test("link_color", "blue", "red")
|
656
656
|
|
657
|
-
|
658
|
-
|
659
|
-
new_red_count = Split::Alternative.new('red', 'link_color').participant_count
|
660
|
-
new_blue_count = Split::Alternative.new('blue', 'link_color').participant_count
|
657
|
+
new_red_count = Split::Alternative.new("red", "link_color").participant_count
|
658
|
+
new_blue_count = Split::Alternative.new("blue", "link_color").participant_count
|
661
659
|
|
662
660
|
expect((new_red_count + new_blue_count)).to eq(previous_red_count + previous_blue_count)
|
663
661
|
end
|
664
662
|
end
|
665
663
|
|
666
|
-
describe
|
664
|
+
describe "finished" do
|
667
665
|
it "should not increment the completed count" do
|
668
|
-
alternative_name = ab_test(
|
666
|
+
alternative_name = ab_test("link_color", "blue", "red")
|
669
667
|
|
670
|
-
previous_completion_count = Split::Alternative.new(alternative_name,
|
668
|
+
previous_completion_count = Split::Alternative.new(alternative_name, "link_color").completed_count
|
671
669
|
|
672
|
-
ab_finished(
|
670
|
+
ab_finished("link_color")
|
673
671
|
|
674
|
-
new_completion_count = Split::Alternative.new(alternative_name,
|
672
|
+
new_completion_count = Split::Alternative.new(alternative_name, "link_color").completed_count
|
675
673
|
|
676
674
|
expect(new_completion_count).to eq(previous_completion_count)
|
677
675
|
end
|
678
676
|
end
|
679
677
|
end
|
680
678
|
|
681
|
-
describe
|
679
|
+
describe "when providing custom ignore logic" do
|
682
680
|
context "using a proc to configure custom logic" do
|
683
|
-
|
684
681
|
before(:each) do
|
685
682
|
Split.configure do |c|
|
686
|
-
c.ignore_filter = proc{|request| true } # ignore everything
|
683
|
+
c.ignore_filter = proc { |request| true } # ignore everything
|
687
684
|
end
|
688
685
|
end
|
689
686
|
|
690
687
|
it "ignores the ab_test" do
|
691
|
-
ab_test(
|
688
|
+
ab_test("link_color", "blue", "red")
|
692
689
|
|
693
|
-
red_count = Split::Alternative.new(
|
694
|
-
blue_count = Split::Alternative.new(
|
690
|
+
red_count = Split::Alternative.new("red", "link_color").participant_count
|
691
|
+
blue_count = Split::Alternative.new("blue", "link_color").participant_count
|
695
692
|
expect((red_count + blue_count)).to be(0)
|
696
693
|
end
|
697
694
|
end
|
698
695
|
end
|
699
696
|
|
700
697
|
shared_examples_for "a disabled test" do
|
701
|
-
describe
|
702
|
-
it
|
703
|
-
alternative = ab_test(
|
698
|
+
describe "ab_test" do
|
699
|
+
it "should return the control" do
|
700
|
+
alternative = ab_test("link_color", "blue", "red")
|
704
701
|
expect(alternative).to eq experiment.control.name
|
705
702
|
end
|
706
703
|
|
707
704
|
it "should not increment the participation count" do
|
708
|
-
previous_red_count = Split::Alternative.new(
|
709
|
-
previous_blue_count = Split::Alternative.new(
|
705
|
+
previous_red_count = Split::Alternative.new("red", "link_color").participant_count
|
706
|
+
previous_blue_count = Split::Alternative.new("blue", "link_color").participant_count
|
710
707
|
|
711
|
-
ab_test(
|
708
|
+
ab_test("link_color", "blue", "red")
|
712
709
|
|
713
|
-
new_red_count = Split::Alternative.new(
|
714
|
-
new_blue_count = Split::Alternative.new(
|
710
|
+
new_red_count = Split::Alternative.new("red", "link_color").participant_count
|
711
|
+
new_blue_count = Split::Alternative.new("blue", "link_color").participant_count
|
715
712
|
|
716
713
|
expect((new_red_count + new_blue_count)).to eq(previous_red_count + previous_blue_count)
|
717
714
|
end
|
718
715
|
end
|
719
716
|
|
720
|
-
describe
|
717
|
+
describe "finished" do
|
721
718
|
it "should not increment the completed count" do
|
722
|
-
alternative_name = ab_test(
|
719
|
+
alternative_name = ab_test("link_color", "blue", "red")
|
723
720
|
|
724
|
-
previous_completion_count = Split::Alternative.new(alternative_name,
|
721
|
+
previous_completion_count = Split::Alternative.new(alternative_name, "link_color").completed_count
|
725
722
|
|
726
|
-
ab_finished(
|
723
|
+
ab_finished("link_color")
|
727
724
|
|
728
|
-
new_completion_count = Split::Alternative.new(alternative_name,
|
725
|
+
new_completion_count = Split::Alternative.new(alternative_name, "link_color").completed_count
|
729
726
|
|
730
727
|
expect(new_completion_count).to eq(previous_completion_count)
|
731
728
|
end
|
732
729
|
end
|
733
730
|
end
|
734
731
|
|
735
|
-
describe
|
732
|
+
describe "when ip address is ignored" do
|
736
733
|
context "individually" do
|
737
734
|
before(:each) do
|
738
|
-
@request = OpenStruct.new(:
|
735
|
+
@request = OpenStruct.new(ip: "81.19.48.130")
|
739
736
|
Split.configure do |c|
|
740
|
-
c.ignore_ip_addresses <<
|
737
|
+
c.ignore_ip_addresses << "81.19.48.130"
|
741
738
|
end
|
742
739
|
end
|
743
740
|
|
@@ -746,7 +743,7 @@ describe Split::Helper do
|
|
746
743
|
|
747
744
|
context "for a range" do
|
748
745
|
before(:each) do
|
749
|
-
@request = OpenStruct.new(:
|
746
|
+
@request = OpenStruct.new(ip: "81.19.48.129")
|
750
747
|
Split.configure do |c|
|
751
748
|
c.ignore_ip_addresses << /81\.19\.48\.[0-9]+/
|
752
749
|
end
|
@@ -757,9 +754,9 @@ describe Split::Helper do
|
|
757
754
|
|
758
755
|
context "using both a range and a specific value" do
|
759
756
|
before(:each) do
|
760
|
-
@request = OpenStruct.new(:
|
757
|
+
@request = OpenStruct.new(ip: "81.19.48.128")
|
761
758
|
Split.configure do |c|
|
762
|
-
c.ignore_ip_addresses <<
|
759
|
+
c.ignore_ip_addresses << "81.19.48.130"
|
763
760
|
c.ignore_ip_addresses << /81\.19\.48\.[0-9]+/
|
764
761
|
end
|
765
762
|
end
|
@@ -769,119 +766,119 @@ describe Split::Helper do
|
|
769
766
|
|
770
767
|
context "when ignored other address" do
|
771
768
|
before do
|
772
|
-
@request = OpenStruct.new(:
|
769
|
+
@request = OpenStruct.new(ip: "1.1.1.1")
|
773
770
|
Split.configure do |c|
|
774
|
-
c.ignore_ip_addresses <<
|
771
|
+
c.ignore_ip_addresses << "81.19.48.130"
|
775
772
|
end
|
776
773
|
end
|
777
774
|
|
778
775
|
it "works as usual" do
|
779
|
-
alternative_name = ab_test(
|
780
|
-
expect{
|
781
|
-
ab_finished(
|
782
|
-
}.to change(Split::Alternative.new(alternative_name,
|
776
|
+
alternative_name = ab_test("link_color", "red", "blue")
|
777
|
+
expect {
|
778
|
+
ab_finished("link_color")
|
779
|
+
}.to change(Split::Alternative.new(alternative_name, "link_color"), :completed_count).by(1)
|
783
780
|
end
|
784
781
|
end
|
785
782
|
end
|
786
783
|
|
787
|
-
describe
|
784
|
+
describe "when user is previewing" do
|
788
785
|
before(:each) do
|
789
|
-
@request = OpenStruct.new(headers: {
|
786
|
+
@request = OpenStruct.new(headers: { "x-purpose" => "preview" })
|
790
787
|
end
|
791
788
|
|
792
789
|
it_behaves_like "a disabled test"
|
793
790
|
end
|
794
791
|
|
795
|
-
describe
|
792
|
+
describe "versioned experiments" do
|
796
793
|
it "should use version zero if no version is present" do
|
797
|
-
alternative_name = ab_test(
|
794
|
+
alternative_name = ab_test("link_color", "blue", "red")
|
798
795
|
expect(experiment.version).to eq(0)
|
799
|
-
expect(ab_user[
|
796
|
+
expect(ab_user["link_color"]).to eq(alternative_name)
|
800
797
|
end
|
801
798
|
|
802
799
|
it "should save the version of the experiment to the session" do
|
803
800
|
experiment.reset
|
804
801
|
expect(experiment.version).to eq(1)
|
805
|
-
alternative_name = ab_test(
|
806
|
-
expect(ab_user[
|
802
|
+
alternative_name = ab_test("link_color", "blue", "red")
|
803
|
+
expect(ab_user["link_color:1"]).to eq(alternative_name)
|
807
804
|
end
|
808
805
|
|
809
806
|
it "should load the experiment even if the version is not 0" do
|
810
807
|
experiment.reset
|
811
808
|
expect(experiment.version).to eq(1)
|
812
|
-
alternative_name = ab_test(
|
813
|
-
expect(ab_user[
|
814
|
-
return_alternative_name = ab_test(
|
809
|
+
alternative_name = ab_test("link_color", "blue", "red")
|
810
|
+
expect(ab_user["link_color:1"]).to eq(alternative_name)
|
811
|
+
return_alternative_name = ab_test("link_color", "blue", "red")
|
815
812
|
expect(return_alternative_name).to eq(alternative_name)
|
816
813
|
end
|
817
814
|
|
818
815
|
it "should reset the session of a user on an older version of the experiment" do
|
819
|
-
alternative_name = ab_test(
|
820
|
-
expect(ab_user[
|
821
|
-
alternative = Split::Alternative.new(alternative_name,
|
816
|
+
alternative_name = ab_test("link_color", "blue", "red")
|
817
|
+
expect(ab_user["link_color"]).to eq(alternative_name)
|
818
|
+
alternative = Split::Alternative.new(alternative_name, "link_color")
|
822
819
|
expect(alternative.participant_count).to eq(1)
|
823
820
|
|
824
821
|
experiment.reset
|
825
822
|
expect(experiment.version).to eq(1)
|
826
|
-
alternative = Split::Alternative.new(alternative_name,
|
823
|
+
alternative = Split::Alternative.new(alternative_name, "link_color")
|
827
824
|
expect(alternative.participant_count).to eq(0)
|
828
825
|
|
829
|
-
new_alternative_name = ab_test(
|
830
|
-
expect(ab_user[
|
831
|
-
new_alternative = Split::Alternative.new(new_alternative_name,
|
826
|
+
new_alternative_name = ab_test("link_color", "blue", "red")
|
827
|
+
expect(ab_user["link_color:1"]).to eq(new_alternative_name)
|
828
|
+
new_alternative = Split::Alternative.new(new_alternative_name, "link_color")
|
832
829
|
expect(new_alternative.participant_count).to eq(1)
|
833
830
|
end
|
834
831
|
|
835
832
|
it "should cleanup old versions of experiments from the session" do
|
836
|
-
alternative_name = ab_test(
|
837
|
-
expect(ab_user[
|
838
|
-
alternative = Split::Alternative.new(alternative_name,
|
833
|
+
alternative_name = ab_test("link_color", "blue", "red")
|
834
|
+
expect(ab_user["link_color"]).to eq(alternative_name)
|
835
|
+
alternative = Split::Alternative.new(alternative_name, "link_color")
|
839
836
|
expect(alternative.participant_count).to eq(1)
|
840
837
|
|
841
838
|
experiment.reset
|
842
839
|
expect(experiment.version).to eq(1)
|
843
|
-
alternative = Split::Alternative.new(alternative_name,
|
840
|
+
alternative = Split::Alternative.new(alternative_name, "link_color")
|
844
841
|
expect(alternative.participant_count).to eq(0)
|
845
842
|
|
846
|
-
new_alternative_name = ab_test(
|
847
|
-
expect(ab_user[
|
843
|
+
new_alternative_name = ab_test("link_color", "blue", "red")
|
844
|
+
expect(ab_user["link_color:1"]).to eq(new_alternative_name)
|
848
845
|
end
|
849
846
|
|
850
847
|
it "should only count completion of users on the current version" do
|
851
|
-
alternative_name = ab_test(
|
852
|
-
expect(ab_user[
|
853
|
-
|
848
|
+
alternative_name = ab_test("link_color", "blue", "red")
|
849
|
+
expect(ab_user["link_color"]).to eq(alternative_name)
|
850
|
+
Split::Alternative.new(alternative_name, "link_color")
|
854
851
|
|
855
852
|
experiment.reset
|
856
853
|
expect(experiment.version).to eq(1)
|
857
854
|
|
858
|
-
ab_finished(
|
859
|
-
alternative = Split::Alternative.new(alternative_name,
|
855
|
+
ab_finished("link_color")
|
856
|
+
alternative = Split::Alternative.new(alternative_name, "link_color")
|
860
857
|
expect(alternative.completed_count).to eq(0)
|
861
858
|
end
|
862
859
|
end
|
863
860
|
|
864
|
-
context
|
861
|
+
context "when redis is not available" do
|
865
862
|
before(:each) do
|
866
863
|
expect(Split).to receive(:redis).at_most(5).times.and_raise(Errno::ECONNREFUSED.new)
|
867
864
|
end
|
868
865
|
|
869
|
-
context
|
866
|
+
context "and db_failover config option is turned off" do
|
870
867
|
before(:each) do
|
871
868
|
Split.configure do |config|
|
872
869
|
config.db_failover = false
|
873
870
|
end
|
874
871
|
end
|
875
872
|
|
876
|
-
describe
|
877
|
-
it
|
878
|
-
expect
|
873
|
+
describe "ab_test" do
|
874
|
+
it "should raise an exception" do
|
875
|
+
expect { ab_test("link_color", "blue", "red") }.to raise_error(Errno::ECONNREFUSED)
|
879
876
|
end
|
880
877
|
end
|
881
878
|
|
882
|
-
describe
|
883
|
-
it
|
884
|
-
expect
|
879
|
+
describe "finished" do
|
880
|
+
it "should raise an exception" do
|
881
|
+
expect { ab_finished("link_color") }.to raise_error(Errno::ECONNREFUSED)
|
885
882
|
end
|
886
883
|
end
|
887
884
|
|
@@ -893,29 +890,29 @@ describe Split::Helper do
|
|
893
890
|
end
|
894
891
|
|
895
892
|
it "should not attempt to connect to redis" do
|
896
|
-
expect
|
893
|
+
expect { ab_test("link_color", "blue", "red") }.not_to raise_error
|
897
894
|
end
|
898
895
|
|
899
896
|
it "should return control variable" do
|
900
|
-
expect(ab_test(
|
901
|
-
expect
|
897
|
+
expect(ab_test("link_color", "blue", "red")).to eq("blue")
|
898
|
+
expect { ab_finished("link_color") }.not_to raise_error
|
902
899
|
end
|
903
900
|
end
|
904
901
|
end
|
905
902
|
|
906
|
-
context
|
903
|
+
context "and db_failover config option is turned on" do
|
907
904
|
before(:each) do
|
908
905
|
Split.configure do |config|
|
909
906
|
config.db_failover = true
|
910
907
|
end
|
911
908
|
end
|
912
909
|
|
913
|
-
describe
|
914
|
-
it
|
915
|
-
expect
|
910
|
+
describe "ab_test" do
|
911
|
+
it "should not raise an exception" do
|
912
|
+
expect { ab_test("link_color", "blue", "red") }.not_to raise_error
|
916
913
|
end
|
917
914
|
|
918
|
-
it
|
915
|
+
it "should call db_failover_on_db_error proc with error as parameter" do
|
919
916
|
Split.configure do |config|
|
920
917
|
config.db_failover_on_db_error = proc do |error|
|
921
918
|
expect(error).to be_a(Errno::ECONNREFUSED)
|
@@ -923,43 +920,43 @@ describe Split::Helper do
|
|
923
920
|
end
|
924
921
|
|
925
922
|
expect(Split.configuration.db_failover_on_db_error).to receive(:call).and_call_original
|
926
|
-
ab_test(
|
923
|
+
ab_test("link_color", "blue", "red")
|
927
924
|
end
|
928
925
|
|
929
|
-
it
|
930
|
-
expect(ab_test(
|
931
|
-
expect(ab_test(
|
932
|
-
expect(ab_test(
|
933
|
-
expect(ab_test(
|
926
|
+
it "should always use first alternative" do
|
927
|
+
expect(ab_test("link_color", "blue", "red")).to eq("blue")
|
928
|
+
expect(ab_test("link_color", { "blue" => 0.01 }, "red" => 0.2)).to eq("blue")
|
929
|
+
expect(ab_test("link_color", { "blue" => 0.8 }, { "red" => 20 })).to eq("blue")
|
930
|
+
expect(ab_test("link_color", "blue", "red") do |alternative|
|
934
931
|
"shared/#{alternative}"
|
935
|
-
end).to eq(
|
932
|
+
end).to eq("shared/blue")
|
936
933
|
end
|
937
934
|
|
938
|
-
context
|
935
|
+
context "and db_failover_allow_parameter_override config option is turned on" do
|
939
936
|
before(:each) do
|
940
937
|
Split.configure do |config|
|
941
938
|
config.db_failover_allow_parameter_override = true
|
942
939
|
end
|
943
940
|
end
|
944
941
|
|
945
|
-
context
|
946
|
-
it
|
947
|
-
@params = {
|
948
|
-
expect(ab_test(
|
949
|
-
expect(ab_test(
|
950
|
-
expect(ab_test(
|
951
|
-
expect(ab_test(
|
952
|
-
expect(ab_test(
|
942
|
+
context "and given an override parameter" do
|
943
|
+
it "should use given override instead of the first alternative" do
|
944
|
+
@params = { "ab_test" => { "link_color" => "red" } }
|
945
|
+
expect(ab_test("link_color", "blue", "red")).to eq("red")
|
946
|
+
expect(ab_test("link_color", "blue", "red", "green")).to eq("red")
|
947
|
+
expect(ab_test("link_color", { "blue" => 0.01 }, "red" => 0.2)).to eq("red")
|
948
|
+
expect(ab_test("link_color", { "blue" => 0.8 }, { "red" => 20 })).to eq("red")
|
949
|
+
expect(ab_test("link_color", "blue", "red") do |alternative|
|
953
950
|
"shared/#{alternative}"
|
954
|
-
end).to eq(
|
951
|
+
end).to eq("shared/red")
|
955
952
|
end
|
956
953
|
end
|
957
954
|
end
|
958
955
|
|
959
|
-
context
|
956
|
+
context "and preloaded config given" do
|
960
957
|
before do
|
961
958
|
Split.configuration.experiments[:link_color] = {
|
962
|
-
:
|
959
|
+
alternatives: [ "blue", "red" ],
|
963
960
|
}
|
964
961
|
end
|
965
962
|
|
@@ -969,12 +966,12 @@ describe Split::Helper do
|
|
969
966
|
end
|
970
967
|
end
|
971
968
|
|
972
|
-
describe
|
973
|
-
it
|
974
|
-
expect
|
969
|
+
describe "finished" do
|
970
|
+
it "should not raise an exception" do
|
971
|
+
expect { ab_finished("link_color") }.not_to raise_error
|
975
972
|
end
|
976
973
|
|
977
|
-
it
|
974
|
+
it "should call db_failover_on_db_error proc with error as parameter" do
|
978
975
|
Split.configure do |config|
|
979
976
|
config.db_failover_on_db_error = proc do |error|
|
980
977
|
expect(error).to be_a(Errno::ECONNREFUSED)
|
@@ -982,19 +979,19 @@ describe Split::Helper do
|
|
982
979
|
end
|
983
980
|
|
984
981
|
expect(Split.configuration.db_failover_on_db_error).to receive(:call).and_call_original
|
985
|
-
ab_finished(
|
982
|
+
ab_finished("link_color")
|
986
983
|
end
|
987
984
|
end
|
988
985
|
end
|
989
986
|
end
|
990
987
|
|
991
988
|
context "with preloaded config" do
|
992
|
-
before { Split.configuration.experiments = {}}
|
989
|
+
before { Split.configuration.experiments = {} }
|
993
990
|
|
994
991
|
it "pulls options from config file" do
|
995
992
|
Split.configuration.experiments[:my_experiment] = {
|
996
|
-
:
|
997
|
-
:
|
993
|
+
alternatives: [ "control_opt", "other_opt" ],
|
994
|
+
goals: ["goal1", "goal2"]
|
998
995
|
}
|
999
996
|
ab_test :my_experiment
|
1000
997
|
expect(Split::Experiment.new(:my_experiment).alternatives.map(&:name)).to eq([ "control_opt", "other_opt" ])
|
@@ -1003,8 +1000,8 @@ describe Split::Helper do
|
|
1003
1000
|
|
1004
1001
|
it "can be called multiple times" do
|
1005
1002
|
Split.configuration.experiments[:my_experiment] = {
|
1006
|
-
:
|
1007
|
-
:
|
1003
|
+
alternatives: [ "control_opt", "other_opt" ],
|
1004
|
+
goals: ["goal1", "goal2"]
|
1008
1005
|
}
|
1009
1006
|
5.times { ab_test :my_experiment }
|
1010
1007
|
experiment = Split::Experiment.new(:my_experiment)
|
@@ -1015,8 +1012,8 @@ describe Split::Helper do
|
|
1015
1012
|
|
1016
1013
|
it "accepts multiple goals" do
|
1017
1014
|
Split.configuration.experiments[:my_experiment] = {
|
1018
|
-
:
|
1019
|
-
:
|
1015
|
+
alternatives: [ "control_opt", "other_opt" ],
|
1016
|
+
goals: [ "goal1", "goal2", "goal3" ]
|
1020
1017
|
}
|
1021
1018
|
ab_test :my_experiment
|
1022
1019
|
experiment = Split::Experiment.new(:my_experiment)
|
@@ -1025,7 +1022,7 @@ describe Split::Helper do
|
|
1025
1022
|
|
1026
1023
|
it "allow specifying goals to be optional" do
|
1027
1024
|
Split.configuration.experiments[:my_experiment] = {
|
1028
|
-
:
|
1025
|
+
alternatives: [ "control_opt", "other_opt" ]
|
1029
1026
|
}
|
1030
1027
|
experiment = Split::Experiment.new(:my_experiment)
|
1031
1028
|
expect(experiment.goals).to eq([])
|
@@ -1033,7 +1030,7 @@ describe Split::Helper do
|
|
1033
1030
|
|
1034
1031
|
it "accepts multiple alternatives" do
|
1035
1032
|
Split.configuration.experiments[:my_experiment] = {
|
1036
|
-
:
|
1033
|
+
alternatives: [ "control_opt", "second_opt", "third_opt" ],
|
1037
1034
|
}
|
1038
1035
|
ab_test :my_experiment
|
1039
1036
|
experiment = Split::Experiment.new(:my_experiment)
|
@@ -1042,68 +1039,68 @@ describe Split::Helper do
|
|
1042
1039
|
|
1043
1040
|
it "accepts probability on alternatives" do
|
1044
1041
|
Split.configuration.experiments[:my_experiment] = {
|
1045
|
-
:
|
1046
|
-
{ :
|
1047
|
-
{ :
|
1048
|
-
{ :
|
1042
|
+
alternatives: [
|
1043
|
+
{ name: "control_opt", percent: 67 },
|
1044
|
+
{ name: "second_opt", percent: 10 },
|
1045
|
+
{ name: "third_opt", percent: 23 },
|
1049
1046
|
],
|
1050
1047
|
}
|
1051
1048
|
ab_test :my_experiment
|
1052
1049
|
experiment = Split::Experiment.new(:my_experiment)
|
1053
|
-
expect(experiment.alternatives.collect{|a| [a.name, a.weight]}).to eq([[
|
1050
|
+
expect(experiment.alternatives.collect { |a| [a.name, a.weight] }).to eq([["control_opt", 0.67], ["second_opt", 0.1], ["third_opt", 0.23]])
|
1054
1051
|
end
|
1055
1052
|
|
1056
1053
|
it "accepts probability on some alternatives" do
|
1057
1054
|
Split.configuration.experiments[:my_experiment] = {
|
1058
|
-
:
|
1059
|
-
{ :
|
1055
|
+
alternatives: [
|
1056
|
+
{ name: "control_opt", percent: 34 },
|
1060
1057
|
"second_opt",
|
1061
|
-
{ :
|
1058
|
+
{ name: "third_opt", percent: 23 },
|
1062
1059
|
"fourth_opt",
|
1063
1060
|
],
|
1064
1061
|
}
|
1065
1062
|
ab_test :my_experiment
|
1066
1063
|
experiment = Split::Experiment.new(:my_experiment)
|
1067
|
-
names_and_weights = experiment.alternatives.collect{|a| [a.name, a.weight]}
|
1068
|
-
expect(names_and_weights).to eq([[
|
1069
|
-
expect(names_and_weights.inject(0){|sum, nw| sum + nw[1]}).to eq(1.0)
|
1064
|
+
names_and_weights = experiment.alternatives.collect { |a| [a.name, a.weight] }
|
1065
|
+
expect(names_and_weights).to eq([["control_opt", 0.34], ["second_opt", 0.215], ["third_opt", 0.23], ["fourth_opt", 0.215]])
|
1066
|
+
expect(names_and_weights.inject(0) { |sum, nw| sum + nw[1] }).to eq(1.0)
|
1070
1067
|
end
|
1071
1068
|
|
1072
1069
|
it "allows name param without probability" do
|
1073
1070
|
Split.configuration.experiments[:my_experiment] = {
|
1074
|
-
:
|
1075
|
-
{ :
|
1071
|
+
alternatives: [
|
1072
|
+
{ name: "control_opt" },
|
1076
1073
|
"second_opt",
|
1077
|
-
{ :
|
1074
|
+
{ name: "third_opt", percent: 64 },
|
1078
1075
|
],
|
1079
1076
|
}
|
1080
1077
|
ab_test :my_experiment
|
1081
1078
|
experiment = Split::Experiment.new(:my_experiment)
|
1082
|
-
names_and_weights = experiment.alternatives.collect{|a| [a.name, a.weight]}
|
1083
|
-
expect(names_and_weights).to eq([[
|
1084
|
-
expect(names_and_weights.inject(0){|sum, nw| sum + nw[1]}).to eq(1.0)
|
1079
|
+
names_and_weights = experiment.alternatives.collect { |a| [a.name, a.weight] }
|
1080
|
+
expect(names_and_weights).to eq([["control_opt", 0.18], ["second_opt", 0.18], ["third_opt", 0.64]])
|
1081
|
+
expect(names_and_weights.inject(0) { |sum, nw| sum + nw[1] }).to eq(1.0)
|
1085
1082
|
end
|
1086
1083
|
|
1087
1084
|
it "fails gracefully if config is missing experiment" do
|
1088
|
-
Split.configuration.experiments = { :
|
1089
|
-
expect
|
1085
|
+
Split.configuration.experiments = { other_experiment: { foo: "Bar" } }
|
1086
|
+
expect { ab_test :my_experiment }.to raise_error(Split::ExperimentNotFound)
|
1090
1087
|
end
|
1091
1088
|
|
1092
1089
|
it "fails gracefully if config is missing" do
|
1093
|
-
expect
|
1090
|
+
expect { Split.configuration.experiments = nil }.to raise_error(Split::InvalidExperimentsFormatError)
|
1094
1091
|
end
|
1095
1092
|
|
1096
1093
|
it "fails gracefully if config is missing alternatives" do
|
1097
|
-
Split.configuration.experiments[:my_experiment] = { :
|
1098
|
-
expect
|
1094
|
+
Split.configuration.experiments[:my_experiment] = { foo: "Bar" }
|
1095
|
+
expect { ab_test :my_experiment }.to raise_error(NoMethodError)
|
1099
1096
|
end
|
1100
1097
|
end
|
1101
1098
|
|
1102
|
-
it
|
1103
|
-
experiment2 = Split::ExperimentCatalog.find_or_create(
|
1104
|
-
ab_test(
|
1105
|
-
ab_test(
|
1106
|
-
ab_finished(
|
1099
|
+
it "should handle multiple experiments correctly" do
|
1100
|
+
experiment2 = Split::ExperimentCatalog.find_or_create("link_color2", "blue", "red")
|
1101
|
+
ab_test("link_color", "blue", "red")
|
1102
|
+
ab_test("link_color2", "blue", "red")
|
1103
|
+
ab_finished("link_color2")
|
1107
1104
|
|
1108
1105
|
experiment2.alternatives.each do |alt|
|
1109
1106
|
expect(alt.unfinished_count).to eq(0)
|
@@ -1112,8 +1109,8 @@ describe Split::Helper do
|
|
1112
1109
|
|
1113
1110
|
context "with goals" do
|
1114
1111
|
before do
|
1115
|
-
@experiment = {
|
1116
|
-
@alternatives = [
|
1112
|
+
@experiment = { "link_color" => ["purchase", "refund"] }
|
1113
|
+
@alternatives = ["blue", "red"]
|
1117
1114
|
@experiment_name, @goals = normalize_metric(@experiment)
|
1118
1115
|
@goal1 = @goals[0]
|
1119
1116
|
@goal2 = @goals[1]
|
@@ -1127,8 +1124,8 @@ describe Split::Helper do
|
|
1127
1124
|
describe "ab_test" do
|
1128
1125
|
it "should allow experiment goals interface as a single hash" do
|
1129
1126
|
ab_test(@experiment, *@alternatives)
|
1130
|
-
experiment = Split::ExperimentCatalog.find(
|
1131
|
-
expect(experiment.goals).to eq([
|
1127
|
+
experiment = Split::ExperimentCatalog.find("link_color")
|
1128
|
+
expect(experiment.goals).to eq(["purchase", "refund"])
|
1132
1129
|
end
|
1133
1130
|
end
|
1134
1131
|
|
@@ -1138,9 +1135,9 @@ describe Split::Helper do
|
|
1138
1135
|
end
|
1139
1136
|
|
1140
1137
|
it "should increment the counter for the specified-goal completed alternative" do
|
1141
|
-
expect{ ab_finished({"link_color" => ["purchase"]}) }
|
1142
|
-
.to change{ Split::Alternative.new(@alternative_name, @experiment_name).completed_count(@goal2) }.by(0)
|
1143
|
-
.and change{ Split::Alternative.new(@alternative_name, @experiment_name).completed_count(@goal1) }.by(1)
|
1138
|
+
expect { ab_finished({ "link_color" => ["purchase"] }) }
|
1139
|
+
.to change { Split::Alternative.new(@alternative_name, @experiment_name).completed_count(@goal2) }.by(0)
|
1140
|
+
.and change { Split::Alternative.new(@alternative_name, @experiment_name).completed_count(@goal1) }.by(1)
|
1144
1141
|
end
|
1145
1142
|
end
|
1146
1143
|
end
|