best_choice 0.0.1

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.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/README.rdoc +3 -0
  3. data/Rakefile +32 -0
  4. data/lib/best_choice.rb +26 -0
  5. data/lib/best_choice/algorithm.rb +65 -0
  6. data/lib/best_choice/algorithms/epsilon_greedy.rb +31 -0
  7. data/lib/best_choice/rails_util.rb +76 -0
  8. data/lib/best_choice/selector.rb +51 -0
  9. data/lib/best_choice/selectors/greedy_redis.rb +16 -0
  10. data/lib/best_choice/storage/redis_hash.rb +71 -0
  11. data/lib/best_choice/version.rb +5 -0
  12. data/test/algorithm_test.rb +40 -0
  13. data/test/algorithms/epsilon_greedy_test.rb +152 -0
  14. data/test/best_choice_test.rb +97 -0
  15. data/test/dummy/app/controllers/application_controller.rb +5 -0
  16. data/test/dummy/app/controllers/main_controller.rb +20 -0
  17. data/test/dummy/app/views/layouts/application.html.erb +11 -0
  18. data/test/dummy/app/views/main/landing.html.erb +22 -0
  19. data/test/dummy/bin/bundle +3 -0
  20. data/test/dummy/bin/rails +4 -0
  21. data/test/dummy/bin/rake +4 -0
  22. data/test/dummy/config.ru +4 -0
  23. data/test/dummy/config/application.rb +12 -0
  24. data/test/dummy/config/boot.rb +5 -0
  25. data/test/dummy/config/database.yml +25 -0
  26. data/test/dummy/config/environment.rb +5 -0
  27. data/test/dummy/config/environments/development.rb +29 -0
  28. data/test/dummy/config/environments/production.rb +80 -0
  29. data/test/dummy/config/environments/test.rb +36 -0
  30. data/test/dummy/config/initializers/secret_token.rb +12 -0
  31. data/test/dummy/config/initializers/session_store.rb +3 -0
  32. data/test/dummy/config/routes.rb +6 -0
  33. data/test/dummy/db/test.sqlite3 +0 -0
  34. data/test/dummy/log/test.log +5059 -0
  35. data/test/dummy/test/controllers/main_controller_test.rb +116 -0
  36. data/test/fixtures/dummy_algorithm.rb +6 -0
  37. data/test/fixtures/dummy_storage.rb +6 -0
  38. data/test/test_helper.rb +20 -0
  39. metadata +178 -0
