vanity 1.8.2 → 1.8.3.beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +14 -5
- data/Gemfile +5 -0
- data/Gemfile.lock +12 -6
- data/gemfiles/rails3.gemfile +3 -0
- data/gemfiles/rails3.gemfile.lock +11 -5
- data/gemfiles/rails31.gemfile +3 -0
- data/gemfiles/rails31.gemfile.lock +11 -6
- data/gemfiles/rails32.gemfile +3 -0
- data/gemfiles/rails32.gemfile.lock +11 -5
- data/lib/vanity/adapters/abstract_adapter.rb +13 -8
- data/lib/vanity/adapters/active_record_adapter.rb +6 -0
- data/lib/vanity/adapters/mongodb_adapter.rb +6 -0
- data/lib/vanity/adapters/redis_adapter.rb +10 -0
- data/lib/vanity/backport.rb +1 -2
- data/lib/vanity/experiment/ab_test.rb +182 -139
- data/lib/vanity/experiment/alternative.rb +93 -0
- data/lib/vanity/experiment/base.rb +8 -35
- data/lib/vanity/experiment/bayesian_bandit_score.rb +93 -0
- data/lib/vanity/experiment/definition.rb +32 -0
- data/lib/vanity/frameworks/rails.rb +18 -0
- data/lib/vanity/playground.rb +16 -0
- data/lib/vanity/templates/_ab_test.erb +28 -13
- data/lib/vanity/templates/_participant.erb +12 -0
- data/lib/vanity/version.rb +1 -1
- data/test/experiment/ab_test.rb +141 -0
- data/test/experiment/base_test.rb +13 -4
- data/test/playground_test.rb +12 -0
- data/test/rails_dashboard_test.rb +35 -1
- data/test/rails_test.rb +8 -0
- data/vanity.gemspec +4 -3
- metadata +20 -19
- data/.rvmrc +0 -3
@@ -8,7 +8,7 @@ class ExperimentTest < Test::Unit::TestCase
|
|
8
8
|
end
|
9
9
|
|
10
10
|
# -- Defining experiment --
|
11
|
-
|
11
|
+
|
12
12
|
def test_can_access_experiment_by_id
|
13
13
|
exp = new_ab_test(:ice_cream_flavor) { metrics :happiness }
|
14
14
|
assert_equal exp, experiment(:ice_cream_flavor)
|
@@ -105,7 +105,7 @@ class ExperimentTest < Test::Unit::TestCase
|
|
105
105
|
assert_kind_of Time, experiment(:ice_cream_flavor).created_at
|
106
106
|
assert_in_delta experiment(:ice_cream_flavor).created_at.to_i, Time.now.to_i, 1
|
107
107
|
end
|
108
|
-
|
108
|
+
|
109
109
|
def test_experiment_keeps_created_timestamp_across_definitions
|
110
110
|
past = Date.today - 1
|
111
111
|
Timecop.freeze past.to_time do
|
@@ -136,7 +136,7 @@ class ExperimentTest < Test::Unit::TestCase
|
|
136
136
|
end
|
137
137
|
|
138
138
|
# -- completion -- #
|
139
|
-
|
139
|
+
|
140
140
|
# check_completion is called by derived classes, but since it's
|
141
141
|
# part of the base_test I'm testing it here.
|
142
142
|
def test_error_in_check_completion
|
@@ -148,5 +148,14 @@ class ExperimentTest < Test::Unit::TestCase
|
|
148
148
|
e.stubs(:identity).returns(:b)
|
149
149
|
e.track!(:a, Time.now, 10)
|
150
150
|
end
|
151
|
-
|
151
|
+
|
152
|
+
def test_complete_updates_completed_at
|
153
|
+
new_ab_test(:ice_cream_flavor) { metrics :happiness }
|
154
|
+
|
155
|
+
Timecop.freeze(2008, 9, 1, 12, 0, 0) do
|
156
|
+
experiment(:ice_cream_flavor).complete!(1)
|
157
|
+
end
|
158
|
+
assert_equal Time.local(2008, 9, 1, 12, 0, 0), experiment(:ice_cream_flavor).completed_at
|
159
|
+
end
|
160
|
+
|
152
161
|
end
|
data/test/playground_test.rb
CHANGED
@@ -34,4 +34,16 @@ class PlaygroundTest < Test::Unit::TestCase
|
|
34
34
|
assert !instance.connected?
|
35
35
|
end
|
36
36
|
|
37
|
+
def test_participant_info
|
38
|
+
assert_equal [], Vanity.playground.participant_info("abcdef")
|
39
|
+
metric "Coolness"
|
40
|
+
new_ab_test :foobar do
|
41
|
+
alternatives "foo", "bar"
|
42
|
+
identify { "abcdef" }
|
43
|
+
metrics :coolness
|
44
|
+
end
|
45
|
+
alt = experiment(:foobar).choose
|
46
|
+
assert_equal [[Vanity.playground.experiment(:foobar), alt]], Vanity.playground.participant_info("abcdef")
|
47
|
+
end
|
48
|
+
|
37
49
|
end
|
@@ -4,7 +4,6 @@ class VanityController < ActionController::Base
|
|
4
4
|
include Vanity::Rails::Dashboard
|
5
5
|
end
|
6
6
|
|
7
|
-
# Pages accessible to everyone, e.g. sign in, community search.
|
8
7
|
class RailsDashboardTest < ActionController::TestCase
|
9
8
|
tests VanityController
|
10
9
|
|
@@ -18,6 +17,8 @@ class RailsDashboardTest < ActionController::TestCase
|
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
20
|
+
# -- Actions accessible to everyone, e.g. sign in, community search --
|
21
|
+
|
21
22
|
def test_add_participant
|
22
23
|
xhr :post, :add_participant, :e => "food", :a => 0
|
23
24
|
assert_response :success
|
@@ -30,6 +31,39 @@ class RailsDashboardTest < ActionController::TestCase
|
|
30
31
|
assert @response.body.blank?
|
31
32
|
end
|
32
33
|
|
34
|
+
# -- Test administrator actions --
|
35
|
+
|
36
|
+
def test_participant_renders_experiment_for_id
|
37
|
+
experiment(:food).choose
|
38
|
+
get :participant, :id => "1"
|
39
|
+
assert_response :success
|
40
|
+
assert @response.body =~ %r{id 1 is taking part in the following experiments:\n<ul class=\"experiments\">[\s]+<li class=\"experiment ab_test}
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_participant_renders_empty_for_bad_id
|
44
|
+
get :participant, :id => "2"
|
45
|
+
assert_response :success
|
46
|
+
assert @response.body =~ %r{<ul class=\"experiments\">[\s]+</ul>}
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_participant_renders_empty_for_no_id
|
50
|
+
get :participant
|
51
|
+
assert_response :success
|
52
|
+
assert @response.body =~ %r{<ul class=\"experiments\">[\s]+</ul>}
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_complete_forces_confirmation
|
56
|
+
xhr :post, :complete, :e => "food", :a => 0
|
57
|
+
assert_response :success
|
58
|
+
assert_equal 0, assigns(:to_confirm)
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_complete_with_confirmation_completes
|
62
|
+
xhr :post, :complete, :e => "food", :a => 0, :confirmed => 'true'
|
63
|
+
assert_response :success
|
64
|
+
assert !Vanity.playground.experiment('food').active?
|
65
|
+
end
|
66
|
+
|
33
67
|
def test_chooses
|
34
68
|
xhr :post, :chooses, :e => "food", :a => 0
|
35
69
|
assert_response :success
|
data/test/rails_test.rb
CHANGED
@@ -254,6 +254,7 @@ $stdout << Vanity.playground.connection
|
|
254
254
|
|
255
255
|
def test_connection_from_yaml
|
256
256
|
FileUtils.mkpath "tmp/config"
|
257
|
+
@original_env = ENV["RAILS_ENV"]
|
257
258
|
ENV["RAILS_ENV"] = "production"
|
258
259
|
File.open("tmp/config/vanity.yml", "w") do |io|
|
259
260
|
io.write <<-YML
|
@@ -267,11 +268,13 @@ production:
|
|
267
268
|
$stdout << Vanity.playground.connection
|
268
269
|
RB
|
269
270
|
ensure
|
271
|
+
ENV["RAILS_ENV"] = @original_env
|
270
272
|
File.unlink "tmp/config/vanity.yml"
|
271
273
|
end
|
272
274
|
|
273
275
|
def test_connection_from_yaml_url
|
274
276
|
FileUtils.mkpath "tmp/config"
|
277
|
+
@original_env = ENV["RAILS_ENV"]
|
275
278
|
ENV["RAILS_ENV"] = "production"
|
276
279
|
File.open("tmp/config/vanity.yml", "w") do |io|
|
277
280
|
io.write <<-YML
|
@@ -282,13 +285,16 @@ production: redis://somehost/15
|
|
282
285
|
$stdout << Vanity.playground.connection
|
283
286
|
RB
|
284
287
|
ensure
|
288
|
+
ENV["RAILS_ENV"] = @original_env
|
285
289
|
File.unlink "tmp/config/vanity.yml"
|
286
290
|
end
|
287
291
|
|
288
292
|
def test_connection_from_yaml_with_erb
|
289
293
|
FileUtils.mkpath "tmp/config"
|
294
|
+
@original_env = ENV["RAILS_ENV"]
|
290
295
|
ENV["RAILS_ENV"] = "production"
|
291
296
|
# Pass storage URL through environment like heroku does
|
297
|
+
@original_redis_url = ENV["REDIS_URL"]
|
292
298
|
ENV["REDIS_URL"] = "redis://somehost:6379/15"
|
293
299
|
File.open("tmp/config/vanity.yml", "w") do |io|
|
294
300
|
io.write <<-YML
|
@@ -299,6 +305,8 @@ production: <%= ENV['REDIS_URL'] %>
|
|
299
305
|
$stdout << Vanity.playground.connection
|
300
306
|
RB
|
301
307
|
ensure
|
308
|
+
ENV["RAILS_ENV"] = @original_env
|
309
|
+
ENV["REDIS_URL"] = @original_redis_url
|
302
310
|
File.unlink "tmp/config/vanity.yml"
|
303
311
|
end
|
304
312
|
|
data/vanity.gemspec
CHANGED
@@ -7,6 +7,7 @@ Gem::Specification.new do |spec|
|
|
7
7
|
spec.author = "Assaf Arkin"
|
8
8
|
spec.email = "assaf@labnotes.org"
|
9
9
|
spec.homepage = "http://vanity.labnotes.org"
|
10
|
+
spec.license = "MIT"
|
10
11
|
spec.summary = "Experience Driven Development framework for Ruby"
|
11
12
|
spec.description = "Mirror, mirror on the wall ..."
|
12
13
|
spec.post_install_message = "To get started run vanity --help"
|
@@ -20,7 +21,7 @@ Gem::Specification.new do |spec|
|
|
20
21
|
spec.rdoc_options = "--title", "Vanity #{spec.version}", "--main", "README.rdoc",
|
21
22
|
"--webcvs", "http://github.com/assaf/#{spec.name}"
|
22
23
|
|
23
|
-
spec.required_ruby_version =
|
24
|
-
spec.add_dependency "redis", "
|
25
|
-
spec.add_dependency "redis-namespace", "
|
24
|
+
spec.required_ruby_version = ">= 1.8.7"
|
25
|
+
spec.add_dependency "redis", ">= 2.1"
|
26
|
+
spec.add_dependency "redis-namespace", ">= 1.1.0"
|
26
27
|
end
|
metadata
CHANGED
@@ -1,48 +1,48 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vanity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.8.
|
5
|
-
prerelease:
|
4
|
+
version: 1.8.3.beta
|
5
|
+
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Assaf Arkin
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-11-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: '2.
|
21
|
+
version: '2.1'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '2.
|
29
|
+
version: '2.1'
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: redis-namespace
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
none: false
|
34
34
|
requirements:
|
35
|
-
- -
|
35
|
+
- - ! '>='
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: 1.
|
37
|
+
version: 1.1.0
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
|
-
- -
|
43
|
+
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: 1.
|
45
|
+
version: 1.1.0
|
46
46
|
description: Mirror, mirror on the wall ...
|
47
47
|
email: assaf@labnotes.org
|
48
48
|
executables:
|
@@ -54,7 +54,6 @@ extra_rdoc_files:
|
|
54
54
|
files:
|
55
55
|
- .autotest
|
56
56
|
- .gitignore
|
57
|
-
- .rvmrc
|
58
57
|
- .travis.yml
|
59
58
|
- Appraisals
|
60
59
|
- CHANGELOG
|
@@ -111,7 +110,10 @@ files:
|
|
111
110
|
- lib/vanity/commands/report.rb
|
112
111
|
- lib/vanity/commands/upgrade.rb
|
113
112
|
- lib/vanity/experiment/ab_test.rb
|
113
|
+
- lib/vanity/experiment/alternative.rb
|
114
114
|
- lib/vanity/experiment/base.rb
|
115
|
+
- lib/vanity/experiment/bayesian_bandit_score.rb
|
116
|
+
- lib/vanity/experiment/definition.rb
|
115
117
|
- lib/vanity/frameworks.rb
|
116
118
|
- lib/vanity/frameworks/rails.rb
|
117
119
|
- lib/vanity/helpers.rb
|
@@ -126,6 +128,7 @@ files:
|
|
126
128
|
- lib/vanity/templates/_experiments.erb
|
127
129
|
- lib/vanity/templates/_metric.erb
|
128
130
|
- lib/vanity/templates/_metrics.erb
|
131
|
+
- lib/vanity/templates/_participant.erb
|
129
132
|
- lib/vanity/templates/_report.erb
|
130
133
|
- lib/vanity/templates/_vanity.js.erb
|
131
134
|
- lib/vanity/templates/flot.min.js
|
@@ -186,11 +189,12 @@ files:
|
|
186
189
|
- test/test_helper.rb
|
187
190
|
- vanity.gemspec
|
188
191
|
homepage: http://vanity.labnotes.org
|
189
|
-
licenses:
|
192
|
+
licenses:
|
193
|
+
- MIT
|
190
194
|
post_install_message: To get started run vanity --help
|
191
195
|
rdoc_options:
|
192
196
|
- --title
|
193
|
-
- Vanity 1.8.
|
197
|
+
- Vanity 1.8.3.beta
|
194
198
|
- --main
|
195
199
|
- README.rdoc
|
196
200
|
- --webcvs
|
@@ -206,12 +210,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
206
210
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
207
211
|
none: false
|
208
212
|
requirements:
|
209
|
-
- - ! '
|
213
|
+
- - ! '>'
|
210
214
|
- !ruby/object:Gem::Version
|
211
|
-
version:
|
212
|
-
segments:
|
213
|
-
- 0
|
214
|
-
hash: 3663910220837793406
|
215
|
+
version: 1.3.1
|
215
216
|
requirements: []
|
216
217
|
rubyforge_project:
|
217
218
|
rubygems_version: 1.8.23
|
data/.rvmrc
DELETED