split 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +3 -22
- data/Appraisals +5 -9
- data/{CHANGELOG.mdown → CHANGELOG.md} +17 -0
- data/Gemfile +1 -1
- data/LICENSE +2 -2
- data/{README.mdown → README.md} +3 -14
- data/gemfiles/4.0.gemfile +1 -1
- data/gemfiles/{3.1.gemfile → 4.1.gemfile} +1 -1
- data/lib/split/alternative.rb +1 -1
- data/lib/split/dashboard.rb +6 -6
- data/lib/split/experiment.rb +2 -19
- data/lib/split/experiment_catalog.rb +20 -11
- data/lib/split/helper.rb +36 -99
- data/lib/split/metric.rb +2 -2
- data/lib/split/persistence/redis_adapter.rb +4 -2
- data/lib/split/trial.rb +84 -22
- data/lib/split/version.rb +1 -1
- data/spec/algorithms/weighted_sample_spec.rb +3 -3
- data/spec/algorithms/whiplash_spec.rb +2 -2
- data/spec/alternative_spec.rb +1 -1
- data/spec/dashboard_spec.rb +3 -3
- data/spec/encapsulated_helper_spec.rb +2 -6
- data/spec/experiment_catalog_spec.rb +37 -0
- data/spec/experiment_spec.rb +26 -26
- data/spec/helper_spec.rb +55 -20
- data/spec/metric_spec.rb +5 -5
- data/spec/persistence/redis_adapter_spec.rb +9 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/trial_spec.rb +126 -29
- data/split.gemspec +3 -3
- metadata +28 -30
- data/changes.rtf +0 -14
- data/gemfiles/3.0.gemfile +0 -8
data/lib/split/metric.rb
CHANGED
@@ -17,7 +17,7 @@ module Split
|
|
17
17
|
experiment_names = metric.split(',')
|
18
18
|
|
19
19
|
experiments = experiment_names.collect do |experiment_name|
|
20
|
-
Split::
|
20
|
+
Split::ExperimentCatalog.find(experiment_name)
|
21
21
|
end
|
22
22
|
|
23
23
|
Split::Metric.new(:name => name, :experiments => experiments)
|
@@ -67,7 +67,7 @@ module Split
|
|
67
67
|
if metric
|
68
68
|
experiments << metric.experiments
|
69
69
|
end
|
70
|
-
experiment = Split::
|
70
|
+
experiment = Split::ExperimentCatalog.find(metric_name)
|
71
71
|
if experiment
|
72
72
|
experiments << experiment
|
73
73
|
end
|
@@ -5,8 +5,10 @@ module Split
|
|
5
5
|
|
6
6
|
attr_reader :redis_key
|
7
7
|
|
8
|
-
def initialize(context)
|
9
|
-
if
|
8
|
+
def initialize(context, key = nil)
|
9
|
+
if key
|
10
|
+
@redis_key = "#{self.class.config[:namespace]}:#{key}"
|
11
|
+
elsif lookup_by = self.class.config[:lookup_by]
|
10
12
|
if lookup_by.respond_to?(:call)
|
11
13
|
key_frag = lookup_by.call(context)
|
12
14
|
else
|
data/lib/split/trial.rb
CHANGED
@@ -1,49 +1,111 @@
|
|
1
1
|
module Split
|
2
2
|
class Trial
|
3
3
|
attr_accessor :experiment
|
4
|
-
attr_accessor :goals
|
5
4
|
|
6
5
|
def initialize(attrs = {})
|
7
|
-
self.experiment
|
8
|
-
self.alternative
|
9
|
-
|
6
|
+
self.experiment = attrs.delete(:experiment)
|
7
|
+
self.alternative = attrs.delete(:alternative)
|
8
|
+
|
9
|
+
@user = attrs.delete(:user)
|
10
|
+
@options = attrs
|
11
|
+
|
12
|
+
@alternative_choosen = false
|
10
13
|
end
|
11
14
|
|
12
15
|
def alternative
|
13
|
-
@alternative ||= if experiment.has_winner?
|
14
|
-
experiment.winner
|
16
|
+
@alternative ||= if @experiment.has_winner?
|
17
|
+
@experiment.winner
|
15
18
|
end
|
16
19
|
end
|
17
20
|
|
18
|
-
def
|
21
|
+
def alternative=(alternative)
|
22
|
+
@alternative = if alternative.kind_of?(Split::Alternative)
|
23
|
+
alternative
|
24
|
+
else
|
25
|
+
@experiment.alternatives.find{|a| a.name == alternative }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def complete!(goals, context = nil)
|
30
|
+
goals = goals || []
|
31
|
+
|
19
32
|
if alternative
|
20
|
-
if
|
33
|
+
if goals.empty?
|
21
34
|
alternative.increment_completion
|
22
35
|
else
|
23
|
-
|
36
|
+
goals.each {|g| alternative.increment_completion(g) }
|
24
37
|
end
|
38
|
+
|
39
|
+
context.send(Split.configuration.on_trial_complete, self) \
|
40
|
+
if Split.configuration.on_trial_complete && context
|
25
41
|
end
|
26
42
|
end
|
27
43
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
44
|
+
# Choose an alternative, add a participant, and save the alternative choice on the user. This
|
45
|
+
# method is guaranteed to only run once, and will skip the alternative choosing process if run
|
46
|
+
# a second time.
|
47
|
+
def choose!(context = nil)
|
48
|
+
# Only run the process once
|
49
|
+
return alternative if @alternative_choosen
|
32
50
|
|
33
|
-
|
34
|
-
|
35
|
-
|
51
|
+
if @options[:override]
|
52
|
+
self.alternative = @options[:override]
|
53
|
+
elsif @options[:disabled] || !Split.configuration.enabled
|
54
|
+
self.alternative = @experiment.control
|
55
|
+
elsif @experiment.has_winner?
|
56
|
+
self.alternative = @experiment.winner
|
57
|
+
else
|
58
|
+
cleanup_old_versions
|
59
|
+
|
60
|
+
if exclude_user?
|
61
|
+
self.alternative = @experiment.control
|
62
|
+
elsif @user[@experiment.key]
|
63
|
+
self.alternative = @user[@experiment.key]
|
64
|
+
else
|
65
|
+
self.alternative = @experiment.next_alternative
|
66
|
+
|
67
|
+
# Increment the number of participants since we are actually choosing a new alternative
|
68
|
+
self.alternative.increment_participation
|
36
69
|
|
37
|
-
|
38
|
-
|
70
|
+
# Run the post-choosing hook on the context
|
71
|
+
context.send(Split.configuration.on_trial_choose, self) \
|
72
|
+
if Split.configuration.on_trial_choose && context
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
@user[@experiment.key] = alternative.name if should_store_alternative?
|
77
|
+
@alternative_choosen = true
|
78
|
+
alternative
|
39
79
|
end
|
40
80
|
|
41
|
-
|
42
|
-
|
43
|
-
|
81
|
+
private
|
82
|
+
|
83
|
+
def should_store_alternative?
|
84
|
+
if @options[:override] || @options[:disabled]
|
85
|
+
Split.configuration.store_override
|
44
86
|
else
|
45
|
-
|
87
|
+
!exclude_user?
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def cleanup_old_versions
|
92
|
+
if @experiment.version > 0
|
93
|
+
keys = @user.keys.select { |k| k.match(Regexp.new(@experiment.name)) }
|
94
|
+
keys_without_experiment(keys).each { |key| @user.delete(key) }
|
46
95
|
end
|
47
96
|
end
|
97
|
+
|
98
|
+
def exclude_user?
|
99
|
+
@options[:exclude] || @experiment.start_time.nil? || max_experiments_reached?
|
100
|
+
end
|
101
|
+
|
102
|
+
def max_experiments_reached?
|
103
|
+
!Split.configuration.allow_multiple_experiments &&
|
104
|
+
keys_without_experiment(@user.keys).length > 0
|
105
|
+
end
|
106
|
+
|
107
|
+
def keys_without_experiment(keys)
|
108
|
+
keys.reject { |k| k.match(Regexp.new("^#{@experiment.key}(:finished)?$")) }
|
109
|
+
end
|
48
110
|
end
|
49
111
|
end
|
data/lib/split/version.rb
CHANGED
@@ -2,17 +2,17 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Split::Algorithms::WeightedSample do
|
4
4
|
it "should return an alternative" do
|
5
|
-
experiment = Split::
|
5
|
+
experiment = Split::ExperimentCatalog.find_or_create('link_color', {'blue' => 100}, {'red' => 0 })
|
6
6
|
expect(Split::Algorithms::WeightedSample.choose_alternative(experiment).class).to eq(Split::Alternative)
|
7
7
|
end
|
8
8
|
|
9
9
|
it "should always return a heavily weighted option" do
|
10
|
-
experiment = Split::
|
10
|
+
experiment = Split::ExperimentCatalog.find_or_create('link_color', {'blue' => 100}, {'red' => 0 })
|
11
11
|
expect(Split::Algorithms::WeightedSample.choose_alternative(experiment).name).to eq('blue')
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should return one of the results" do
|
15
|
-
experiment = Split::
|
15
|
+
experiment = Split::ExperimentCatalog.find_or_create('link_color', {'blue' => 1}, {'red' => 1 })
|
16
16
|
expect(['red', 'blue']).to include Split::Algorithms::WeightedSample.choose_alternative(experiment).name
|
17
17
|
end
|
18
18
|
end
|
@@ -3,12 +3,12 @@ require "spec_helper"
|
|
3
3
|
describe Split::Algorithms::Whiplash do
|
4
4
|
|
5
5
|
it "should return an algorithm" do
|
6
|
-
experiment = Split::
|
6
|
+
experiment = Split::ExperimentCatalog.find_or_create('link_color', {'blue' => 1}, {'red' => 1 })
|
7
7
|
expect(Split::Algorithms::Whiplash.choose_alternative(experiment).class).to eq(Split::Alternative)
|
8
8
|
end
|
9
9
|
|
10
10
|
it "should return one of the results" do
|
11
|
-
experiment = Split::
|
11
|
+
experiment = Split::ExperimentCatalog.find_or_create('link_color', {'blue' => 1}, {'red' => 1 })
|
12
12
|
expect(['red', 'blue']).to include Split::Algorithms::Whiplash.choose_alternative(experiment).name
|
13
13
|
end
|
14
14
|
|
data/spec/alternative_spec.rb
CHANGED
@@ -12,7 +12,7 @@ describe Split::Alternative do
|
|
12
12
|
}
|
13
13
|
|
14
14
|
let!(:experiment) {
|
15
|
-
Split::
|
15
|
+
Split::ExperimentCatalog.find_or_create({"basket_text" => ["purchase", "refund"]}, "Basket", "Cart")
|
16
16
|
}
|
17
17
|
|
18
18
|
let(:goal1) { "purchase" }
|
data/spec/dashboard_spec.rb
CHANGED
@@ -14,11 +14,11 @@ describe Split::Dashboard do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
let(:experiment) {
|
17
|
-
Split::
|
17
|
+
Split::ExperimentCatalog.find_or_create("link_color", "blue", "red")
|
18
18
|
}
|
19
19
|
|
20
20
|
let(:experiment_with_goals) {
|
21
|
-
Split::
|
21
|
+
Split::ExperimentCatalog.find_or_create({"link_color" => ["goal_1", "goal_2"]}, "blue", "red")
|
22
22
|
}
|
23
23
|
|
24
24
|
let(:metric) {
|
@@ -139,7 +139,7 @@ describe Split::Dashboard do
|
|
139
139
|
it "should delete an experiment" do
|
140
140
|
delete "/#{experiment.name}"
|
141
141
|
expect(last_response).to be_redirect
|
142
|
-
expect(Split::
|
142
|
+
expect(Split::ExperimentCatalog.find(experiment.name)).to be_nil
|
143
143
|
end
|
144
144
|
|
145
145
|
it "should mark an alternative as the winner" do
|
@@ -4,12 +4,8 @@ describe Split::EncapsulatedHelper do
|
|
4
4
|
include Split::EncapsulatedHelper
|
5
5
|
|
6
6
|
before do
|
7
|
-
|
8
|
-
|
9
|
-
end
|
10
|
-
|
11
|
-
after do
|
12
|
-
Split.configuration.persistence = @persistence_adapter
|
7
|
+
allow_any_instance_of(Split::EncapsulatedHelper::ContextShim).to receive(:ab_user)
|
8
|
+
.and_return({})
|
13
9
|
end
|
14
10
|
|
15
11
|
def params
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Split::ExperimentCatalog do
|
4
|
+
subject { Split::ExperimentCatalog }
|
5
|
+
|
6
|
+
describe ".find_or_create" do
|
7
|
+
it "should not raise an error when passed strings for alternatives" do
|
8
|
+
expect { subject.find_or_create('xyz', '1', '2', '3') }.not_to raise_error
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should not raise an error when passed an array for alternatives" do
|
12
|
+
expect { subject.find_or_create('xyz', ['1', '2', '3']) }.not_to raise_error
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should raise the appropriate error when passed integers for alternatives" do
|
16
|
+
expect { subject.find_or_create('xyz', 1, 2, 3) }.to raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should raise the appropriate error when passed symbols for alternatives" do
|
20
|
+
expect { subject.find_or_create('xyz', :a, :b, :c) }.to raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should not raise error when passed an array for goals" do
|
24
|
+
expect { subject.find_or_create({'link_color' => ["purchase", "refund"]}, 'blue', 'red') }
|
25
|
+
.not_to raise_error
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should not raise error when passed just one goal" do
|
29
|
+
expect { subject.find_or_create({'link_color' => "purchase"}, 'blue', 'red') }
|
30
|
+
.not_to raise_error
|
31
|
+
end
|
32
|
+
|
33
|
+
it "constructs a new experiment" do
|
34
|
+
expect(subject.find_or_create('my_exp', 'control me').control.to_s).to eq('control me')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/spec/experiment_spec.rb
CHANGED
@@ -48,14 +48,14 @@ describe Split::Experiment do
|
|
48
48
|
expect(Time).to receive(:now).and_return(experiment_start_time)
|
49
49
|
experiment.save
|
50
50
|
|
51
|
-
expect(Split::
|
51
|
+
expect(Split::ExperimentCatalog.find('basket_text').start_time).to eq(experiment_start_time)
|
52
52
|
end
|
53
53
|
|
54
54
|
it "should not save the start time to redis when start_manually is enabled" do
|
55
55
|
expect(Split.configuration).to receive(:start_manually).and_return(true)
|
56
56
|
experiment.save
|
57
57
|
|
58
|
-
expect(Split::
|
58
|
+
expect(Split::ExperimentCatalog.find('basket_text').start_time).to be_nil
|
59
59
|
end
|
60
60
|
|
61
61
|
it "should save the selected algorithm to redis" do
|
@@ -63,7 +63,7 @@ describe Split::Experiment do
|
|
63
63
|
experiment.algorithm = experiment_algorithm
|
64
64
|
experiment.save
|
65
65
|
|
66
|
-
expect(Split::
|
66
|
+
expect(Split::ExperimentCatalog.find('basket_text').algorithm).to eq(experiment_algorithm)
|
67
67
|
end
|
68
68
|
|
69
69
|
it "should handle having a start time stored as a string" do
|
@@ -72,7 +72,7 @@ describe Split::Experiment do
|
|
72
72
|
experiment.save
|
73
73
|
Split.redis.hset(:experiment_start_times, experiment.name, experiment_start_time)
|
74
74
|
|
75
|
-
expect(Split::
|
75
|
+
expect(Split::ExperimentCatalog.find('basket_text').start_time).to eq(experiment_start_time)
|
76
76
|
end
|
77
77
|
|
78
78
|
it "should handle not having a start time" do
|
@@ -82,7 +82,7 @@ describe Split::Experiment do
|
|
82
82
|
|
83
83
|
Split.redis.hdel(:experiment_start_times, experiment.name)
|
84
84
|
|
85
|
-
expect(Split::
|
85
|
+
expect(Split::ExperimentCatalog.find('basket_text').start_time).to be_nil
|
86
86
|
end
|
87
87
|
|
88
88
|
it "should not create duplicates when saving multiple times" do
|
@@ -106,12 +106,12 @@ describe Split::Experiment do
|
|
106
106
|
describe 'find' do
|
107
107
|
it "should return an existing experiment" do
|
108
108
|
experiment.save
|
109
|
-
experiment = Split::
|
109
|
+
experiment = Split::ExperimentCatalog.find('basket_text')
|
110
110
|
expect(experiment.name).to eq('basket_text')
|
111
111
|
end
|
112
112
|
|
113
113
|
it "should return an existing experiment" do
|
114
|
-
expect(Split::
|
114
|
+
expect(Split::ExperimentCatalog.find('non_existent_experiment')).to be_nil
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
@@ -141,7 +141,7 @@ describe Split::Experiment do
|
|
141
141
|
experiment = Split::Experiment.new('basket_text', :alternatives => ['Basket', "Cart"], :resettable => false)
|
142
142
|
experiment.save
|
143
143
|
|
144
|
-
e = Split::
|
144
|
+
e = Split::ExperimentCatalog.find('basket_text')
|
145
145
|
expect(e).to eq(experiment)
|
146
146
|
expect(e.resettable).to be_falsey
|
147
147
|
|
@@ -151,7 +151,7 @@ describe Split::Experiment do
|
|
151
151
|
experiment = Split::Experiment.new('basket_text', :alternatives => ['Basket', "Cart"], :algorithm => Split::Algorithms::Whiplash)
|
152
152
|
experiment.save
|
153
153
|
|
154
|
-
e = Split::
|
154
|
+
e = Split::ExperimentCatalog.find('basket_text')
|
155
155
|
expect(e).to eq(experiment)
|
156
156
|
expect(e.algorithm).to eq(Split::Algorithms::Whiplash)
|
157
157
|
end
|
@@ -160,7 +160,7 @@ describe Split::Experiment do
|
|
160
160
|
experiment = Split::Experiment.new('foobar', :alternatives => ['tra', 'la'], :algorithm => Split::Algorithms::Whiplash)
|
161
161
|
experiment.save
|
162
162
|
|
163
|
-
e = Split::
|
163
|
+
e = Split::ExperimentCatalog.find('foobar')
|
164
164
|
expect(e).to eq(experiment)
|
165
165
|
expect(e.alternatives.collect{|a| a.name}).to eq(['tra', 'la'])
|
166
166
|
end
|
@@ -173,7 +173,7 @@ describe Split::Experiment do
|
|
173
173
|
|
174
174
|
experiment.delete
|
175
175
|
expect(Split.redis.exists('link_color')).to be false
|
176
|
-
expect(Split::
|
176
|
+
expect(Split::ExperimentCatalog.find('link_color')).to be_nil
|
177
177
|
end
|
178
178
|
|
179
179
|
it "should increment the version" do
|
@@ -255,7 +255,7 @@ describe Split::Experiment do
|
|
255
255
|
end
|
256
256
|
|
257
257
|
describe 'algorithm' do
|
258
|
-
let(:experiment) { Split::
|
258
|
+
let(:experiment) { Split::ExperimentCatalog.find_or_create('link_color', 'blue', 'red', 'green') }
|
259
259
|
|
260
260
|
it 'should use the default algorithm if none is specified' do
|
261
261
|
expect(experiment.algorithm).to eq(Split.configuration.algorithm)
|
@@ -268,7 +268,7 @@ describe Split::Experiment do
|
|
268
268
|
end
|
269
269
|
|
270
270
|
describe 'next_alternative' do
|
271
|
-
let(:experiment) { Split::
|
271
|
+
let(:experiment) { Split::ExperimentCatalog.find_or_create('link_color', 'blue', 'red', 'green') }
|
272
272
|
|
273
273
|
it "should always return the winner if one exists" do
|
274
274
|
green = Split::Alternative.new('green', 'link_color')
|
@@ -288,7 +288,7 @@ describe Split::Experiment do
|
|
288
288
|
end
|
289
289
|
|
290
290
|
describe 'single alternative' do
|
291
|
-
let(:experiment) { Split::
|
291
|
+
let(:experiment) { Split::ExperimentCatalog.find_or_create('link_color', 'blue') }
|
292
292
|
|
293
293
|
it "should always return the color blue" do
|
294
294
|
expect(experiment.next_alternative.name).to eq('blue')
|
@@ -297,7 +297,7 @@ describe Split::Experiment do
|
|
297
297
|
|
298
298
|
describe 'changing an existing experiment' do
|
299
299
|
def same_but_different_alternative
|
300
|
-
Split::
|
300
|
+
Split::ExperimentCatalog.find_or_create('link_color', 'blue', 'yellow', 'orange')
|
301
301
|
end
|
302
302
|
|
303
303
|
it "should reset an experiment if it is loaded with different alternatives" do
|
@@ -320,14 +320,14 @@ describe Split::Experiment do
|
|
320
320
|
|
321
321
|
describe 'alternatives passed as non-strings' do
|
322
322
|
it "should throw an exception if an alternative is passed that is not a string" do
|
323
|
-
expect(lambda { Split::
|
324
|
-
expect(lambda { Split::
|
323
|
+
expect(lambda { Split::ExperimentCatalog.find_or_create('link_color', :blue, :red) }).to raise_error
|
324
|
+
expect(lambda { Split::ExperimentCatalog.find_or_create('link_enabled', true, false) }).to raise_error
|
325
325
|
end
|
326
326
|
end
|
327
327
|
|
328
328
|
describe 'specifying weights' do
|
329
329
|
let(:experiment_with_weight) {
|
330
|
-
Split::
|
330
|
+
Split::ExperimentCatalog.find_or_create('link_color', {'blue' => 1}, {'red' => 2 })
|
331
331
|
}
|
332
332
|
|
333
333
|
it "should work for a new experiment" do
|
@@ -347,18 +347,18 @@ describe Split::Experiment do
|
|
347
347
|
|
348
348
|
context "saving experiment" do
|
349
349
|
def same_but_different_goals
|
350
|
-
Split::
|
350
|
+
Split::ExperimentCatalog.find_or_create({'link_color' => ["purchase", "refund"]}, 'blue', 'red', 'green')
|
351
351
|
end
|
352
352
|
|
353
353
|
before { experiment.save }
|
354
354
|
|
355
355
|
it "can find existing experiment" do
|
356
|
-
expect(Split::
|
356
|
+
expect(Split::ExperimentCatalog.find("link_color").name).to eq("link_color")
|
357
357
|
end
|
358
358
|
|
359
359
|
it "should reset an experiment if it is loaded with different goals" do
|
360
360
|
same_experiment = same_but_different_goals
|
361
|
-
expect(Split::
|
361
|
+
expect(Split::ExperimentCatalog.find("link_color").goals).to eq(["purchase", "refund"])
|
362
362
|
end
|
363
363
|
|
364
364
|
end
|
@@ -369,9 +369,9 @@ describe Split::Experiment do
|
|
369
369
|
|
370
370
|
context "find or create experiment" do
|
371
371
|
it "should have correct goals" do
|
372
|
-
experiment = Split::
|
372
|
+
experiment = Split::ExperimentCatalog.find_or_create({'link_color3' => ["purchase", "refund"]}, 'blue', 'red', 'green')
|
373
373
|
expect(experiment.goals).to eq(["purchase", "refund"])
|
374
|
-
experiment = Split::
|
374
|
+
experiment = Split::ExperimentCatalog.find_or_create('link_color3', 'blue', 'red', 'green')
|
375
375
|
expect(experiment.goals).to eq([])
|
376
376
|
end
|
377
377
|
end
|
@@ -379,19 +379,19 @@ describe Split::Experiment do
|
|
379
379
|
|
380
380
|
describe "beta probability calculation" do
|
381
381
|
it "should return a hash with the probability of each alternative being the best" do
|
382
|
-
experiment = Split::
|
382
|
+
experiment = Split::ExperimentCatalog.find_or_create('mathematicians', 'bernoulli', 'poisson', 'lagrange')
|
383
383
|
experiment.calc_winning_alternatives
|
384
384
|
expect(experiment.alternative_probabilities).not_to be_nil
|
385
385
|
end
|
386
386
|
|
387
387
|
it "should return between 46% and 54% probability for an experiment with 2 alternatives and no data" do
|
388
|
-
experiment = Split::
|
388
|
+
experiment = Split::ExperimentCatalog.find_or_create('scientists', 'einstein', 'bohr')
|
389
389
|
experiment.calc_winning_alternatives
|
390
390
|
expect(experiment.alternatives[0].p_winner).to be_within(0.04).of(0.50)
|
391
391
|
end
|
392
392
|
|
393
393
|
it "should calculate the probability of being the winning alternative separately for each goal" do
|
394
|
-
experiment = Split::
|
394
|
+
experiment = Split::ExperimentCatalog.find_or_create({'link_color3' => ["purchase", "refund"]}, 'blue', 'red', 'green')
|
395
395
|
goal1 = experiment.goals[0]
|
396
396
|
goal2 = experiment.goals[1]
|
397
397
|
experiment.alternatives.each do |alternative|
|