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/spec/helper_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe Split::Helper do
|
|
6
6
|
include Split::Helper
|
7
7
|
|
8
8
|
let(:experiment) {
|
9
|
-
Split::
|
9
|
+
Split::ExperimentCatalog.find_or_create('link_color', 'blue', 'red')
|
10
10
|
}
|
11
11
|
|
12
12
|
describe "ab_test" do
|
@@ -53,7 +53,7 @@ describe Split::Helper do
|
|
53
53
|
|
54
54
|
it 'should not increment the counter for an experiment that the user is not participating in' do
|
55
55
|
ab_test('link_color', 'blue', 'red')
|
56
|
-
e = Split::
|
56
|
+
e = Split::ExperimentCatalog.find_or_create('button_size', 'small', 'big')
|
57
57
|
expect(lambda {
|
58
58
|
# User shouldn't participate in this second experiment
|
59
59
|
ab_test('button_size', 'small', 'big')
|
@@ -61,7 +61,7 @@ describe Split::Helper do
|
|
61
61
|
end
|
62
62
|
|
63
63
|
it 'should not increment the counter for an ended experiment' do
|
64
|
-
e = Split::
|
64
|
+
e = Split::ExperimentCatalog.find_or_create('button_size', 'small', 'big')
|
65
65
|
e.winner = 'small'
|
66
66
|
expect(lambda {
|
67
67
|
a = ab_test('button_size', 'small', 'big')
|
@@ -71,7 +71,7 @@ describe Split::Helper do
|
|
71
71
|
|
72
72
|
it 'should not increment the counter for an not started experiment' do
|
73
73
|
expect(Split.configuration).to receive(:start_manually).and_return(true)
|
74
|
-
e = Split::
|
74
|
+
e = Split::ExperimentCatalog.find_or_create('button_size', 'small', 'big')
|
75
75
|
expect(lambda {
|
76
76
|
a = ab_test('button_size', 'small', 'big')
|
77
77
|
expect(a).to eq('small')
|
@@ -162,7 +162,7 @@ describe Split::Helper do
|
|
162
162
|
|
163
163
|
it "should allow alternative weighting interface as a single hash" do
|
164
164
|
ab_test('link_color', {'blue' => 0.01}, 'red' => 0.2)
|
165
|
-
experiment = Split::
|
165
|
+
experiment = Split::ExperimentCatalog.find('link_color')
|
166
166
|
expect(experiment.alternatives.map(&:name)).to eq(['blue', 'red'])
|
167
167
|
# TODO: persist alternative weights
|
168
168
|
# expect(experiment.alternatives.collect{|a| a.weight}).to eq([0.01, 0.2])
|
@@ -202,7 +202,7 @@ describe Split::Helper do
|
|
202
202
|
before(:each) do
|
203
203
|
@experiment_name = 'link_color'
|
204
204
|
@alternatives = ['blue', 'red']
|
205
|
-
@experiment = Split::
|
205
|
+
@experiment = Split::ExperimentCatalog.find_or_create(@experiment_name, *@alternatives)
|
206
206
|
@alternative_name = ab_test(@experiment_name, *@alternatives)
|
207
207
|
@previous_completion_count = Split::Alternative.new(@alternative_name, @experiment_name).completed_count
|
208
208
|
end
|
@@ -237,7 +237,7 @@ describe Split::Helper do
|
|
237
237
|
end
|
238
238
|
|
239
239
|
it 'should not increment the counter for an ended experiment' do
|
240
|
-
e = Split::
|
240
|
+
e = Split::ExperimentCatalog.find_or_create('button_size', 'small', 'big')
|
241
241
|
e.winner = 'small'
|
242
242
|
a = ab_test('button_size', 'small', 'big')
|
243
243
|
expect(a).to eq('small')
|
@@ -278,12 +278,6 @@ describe Split::Helper do
|
|
278
278
|
expect(lambda { finished('some_experiment_not_started_by_the_user') }).not_to raise_exception
|
279
279
|
end
|
280
280
|
|
281
|
-
it 'should not be doing other tests when it has completed one that has :reset => false' do
|
282
|
-
ab_user[@experiment.key] = @alternative_name
|
283
|
-
ab_user[@experiment.finished_key] = true
|
284
|
-
expect(doing_other_tests?(@experiment.key)).to be false
|
285
|
-
end
|
286
|
-
|
287
281
|
context "when on_trial_complete is set" do
|
288
282
|
before { Split.configuration.on_trial_complete = :some_method }
|
289
283
|
it "should call the method" do
|
@@ -308,7 +302,7 @@ describe Split::Helper do
|
|
308
302
|
}
|
309
303
|
}
|
310
304
|
alternative = ab_test(:my_experiment)
|
311
|
-
experiment = Split::
|
305
|
+
experiment = Split::ExperimentCatalog.find :my_experiment
|
312
306
|
|
313
307
|
finished :my_experiment
|
314
308
|
expect(ab_user).to eq(experiment.key => alternative, experiment.finished_key => true)
|
@@ -321,7 +315,7 @@ describe Split::Helper do
|
|
321
315
|
|
322
316
|
def should_finish_experiment(experiment_name, should_finish=true)
|
323
317
|
alts = Split.configuration.experiments[experiment_name][:alternatives]
|
324
|
-
experiment = Split::
|
318
|
+
experiment = Split::ExperimentCatalog.find_or_create(experiment_name, *alts)
|
325
319
|
alt_name = ab_user[experiment.key] = alts.first
|
326
320
|
alt = double('alternative')
|
327
321
|
expect(alt).to receive(:name).at_most(1).times.and_return(alt_name)
|
@@ -372,7 +366,7 @@ describe Split::Helper do
|
|
372
366
|
}
|
373
367
|
}
|
374
368
|
alternative_name = ab_test(:my_exp)
|
375
|
-
exp = Split::
|
369
|
+
exp = Split::ExperimentCatalog.find :my_exp
|
376
370
|
|
377
371
|
finished :my_metric
|
378
372
|
expect(ab_user[exp.key]).to eq(alternative_name)
|
@@ -387,7 +381,7 @@ describe Split::Helper do
|
|
387
381
|
}
|
388
382
|
}
|
389
383
|
alternative_name = ab_test(:my_exp)
|
390
|
-
exp = Split::
|
384
|
+
exp = Split::ExperimentCatalog.find :my_exp
|
391
385
|
|
392
386
|
finished :my_metric, :reset => false
|
393
387
|
expect(ab_user[exp.key]).to eq(alternative_name)
|
@@ -409,6 +403,47 @@ describe Split::Helper do
|
|
409
403
|
end
|
410
404
|
end
|
411
405
|
|
406
|
+
describe 'active experiments' do
|
407
|
+
it 'should show an active test' do
|
408
|
+
alternative = ab_test('def', '4', '5', '6')
|
409
|
+
expect(active_experiments.count).to eq 1
|
410
|
+
expect(active_experiments.first[0]).to eq "def"
|
411
|
+
expect(active_experiments.first[1]).to eq alternative
|
412
|
+
end
|
413
|
+
|
414
|
+
it 'should show a finished test' do
|
415
|
+
alternative = ab_test('def', '4', '5', '6')
|
416
|
+
finished('def', {:reset => false})
|
417
|
+
expect(active_experiments.count).to eq 1
|
418
|
+
expect(active_experiments.first[0]).to eq "def"
|
419
|
+
expect(active_experiments.first[1]).to eq alternative
|
420
|
+
end
|
421
|
+
|
422
|
+
it 'should show multiple tests' do
|
423
|
+
Split.configure do |config|
|
424
|
+
config.allow_multiple_experiments = true
|
425
|
+
end
|
426
|
+
alternative = ab_test('def', '4', '5', '6')
|
427
|
+
another_alternative = ab_test('ghi', '7', '8', '9')
|
428
|
+
expect(active_experiments.count).to eq 2
|
429
|
+
expect(active_experiments['def']).to eq alternative
|
430
|
+
expect(active_experiments['ghi']).to eq another_alternative
|
431
|
+
end
|
432
|
+
|
433
|
+
it 'should not show tests with winners' do
|
434
|
+
Split.configure do |config|
|
435
|
+
config.allow_multiple_experiments = true
|
436
|
+
end
|
437
|
+
e = Split::ExperimentCatalog.find_or_create('def', '4', '5', '6')
|
438
|
+
e.winner = '4'
|
439
|
+
alternative = ab_test('def', '4', '5', '6')
|
440
|
+
another_alternative = ab_test('ghi', '7', '8', '9')
|
441
|
+
expect(active_experiments.count).to eq 1
|
442
|
+
expect(active_experiments.first[0]).to eq "ghi"
|
443
|
+
expect(active_experiments.first[1]).to eq another_alternative
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
412
447
|
describe 'when user is a robot' do
|
413
448
|
before(:each) do
|
414
449
|
@request = OpenStruct.new(:user_agent => 'Googlebot/2.1 (+http://www.google.com/bot.html)')
|
@@ -847,7 +882,7 @@ describe Split::Helper do
|
|
847
882
|
end
|
848
883
|
|
849
884
|
it 'should handle multiple experiments correctly' do
|
850
|
-
experiment2 = Split::
|
885
|
+
experiment2 = Split::ExperimentCatalog.find_or_create('link_color2', 'blue', 'red')
|
851
886
|
alternative_name = ab_test('link_color', 'blue', 'red')
|
852
887
|
alternative_name2 = ab_test('link_color2', 'blue', 'red')
|
853
888
|
finished('link_color2')
|
@@ -861,7 +896,7 @@ describe Split::Helper do
|
|
861
896
|
before do
|
862
897
|
@experiment = {'link_color' => ["purchase", "refund"]}
|
863
898
|
@alternatives = ['blue', 'red']
|
864
|
-
@experiment_name, @goals =
|
899
|
+
@experiment_name, @goals = normalize_metric(@experiment)
|
865
900
|
@goal1 = @goals[0]
|
866
901
|
@goal2 = @goals[1]
|
867
902
|
end
|
@@ -874,7 +909,7 @@ describe Split::Helper do
|
|
874
909
|
describe "ab_test" do
|
875
910
|
it "should allow experiment goals interface as a single hash" do
|
876
911
|
ab_test(@experiment, *@alternatives)
|
877
|
-
experiment = Split::
|
912
|
+
experiment = Split::ExperimentCatalog.find('link_color')
|
878
913
|
expect(experiment.goals).to eq(['purchase', "refund"])
|
879
914
|
end
|
880
915
|
end
|
data/spec/metric_spec.rb
CHANGED
@@ -4,13 +4,13 @@ require 'split/metric'
|
|
4
4
|
describe Split::Metric do
|
5
5
|
describe 'possible experiments' do
|
6
6
|
it "should load the experiment if there is one, but no metric" do
|
7
|
-
experiment = Split::
|
7
|
+
experiment = Split::ExperimentCatalog.find_or_create('color', 'red', 'blue')
|
8
8
|
expect(Split::Metric.possible_experiments('color')).to eq([experiment])
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should load the experiments in a metric" do
|
12
|
-
experiment1 = Split::
|
13
|
-
experiment2 = Split::
|
12
|
+
experiment1 = Split::ExperimentCatalog.find_or_create('color', 'red', 'blue')
|
13
|
+
experiment2 = Split::ExperimentCatalog.find_or_create('size', 'big', 'small')
|
14
14
|
|
15
15
|
metric = Split::Metric.new(:name => 'purchase', :experiments => [experiment1, experiment2])
|
16
16
|
metric.save
|
@@ -18,8 +18,8 @@ describe Split::Metric do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should load both the metric experiments and an experiment with the same name" do
|
21
|
-
experiment1 = Split::
|
22
|
-
experiment2 = Split::
|
21
|
+
experiment1 = Split::ExperimentCatalog.find_or_create('purchase', 'red', 'blue')
|
22
|
+
experiment2 = Split::ExperimentCatalog.find_or_create('size', 'big', 'small')
|
23
23
|
|
24
24
|
metric = Split::Metric.new(:name => 'purchase', :experiments => [experiment2])
|
25
25
|
metric.save
|
@@ -16,6 +16,15 @@ describe Split::Persistence::RedisAdapter do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
context 'config with key' do
|
20
|
+
before { Split::Persistence::RedisAdapter.reset_config! }
|
21
|
+
subject { Split::Persistence::RedisAdapter.new(context, 'manual') }
|
22
|
+
|
23
|
+
it 'should be "persistence:manual"' do
|
24
|
+
expect(subject.redis_key).to eq('persistence:manual')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
19
28
|
context 'config with lookup_by = proc { "block" }' do
|
20
29
|
before { Split::Persistence::RedisAdapter.with_config(:lookup_by => proc{'block'}) }
|
21
30
|
|
data/spec/spec_helper.rb
CHANGED
data/spec/trial_spec.rb
CHANGED
@@ -2,61 +2,158 @@ require 'spec_helper'
|
|
2
2
|
require 'split/trial'
|
3
3
|
|
4
4
|
describe Split::Trial do
|
5
|
+
let(:user) { Split::Persistence.adapter.new(double(session: {})) }
|
6
|
+
let(:experiment) do
|
7
|
+
Split::Experiment.new('basket_text', :alternatives => ['basket', 'cart']).save
|
8
|
+
end
|
9
|
+
|
5
10
|
it "should be initializeable" do
|
6
11
|
experiment = double('experiment')
|
7
12
|
alternative = double('alternative', :kind_of? => Split::Alternative)
|
8
13
|
trial = Split::Trial.new(:experiment => experiment, :alternative => alternative)
|
9
14
|
expect(trial.experiment).to eq(experiment)
|
10
15
|
expect(trial.alternative).to eq(alternative)
|
11
|
-
expect(trial.goals).to eq([])
|
12
16
|
end
|
13
17
|
|
14
18
|
describe "alternative" do
|
15
19
|
it "should use the alternative if specified" do
|
16
20
|
alternative = double('alternative', :kind_of? => Split::Alternative)
|
17
|
-
trial = Split::Trial.new(:experiment => experiment = double('experiment'),
|
21
|
+
trial = Split::Trial.new(:experiment => experiment = double('experiment'),
|
22
|
+
:alternative => alternative, :user => user)
|
18
23
|
expect(trial).not_to receive(:choose)
|
19
24
|
expect(trial.alternative).to eq(alternative)
|
20
25
|
end
|
21
26
|
|
22
|
-
it "should
|
27
|
+
it "should load the alternative when the alternative name is set" do
|
23
28
|
experiment = Split::Experiment.new('basket_text', :alternatives => ['basket', 'cart'])
|
24
29
|
experiment.save
|
25
|
-
trial = Split::Trial.new(:experiment => experiment)
|
26
|
-
trial.choose
|
27
|
-
expect(trial.alternative.class).to eq(Split::Alternative)
|
28
|
-
expect(['basket', 'cart']).to include(trial.alternative.name)
|
29
|
-
end
|
30
30
|
|
31
|
-
|
32
|
-
experiment = Split::Experiment.new('basket_text', :alternatives => ['basket'])
|
33
|
-
experiment.save
|
34
|
-
trial = Split::Trial.new(:experiment => experiment)
|
35
|
-
trial.choose
|
36
|
-
expect(trial.alternative.class).to eq(Split::Alternative)
|
31
|
+
trial = Split::Trial.new(:experiment => experiment, :alternative => 'basket')
|
37
32
|
expect(trial.alternative.name).to eq('basket')
|
38
33
|
end
|
34
|
+
end
|
39
35
|
|
36
|
+
describe "#choose!" do
|
37
|
+
def expect_alternative(trial, alternative_name)
|
38
|
+
3.times do
|
39
|
+
trial.choose!
|
40
|
+
expect(trial.alternative.name).to eq(alternative_name)
|
41
|
+
end
|
42
|
+
end
|
40
43
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
expect(alternative).to receive(:increment_participation)
|
46
|
-
expect(experiment).to receive(:winner).at_most(1).times.and_return(nil)
|
47
|
-
trial.choose!
|
44
|
+
context "when override is present" do
|
45
|
+
it "picks the override" do
|
46
|
+
trial = Split::Trial.new(:user => user, :experiment => experiment, :override => 'cart')
|
47
|
+
expect(experiment).to_not receive(:next_alternative)
|
48
48
|
|
49
|
-
|
49
|
+
expect_alternative(trial, 'cart')
|
50
|
+
end
|
50
51
|
end
|
51
|
-
end
|
52
52
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
53
|
+
context "when disabled option is true" do
|
54
|
+
it "picks the control" do
|
55
|
+
trial = Split::Trial.new(:user => user, :experiment => experiment, :disabled => true)
|
56
|
+
expect(experiment).to_not receive(:next_alternative)
|
57
57
|
|
58
|
-
|
59
|
-
|
58
|
+
expect_alternative(trial, 'basket')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when Split is globally disabled" do
|
63
|
+
it "picks the control" do
|
64
|
+
Split.configuration.enabled = false
|
65
|
+
trial = Split::Trial.new(:user => user, :experiment => experiment)
|
66
|
+
expect(experiment).to_not receive(:next_alternative)
|
67
|
+
|
68
|
+
expect_alternative(trial, 'basket')
|
69
|
+
Split.configuration.enabled = true
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "when experiment has winner" do
|
74
|
+
it "picks the winner" do
|
75
|
+
trial = Split::Trial.new(:user => user, :experiment => experiment)
|
76
|
+
experiment.winner = 'cart'
|
77
|
+
expect(experiment).to_not receive(:next_alternative)
|
78
|
+
|
79
|
+
expect_alternative(trial, 'cart')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "when exclude is true" do
|
84
|
+
it "picks the control" do
|
85
|
+
trial = Split::Trial.new(:user => user, :experiment => experiment, :exclude => true)
|
86
|
+
expect(experiment).to_not receive(:next_alternative)
|
87
|
+
|
88
|
+
expect_alternative(trial, 'basket')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context "when user is already participating" do
|
93
|
+
it "picks the same alternative" do
|
94
|
+
user[experiment.key] = 'basket'
|
95
|
+
trial = Split::Trial.new(:user => user, :experiment => experiment)
|
96
|
+
expect(experiment).to_not receive(:next_alternative)
|
97
|
+
|
98
|
+
expect_alternative(trial, 'basket')
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "when user is a new participant" do
|
103
|
+
it "picks a new alternative" do
|
104
|
+
trial = Split::Trial.new(:user => user, :experiment => experiment)
|
105
|
+
expect(experiment).to receive(:next_alternative).and_call_original
|
106
|
+
|
107
|
+
trial.choose!
|
108
|
+
expect(trial.alternative.name).to_not be_empty
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "alternative recording" do
|
113
|
+
before(:each) { Split.configuration.store_override = false }
|
114
|
+
|
115
|
+
context "when override is present" do
|
116
|
+
it "stores when store_override is true" do
|
117
|
+
trial = Split::Trial.new(:user => user, :experiment => experiment, :override => 'basket')
|
118
|
+
|
119
|
+
Split.configuration.store_override = true
|
120
|
+
expect(user).to receive("[]=")
|
121
|
+
trial.choose!
|
122
|
+
end
|
123
|
+
|
124
|
+
it "does not store when store_override is false" do
|
125
|
+
trial = Split::Trial.new(:user => user, :experiment => experiment, :override => 'basket')
|
126
|
+
|
127
|
+
expect(user).to_not receive("[]=")
|
128
|
+
trial.choose!
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context "when disabled is present" do
|
133
|
+
it "stores when store_override is true" do
|
134
|
+
trial = Split::Trial.new(:user => user, :experiment => experiment, :disabled => true)
|
135
|
+
|
136
|
+
Split.configuration.store_override = true
|
137
|
+
expect(user).to receive("[]=")
|
138
|
+
trial.choose!
|
139
|
+
end
|
140
|
+
|
141
|
+
it "does not store when store_override is false" do
|
142
|
+
trial = Split::Trial.new(:user => user, :experiment => experiment, :disabled => true)
|
143
|
+
|
144
|
+
expect(user).to_not receive("[]=")
|
145
|
+
trial.choose!
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context "when exclude is present" do
|
150
|
+
it "does not store" do
|
151
|
+
trial = Split::Trial.new(:user => user, :experiment => experiment, :exclude => true)
|
152
|
+
|
153
|
+
expect(user).to_not receive("[]=")
|
154
|
+
trial.choose!
|
155
|
+
end
|
156
|
+
end
|
60
157
|
end
|
61
158
|
end
|
62
159
|
end
|
data/split.gemspec
CHANGED
@@ -25,9 +25,9 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.add_dependency 'sinatra', '>= 1.2.6'
|
26
26
|
s.add_dependency 'simple-random'
|
27
27
|
|
28
|
-
s.add_development_dependency 'rake'
|
29
28
|
s.add_development_dependency 'bundler', '~> 1.6'
|
30
|
-
s.add_development_dependency 'rspec', '~> 3.0'
|
31
|
-
s.add_development_dependency 'rack-test'
|
32
29
|
s.add_development_dependency 'coveralls'
|
30
|
+
s.add_development_dependency 'rack-test'
|
31
|
+
s.add_development_dependency 'rake'
|
32
|
+
s.add_development_dependency 'rspec', '~> 3.0'
|
33
33
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: split
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Nesbitt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -66,20 +66,6 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: rake
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
70
|
name: bundler
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,19 +81,19 @@ dependencies:
|
|
95
81
|
- !ruby/object:Gem::Version
|
96
82
|
version: '1.6'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
84
|
+
name: coveralls
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
100
86
|
requirements:
|
101
|
-
- - "
|
87
|
+
- - ">="
|
102
88
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
89
|
+
version: '0'
|
104
90
|
type: :development
|
105
91
|
prerelease: false
|
106
92
|
version_requirements: !ruby/object:Gem::Requirement
|
107
93
|
requirements:
|
108
|
-
- - "
|
94
|
+
- - ">="
|
109
95
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
96
|
+
version: '0'
|
111
97
|
- !ruby/object:Gem::Dependency
|
112
98
|
name: rack-test
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,7 +109,7 @@ dependencies:
|
|
123
109
|
- !ruby/object:Gem::Version
|
124
110
|
version: '0'
|
125
111
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
112
|
+
name: rake
|
127
113
|
requirement: !ruby/object:Gem::Requirement
|
128
114
|
requirements:
|
129
115
|
- - ">="
|
@@ -136,6 +122,20 @@ dependencies:
|
|
136
122
|
- - ">="
|
137
123
|
- !ruby/object:Gem::Version
|
138
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rspec
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '3.0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '3.0'
|
139
139
|
description:
|
140
140
|
email:
|
141
141
|
- andrewnez@gmail.com
|
@@ -146,19 +146,15 @@ files:
|
|
146
146
|
- ".gitignore"
|
147
147
|
- ".travis.yml"
|
148
148
|
- Appraisals
|
149
|
-
- CHANGELOG.
|
149
|
+
- CHANGELOG.md
|
150
150
|
- CONTRIBUTING.md
|
151
151
|
- Gemfile
|
152
152
|
- LICENSE
|
153
|
-
- README.
|
153
|
+
- README.md
|
154
154
|
- Rakefile
|
155
|
-
- changes.rtf
|
156
|
-
- gemfiles/3.0.gemfile
|
157
|
-
- gemfiles/3.0.gemfile.lock
|
158
|
-
- gemfiles/3.1.gemfile
|
159
|
-
- gemfiles/3.1.gemfile.lock
|
160
155
|
- gemfiles/3.2.gemfile
|
161
156
|
- gemfiles/4.0.gemfile
|
157
|
+
- gemfiles/4.1.gemfile
|
162
158
|
- lib/split.rb
|
163
159
|
- lib/split/algorithms.rb
|
164
160
|
- lib/split/algorithms/weighted_sample.rb
|
@@ -200,6 +196,7 @@ files:
|
|
200
196
|
- spec/dashboard_helpers_spec.rb
|
201
197
|
- spec/dashboard_spec.rb
|
202
198
|
- spec/encapsulated_helper_spec.rb
|
199
|
+
- spec/experiment_catalog_spec.rb
|
203
200
|
- spec/experiment_spec.rb
|
204
201
|
- spec/helper_spec.rb
|
205
202
|
- spec/metric_spec.rb
|
@@ -231,7 +228,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
231
228
|
version: '0'
|
232
229
|
requirements: []
|
233
230
|
rubyforge_project: split
|
234
|
-
rubygems_version: 2.
|
231
|
+
rubygems_version: 2.4.5
|
235
232
|
signing_key:
|
236
233
|
specification_version: 4
|
237
234
|
summary: Rack based split testing framework
|
@@ -243,6 +240,7 @@ test_files:
|
|
243
240
|
- spec/dashboard_helpers_spec.rb
|
244
241
|
- spec/dashboard_spec.rb
|
245
242
|
- spec/encapsulated_helper_spec.rb
|
243
|
+
- spec/experiment_catalog_spec.rb
|
246
244
|
- spec/experiment_spec.rb
|
247
245
|
- spec/helper_spec.rb
|
248
246
|
- spec/metric_spec.rb
|