vinted-ab 0.2.4 → 0.2.5
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 +5 -0
- data/README.md +9 -0
- data/Rakefile +9 -1
- data/ab.gemspec +3 -4
- data/lib/ab.rb +5 -0
- data/lib/ab/assigned_test.rb +2 -0
- data/lib/ab/configuration.rb +22 -0
- data/lib/ab/missing_variant.rb +26 -0
- data/lib/ab/null_test.rb +2 -9
- data/lib/ab/tests.rb +1 -1
- data/lib/ab/version.rb +1 -1
- data/spec/assigned_test_spec.rb +11 -0
- data/spec/examples/no_end/input.json +23 -0
- data/spec/examples/no_end/output.json +7 -0
- data/spec/null_test_spec.rb +2 -2
- data/spec/spec_helper.rb +3 -2
- data/spec/tests_spec.rb +1 -1
- metadata +14 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f227fe8202a3994a25c47c152ed4ca675ad5d571
|
4
|
+
data.tar.gz: f50d6b977402e19d57a62cba1a9affcf749d011a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dedbd7a58d4d5490e6a27677f36e31dc426ec762a063bbb10c7c2b80cd41fa11efed903e575a63f0dc301603f41529d30eb285e1e836ca39b5196e3b40f188bd
|
7
|
+
data.tar.gz: 41246c457af514bea7a803938b3418a87a195e4cae254abe0080ea081ffd6e850f5a183c1065af8a7a9077257af6b649c961b92cf2d29bbc1d67ee051a9d382c
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# ab
|
2
2
|
|
3
3
|
[](https://codeclimate.com/github/vinted/ab)
|
4
|
+
[](http://travis-ci.org/vinted/ab)
|
4
5
|
[](http://badge.fury.io/rb/vinted-ab)
|
5
6
|
[](https://gemnasium.com/vinted/ab)
|
6
7
|
|
@@ -19,6 +20,11 @@ ab = Ab::Tests.new(configuration, identifier)
|
|
19
20
|
Ab::Tests.before_picking_variant { |test| puts "picking variant for #{test}" }
|
20
21
|
Ab::Tests.after_picking_variant { |test, variant| puts "#{variant_name}" }
|
21
22
|
|
23
|
+
# by default messages are logged to null logger. Can be changed by setting your own logger:
|
24
|
+
Ab.configure do |config|
|
25
|
+
config.logger = Logger.new($stdout)
|
26
|
+
end
|
27
|
+
|
22
28
|
# ab.test never returns nil, but #variant can
|
23
29
|
case ab.test.variant
|
24
30
|
when 'red_button'
|
@@ -32,6 +38,9 @@ end
|
|
32
38
|
# calls #variant underneath, results of that call are cached
|
33
39
|
puts 'red button' if ab.test.red_button?
|
34
40
|
|
41
|
+
# non existant variants return false
|
42
|
+
puts 'this will not get printed' if ab.test.there_is_no_button?
|
43
|
+
|
35
44
|
# both start_at and end_at dates are accessible
|
36
45
|
puts 'newbie button' if user.created_at > ab.test.start_at && ab.test.for_newbies?
|
37
46
|
```
|
data/Rakefile
CHANGED
data/ab.gemspec
CHANGED
@@ -19,10 +19,9 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.test_files = `git ls-files -- {spec}/*`.split("\n")
|
20
20
|
spec.require_paths = ['lib']
|
21
21
|
|
22
|
-
spec.add_development_dependency '
|
23
|
-
spec.add_development_dependency '
|
24
|
-
spec.add_development_dependency 'rspec', '~>
|
25
|
-
spec.add_development_dependency 'rspec-its', '~> 1.0.1'
|
22
|
+
spec.add_development_dependency 'rake', '~> 10.3'
|
23
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
24
|
+
spec.add_development_dependency 'rspec-its', '~> 1.0'
|
26
25
|
spec.add_development_dependency 'json-schema', '~> 2.2.2', '>= 2.2.2'
|
27
26
|
spec.add_development_dependency 'ruby-prof', '~> 0.15.0', '>= 0.15.0'
|
28
27
|
spec.add_development_dependency 'pry', '~> 0.10.0', '>= 0.10.0'
|
data/lib/ab.rb
CHANGED
data/lib/ab/assigned_test.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Ab
|
2
|
+
class << self
|
3
|
+
attr_writer :config
|
4
|
+
|
5
|
+
def config
|
6
|
+
@config ||= Config.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def configure
|
10
|
+
@config ||= Config.new
|
11
|
+
yield(@config)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Config
|
16
|
+
attr_accessor :logger
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@logger = Logger.new(nil)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Ab
|
2
|
+
module MissingVariant
|
3
|
+
def method_missing(meth, *args, &block)
|
4
|
+
if variant_method?(meth)
|
5
|
+
log_missing_variant(meth)
|
6
|
+
false
|
7
|
+
else
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def respond_to_missing?(meth, *)
|
13
|
+
variant_method?(meth) ? true : super
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def variant_method?(meth)
|
19
|
+
meth.to_s.end_with?('?')
|
20
|
+
end
|
21
|
+
|
22
|
+
def log_missing_variant(meth)
|
23
|
+
Ab.config.logger.debug("[AB_testing] Checking non-existing variant: #{meth}")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/ab/null_test.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module Ab
|
2
2
|
class NullTest
|
3
|
+
include Ab::MissingVariant
|
4
|
+
|
3
5
|
def variant
|
4
6
|
end
|
5
7
|
|
@@ -10,14 +12,5 @@ module Ab
|
|
10
12
|
def end_at
|
11
13
|
Test::DEFAULT_END_AT
|
12
14
|
end
|
13
|
-
|
14
|
-
|
15
|
-
def method_missing(meth, *args, &block)
|
16
|
-
meth.to_s.end_with?('?') ? false : super
|
17
|
-
end
|
18
|
-
|
19
|
-
def respond_to?(meth)
|
20
|
-
meth.to_s.end_with?('?') ? true : super
|
21
|
-
end
|
22
15
|
end
|
23
16
|
end
|
data/lib/ab/tests.rb
CHANGED
data/lib/ab/version.rb
CHANGED
data/spec/assigned_test_spec.rb
CHANGED
@@ -16,6 +16,17 @@ module Ab
|
|
16
16
|
let(:buckets) { 1..1000 }
|
17
17
|
let(:thousand_variants) { 1.upto(1000).map { |i| AssignedTest.new(test, i).variant } }
|
18
18
|
|
19
|
+
context 'with non existent variant' do
|
20
|
+
let(:variants) { [OpenStruct.new(name: 'enabled', accumulated_chance_weight: 2)] }
|
21
|
+
let(:message) { '[AB_testing] Checking non-existing variant: disabled?' }
|
22
|
+
|
23
|
+
before { Ab.config.logger.should_receive(:debug).with(message) }
|
24
|
+
|
25
|
+
subject { assigned_test.disabled? }
|
26
|
+
|
27
|
+
it { should be false }
|
28
|
+
end
|
29
|
+
|
19
30
|
describe '#variant' do
|
20
31
|
subject { assigned_test.variant }
|
21
32
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
{
|
2
|
+
"salt": "61b81d7844c40c4057ebe6fc1a7a4a54",
|
3
|
+
"bucket_count": 20,
|
4
|
+
"ab_tests": [
|
5
|
+
{
|
6
|
+
"id": 6,
|
7
|
+
"name": "no_end",
|
8
|
+
"seed": "1995f6808c018b6dd91a3bc927fd7e92",
|
9
|
+
"start_at": "1605-11-05T00:00:00+0100",
|
10
|
+
"all_buckets": true,
|
11
|
+
"variants": [
|
12
|
+
{
|
13
|
+
"name": "green",
|
14
|
+
"chance_weight": 1
|
15
|
+
},
|
16
|
+
{
|
17
|
+
"name": "red",
|
18
|
+
"chance_weight": 1
|
19
|
+
}
|
20
|
+
]
|
21
|
+
}
|
22
|
+
]
|
23
|
+
}
|
data/spec/null_test_spec.rb
CHANGED
@@ -9,11 +9,11 @@ module Ab
|
|
9
9
|
its(:end_at) { should_not be_nil }
|
10
10
|
|
11
11
|
specify 'does not raise for method ending in question mark' do
|
12
|
-
|
12
|
+
lambda { subject.bla? }.should_not raise_error
|
13
13
|
end
|
14
14
|
|
15
15
|
specify 'raises for method not ending in question mark' do
|
16
|
-
|
16
|
+
lambda { subject.bla }.should raise_error
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
require 'json'
|
1
2
|
require 'rspec'
|
2
3
|
require 'rspec/its'
|
3
4
|
require 'ab'
|
4
5
|
|
5
6
|
RSpec.configure do |config|
|
6
|
-
config.
|
7
|
-
config.
|
7
|
+
config.expect_with(:rspec) { |c| c.syntax = :should }
|
8
|
+
config.mock_with(:rspec) { |c| c.syntax = :should }
|
8
9
|
end
|
data/spec/tests_spec.rb
CHANGED
@@ -52,7 +52,7 @@ module Ab
|
|
52
52
|
subject { tests }
|
53
53
|
|
54
54
|
specify 'has no public methods' do
|
55
|
-
(subject.public_methods(false) - [:method_missing, :
|
55
|
+
(subject.public_methods(false) - [:method_missing, :respond_to_missing?, :all]).count.should == 0
|
56
56
|
end
|
57
57
|
|
58
58
|
context 'single experiment with single variant' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vinted-ab
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mindaugas Mozūras
|
@@ -9,76 +9,50 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-05-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: bundler
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
requirements:
|
18
|
-
- - "~>"
|
19
|
-
- !ruby/object:Gem::Version
|
20
|
-
version: '1.3'
|
21
|
-
type: :development
|
22
|
-
prerelease: false
|
23
|
-
version_requirements: !ruby/object:Gem::Requirement
|
24
|
-
requirements:
|
25
|
-
- - "~>"
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
version: '1.3'
|
28
14
|
- !ruby/object:Gem::Dependency
|
29
15
|
name: rake
|
30
16
|
requirement: !ruby/object:Gem::Requirement
|
31
17
|
requirements:
|
32
18
|
- - "~>"
|
33
19
|
- !ruby/object:Gem::Version
|
34
|
-
version: '10.
|
35
|
-
- - ">="
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
version: 10.1.0
|
20
|
+
version: '10.3'
|
38
21
|
type: :development
|
39
22
|
prerelease: false
|
40
23
|
version_requirements: !ruby/object:Gem::Requirement
|
41
24
|
requirements:
|
42
25
|
- - "~>"
|
43
26
|
- !ruby/object:Gem::Version
|
44
|
-
version: '10.
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 10.1.0
|
27
|
+
version: '10.3'
|
48
28
|
- !ruby/object:Gem::Dependency
|
49
29
|
name: rspec
|
50
30
|
requirement: !ruby/object:Gem::Requirement
|
51
31
|
requirements:
|
52
32
|
- - "~>"
|
53
33
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
55
|
-
- - ">="
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
version: 2.14.0
|
34
|
+
version: '3.0'
|
58
35
|
type: :development
|
59
36
|
prerelease: false
|
60
37
|
version_requirements: !ruby/object:Gem::Requirement
|
61
38
|
requirements:
|
62
39
|
- - "~>"
|
63
40
|
- !ruby/object:Gem::Version
|
64
|
-
version: '
|
65
|
-
- - ">="
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: 2.14.0
|
41
|
+
version: '3.0'
|
68
42
|
- !ruby/object:Gem::Dependency
|
69
43
|
name: rspec-its
|
70
44
|
requirement: !ruby/object:Gem::Requirement
|
71
45
|
requirements:
|
72
46
|
- - "~>"
|
73
47
|
- !ruby/object:Gem::Version
|
74
|
-
version: 1.0
|
48
|
+
version: '1.0'
|
75
49
|
type: :development
|
76
50
|
prerelease: false
|
77
51
|
version_requirements: !ruby/object:Gem::Requirement
|
78
52
|
requirements:
|
79
53
|
- - "~>"
|
80
54
|
- !ruby/object:Gem::Version
|
81
|
-
version: 1.0
|
55
|
+
version: '1.0'
|
82
56
|
- !ruby/object:Gem::Dependency
|
83
57
|
name: json-schema
|
84
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -149,6 +123,7 @@ extra_rdoc_files: []
|
|
149
123
|
files:
|
150
124
|
- ".gitignore"
|
151
125
|
- ".rubocop.yml"
|
126
|
+
- ".travis.yml"
|
152
127
|
- Gemfile
|
153
128
|
- LICENSE
|
154
129
|
- README.md
|
@@ -157,6 +132,8 @@ files:
|
|
157
132
|
- config.json
|
158
133
|
- lib/ab.rb
|
159
134
|
- lib/ab/assigned_test.rb
|
135
|
+
- lib/ab/configuration.rb
|
136
|
+
- lib/ab/missing_variant.rb
|
160
137
|
- lib/ab/null_test.rb
|
161
138
|
- lib/ab/test.rb
|
162
139
|
- lib/ab/tests.rb
|
@@ -181,6 +158,8 @@ files:
|
|
181
158
|
- spec/examples/multiple_variants/output.json
|
182
159
|
- spec/examples/no_buckets/input.json
|
183
160
|
- spec/examples/no_buckets/output.json
|
161
|
+
- spec/examples/no_end/input.json
|
162
|
+
- spec/examples/no_end/output.json
|
184
163
|
- spec/examples/no_variants/input.json
|
185
164
|
- spec/examples/no_variants/output.json
|
186
165
|
- spec/examples/zero_buckets/input.json
|
@@ -212,7 +191,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
212
191
|
version: 1.3.6
|
213
192
|
requirements: []
|
214
193
|
rubyforge_project:
|
215
|
-
rubygems_version: 2.
|
194
|
+
rubygems_version: 2.4.5
|
216
195
|
signing_key:
|
217
196
|
specification_version: 4
|
218
197
|
summary: AB testing gem used internally by Vinted
|