@@ -0,0 +1,116 @@
1
+ require 'test_helper'
2
+
3
+ class MainControllerTest < ActionController::TestCase
4
+
5
+ def setup
6
+ Redis.current.flushall
7
+ @s_name = :sign_up_button
8
+ end
9
+
10
+ test 'display the same option for the same visitor' do
11
+
12
+ get :landing
13
+ picked_option = session[:_best_choice_picks][@s_name]
14
+ css_selector = "#test-#{picked_option}"
15
+ assert_select css_selector
16
+
17
+ 3.times {
18
+ get :landing
19
+ assert_select css_selector
20
+ }
21
+ end
22
+
23
+ test 'display better option if available' do
24
+ get :landing
25
+ first_picked_option = session[:_best_choice_picks][@s_name]
26
+ assert_has_html_for first_picked_option
27
+
28
+ new_visitor
29
+ get :landing
30
+ second_picked_option = session[:_best_choice_picks][@s_name]
31
+ assert_not_equal first_picked_option, second_picked_option
32
+ assert_has_html_for second_picked_option
33
+
34
+ new_visitor
35
+ get :landing
36
+ third_picked_option = session[:_best_choice_picks][@s_name]
37
+ assert_not_equal second_picked_option, third_picked_option
38
+ assert_has_html_for third_picked_option
39
+ end
40
+
41
+ test 'display the best option' do
42
+ # -------------------------------------------------
43
+ # 1. Get landing. The visitor does not choose to sign up.
44
+ #
45
+ get :landing
46
+ all_options = BestChoice.for(@s_name)
47
+ .instance_variable_get('@storage')
48
+ .options
49
+ first_picked_option = session[:_best_choice_picks][@s_name]
50
+ assert_has_html_for first_picked_option
51
+ # First option: success 0 / display 1.
52
+
53
+ # -------------------------------------------------
54
+ # 2. The second visitor sees another option and chooses to sign up.
55
+ #
56
+ new_visitor
57
+ get :landing
58
+ second_picked_option = session[:_best_choice_picks][@s_name]
59
+ assert_has_html_for second_picked_option
60
+ get :sign_up
61
+ # Second option: success 1 / display 1.
62
+
63
+ # -------------------------------------------------
64
+ # 3. The third visitor might either see the second option or the last
65
+ # available one with success 0 / display 0. He doesn't sign up.
66
+ #
67
+ new_visitor
68
+ get :landing
69
+ assert_not_equal first_picked_option,
70
+ session[:_best_choice_picks][@s_name]
71
+
72
+ # -------------------------------------------------
73
+ # 4. Force the fourth visitor to see the third option. He also doesn't
74
+ # sign up.
75
+ new_visitor
76
+ third_available_option =
77
+ (all_options - [first_picked_option, second_picked_option])[0]
78
+ session[:_best_choice_picks] = { @s_name => third_available_option }
79
+ get :landing
80
+ assert_has_html_for third_available_option
81
+
82
+ # -------------------------------------------------
83
+ # Success/display ratio:
84
+ # * First option -> 0%
85
+ # * Second option -> 50-100% (depending on the Step 3)
86
+ # * Third option -> 0%
87
+ #
88
+ # Thus the fifth user HAS to see the second option
89
+ # which is currently the best.
90
+ #
91
+ new_visitor
92
+ get :landing
93
+ assert_equal second_picked_option, session[:_best_choice_picks][@s_name]
94
+ assert_has_html_for second_picked_option
95
+ end
96
+
97
+
98
+ # -------------------------------------------------
99
+ # Utilities
100
+
101
+ private
102
+
103
+ # Deletes the picks from the session to avoid forcing the same option
104
+ # in consecutive requests (to mock different visitors).
105
+ #
106
+ def new_visitor
107
+ session.delete :_best_choice_picks
108
+ assigns(:_best_choice_selectors).clear
109
+ end
110
+
111
+ def assert_has_html_for picked_option
112
+ css_selector = "#test-#{picked_option}"
113
+ assert_select css_selector
114
+ end
115
+
116
+ end
@@ -0,0 +1,6 @@
1
+ class DummyAlgorithm < BestChoice::Algorithm
2
+
3
+ def initialize **opts
4
+ end
5
+
6
+ end
@@ -0,0 +1,6 @@
1
+ class DummyStorage
2
+
3
+ def initialize name
4
+ end
5
+
6
+ end
@@ -0,0 +1,20 @@
1
+ # Configure Rails Environment
2
+ ENV["RAILS_ENV"] = "test"
3
+
4
+ require File.expand_path("../dummy/config/environment.rb", __FILE__)
5
+ require "rails/test_help"
6
+
7
+ require 'rr'
8
+
9
+ require 'fixtures/dummy_algorithm'
10
+ require 'fixtures/dummy_storage'
11
+
12
+ Rails.backtrace_cleaner.remove_silencers!
13
+
14
+ # Load support files
15
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
16
+
17
+ # Load fixtures from the engine
18
+ if ActiveSupport::TestCase.method_defined?(:fixture_path=)
19
+ ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
20
+ end
metadata ADDED
@@ -0,0 +1,178 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: best_choice
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Mariusz Pruszyński
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: redis-objects
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rr
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '4'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3
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
+ description: Prepare a set of possible options and let your users determine which
84
+ is the best.
85
+ email:
86
+ - mpruszynski@gmail.com
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - README.rdoc
92
+ - Rakefile
93
+ - lib/best_choice.rb
94
+ - lib/best_choice/algorithm.rb
95
+ - lib/best_choice/algorithms/epsilon_greedy.rb
96
+ - lib/best_choice/rails_util.rb
97
+ - lib/best_choice/selector.rb
98
+ - lib/best_choice/selectors/greedy_redis.rb
99
+ - lib/best_choice/storage/redis_hash.rb
100
+ - lib/best_choice/version.rb
101
+ - test/algorithm_test.rb
102
+ - test/algorithms/epsilon_greedy_test.rb
103
+ - test/best_choice_test.rb
104
+ - test/dummy/app/controllers/application_controller.rb
105
+ - test/dummy/app/controllers/main_controller.rb
106
+ - test/dummy/app/views/layouts/application.html.erb
107
+ - test/dummy/app/views/main/landing.html.erb
108
+ - test/dummy/bin/bundle
109
+ - test/dummy/bin/rails
110
+ - test/dummy/bin/rake
111
+ - test/dummy/config.ru
112
+ - test/dummy/config/application.rb
113
+ - test/dummy/config/boot.rb
114
+ - test/dummy/config/database.yml
115
+ - test/dummy/config/environment.rb
116
+ - test/dummy/config/environments/development.rb
117
+ - test/dummy/config/environments/production.rb
118
+ - test/dummy/config/environments/test.rb
119
+ - test/dummy/config/initializers/secret_token.rb
120
+ - test/dummy/config/initializers/session_store.rb
121
+ - test/dummy/config/routes.rb
122
+ - test/dummy/db/test.sqlite3
123
+ - test/dummy/log/test.log
124
+ - test/dummy/test/controllers/main_controller_test.rb
125
+ - test/fixtures/dummy_algorithm.rb
126
+ - test/fixtures/dummy_storage.rb
127
+ - test/test_helper.rb
128
+ homepage:
129
+ licenses: []
130
+ metadata: {}
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubyforge_project:
147
+ rubygems_version: 2.4.4
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: Auto A/B testing
151
+ test_files:
152
+ - test/algorithm_test.rb
153
+ - test/algorithms/epsilon_greedy_test.rb
154
+ - test/best_choice_test.rb
155
+ - test/dummy/app/controllers/application_controller.rb
156
+ - test/dummy/app/controllers/main_controller.rb
157
+ - test/dummy/app/views/layouts/application.html.erb
158
+ - test/dummy/app/views/main/landing.html.erb
159
+ - test/dummy/bin/bundle
160
+ - test/dummy/bin/rails
161
+ - test/dummy/bin/rake
162
+ - test/dummy/config/application.rb
163
+ - test/dummy/config/boot.rb
164
+ - test/dummy/config/database.yml
165
+ - test/dummy/config/environment.rb
166
+ - test/dummy/config/environments/development.rb
167
+ - test/dummy/config/environments/production.rb
168
+ - test/dummy/config/environments/test.rb
169
+ - test/dummy/config/initializers/secret_token.rb
170
+ - test/dummy/config/initializers/session_store.rb
171
+ - test/dummy/config/routes.rb
172
+ - test/dummy/config.ru
173
+ - test/dummy/db/test.sqlite3
174
+ - test/dummy/log/test.log
175
+ - test/dummy/test/controllers/main_controller_test.rb
176
+ - test/fixtures/dummy_algorithm.rb
177
+ - test/fixtures/dummy_storage.rb
178
+ - test/test_helper.rb