vanity 1.5.3 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +61 -13
- data/Gemfile +5 -5
- data/README.rdoc +10 -1
- data/lib/vanity/adapters/mongodb_adapter.rb +23 -7
- data/lib/vanity/adapters/redis_adapter.rb +8 -2
- data/lib/vanity/experiment/ab_test.rb +55 -30
- data/lib/vanity/experiment/base.rb +4 -2
- data/lib/vanity/frameworks/rails.rb +30 -2
- data/lib/vanity/helpers.rb +8 -1
- data/lib/vanity/playground.rb +35 -2
- data/lib/vanity/templates/_vanity.js.erb +20 -0
- data/lib/vanity/version.rb +1 -1
- data/test/adapters/redis_adapter_test.rb +17 -0
- data/test/experiment/ab_test.rb +83 -11
- data/test/experiment/base_test.rb +14 -0
- data/test/myapp/log/production.log +165 -0
- data/test/playground_test.rb +10 -0
- data/test/rails_dashboard_test.rb +37 -0
- data/test/rails_helper_test.rb +28 -0
- data/test/rails_test.rb +73 -4
- data/test/test_helper.rb +4 -6
- data/vanity.gemspec +1 -1
- metadata +42 -51
- data/test/myapp/app/controllers/application_controller.rbc +0 -66
- data/test/myapp/app/controllers/main_controller.rbc +0 -347
- data/test/myapp/config/boot.rbc +0 -2534
- data/test/myapp/config/environment.rbc +0 -403
- data/test/myapp/config/routes.rbc +0 -174
- data/test/passenger_test.rbc +0 -0
- data/test/playground_test.rbc +0 -256
- data/test/rails_test.rbc +0 -4086
- data/test/test_helper.rbc +0 -4297
data/test/experiment/ab_test.rb
CHANGED
@@ -118,6 +118,21 @@ class AbTestTest < ActionController::TestCase
|
|
118
118
|
assert_equal 1, experiment(:abcd).alternatives.sum(&:conversions)
|
119
119
|
end
|
120
120
|
|
121
|
+
# -- use_js! --
|
122
|
+
|
123
|
+
def test_does_not_record_participant_when_using_js
|
124
|
+
Vanity.playground.use_js!
|
125
|
+
ids = (0...10).to_a
|
126
|
+
new_ab_test :foobar do
|
127
|
+
alternatives "foo", "bar"
|
128
|
+
identify { ids.pop }
|
129
|
+
metrics :coolness
|
130
|
+
end
|
131
|
+
10.times { experiment(:foobar).choose }
|
132
|
+
alts = experiment(:foobar).alternatives
|
133
|
+
assert_equal 0, alts.map(&:participants).sum
|
134
|
+
end
|
135
|
+
|
121
136
|
|
122
137
|
# -- Running experiment --
|
123
138
|
|
@@ -127,10 +142,10 @@ class AbTestTest < ActionController::TestCase
|
|
127
142
|
identify { "6e98ec" }
|
128
143
|
metrics :coolness
|
129
144
|
end
|
130
|
-
assert value = experiment(:foobar).choose
|
145
|
+
assert value = experiment(:foobar).choose.value
|
131
146
|
assert_match /foo|bar/, value
|
132
147
|
1000.times do
|
133
|
-
assert_equal value, experiment(:foobar).choose
|
148
|
+
assert_equal value, experiment(:foobar).choose.value
|
134
149
|
end
|
135
150
|
end
|
136
151
|
|
@@ -140,7 +155,7 @@ class AbTestTest < ActionController::TestCase
|
|
140
155
|
identify { rand }
|
141
156
|
metrics :coolness
|
142
157
|
end
|
143
|
-
alts = Array.new(1000) { experiment(:foobar).choose }
|
158
|
+
alts = Array.new(1000) { experiment(:foobar).choose.value }
|
144
159
|
assert_equal %w{bar foo}, alts.uniq.sort
|
145
160
|
assert_in_delta alts.select { |a| a == "foo" }.size, 500, 100 # this may fail, such is propability
|
146
161
|
end
|
@@ -324,7 +339,7 @@ class AbTestTest < ActionController::TestCase
|
|
324
339
|
fake :abcd, :a=>[182, 35], :b=>[180, 45], :c=>[189,28], :d=>[188, 61]
|
325
340
|
|
326
341
|
z_scores = experiment(:abcd).score.alts.map { |alt| "%.2f" % alt.z_score }
|
327
|
-
assert_equal %w{-1.33 0.00 -2.
|
342
|
+
assert_equal %w{-1.33 0.00 -2.46 1.58}, z_scores
|
328
343
|
probabilities = experiment(:abcd).score.alts.map(&:probability)
|
329
344
|
assert_equal [90, 0, 99, 90], probabilities
|
330
345
|
|
@@ -466,7 +481,7 @@ Option C did not convert.
|
|
466
481
|
|
467
482
|
assert_equal <<-TEXT, experiment(:abcd).conclusion.join("\n") << "\n"
|
468
483
|
There are 374 participants in this experiment.
|
469
|
-
The best choice is option D: it converted at 32.4
|
484
|
+
The best choice is option D: it converted at 32.4% (1% better than option B).
|
470
485
|
This result is not statistically significant, suggest you continue this experiment.
|
471
486
|
Option B converted at 32.3%.
|
472
487
|
Option A did not convert.
|
@@ -530,7 +545,7 @@ This experiment did not run long enough to find a clear winner.
|
|
530
545
|
def test_completion_if_fails
|
531
546
|
new_ab_test :simple do
|
532
547
|
identify { rand }
|
533
|
-
complete_if { fail }
|
548
|
+
complete_if { fail "Testing complete_if raises exception" }
|
534
549
|
metrics :coolness
|
535
550
|
end
|
536
551
|
experiment(:simple).choose
|
@@ -564,7 +579,7 @@ This experiment did not run long enough to find a clear winner.
|
|
564
579
|
# Run experiment to completion (100 participants)
|
565
580
|
results = Set.new
|
566
581
|
100.times do
|
567
|
-
results << experiment(:simple).choose
|
582
|
+
results << experiment(:simple).choose.value
|
568
583
|
metric(:coolness).track!
|
569
584
|
end
|
570
585
|
assert results.include?(true) && results.include?(false)
|
@@ -572,7 +587,7 @@ This experiment did not run long enough to find a clear winner.
|
|
572
587
|
|
573
588
|
# Test that we always get the same choice (true)
|
574
589
|
100.times do
|
575
|
-
assert_equal true, experiment(:simple).choose
|
590
|
+
assert_equal true, experiment(:simple).choose.value
|
576
591
|
metric(:coolness).track!
|
577
592
|
end
|
578
593
|
# We don't get to count the 100 participant's conversion, but that's ok.
|
@@ -592,6 +607,18 @@ This experiment did not run long enough to find a clear winner.
|
|
592
607
|
assert_equal experiment(:quick).alternatives[1], experiment(:quick).outcome
|
593
608
|
end
|
594
609
|
|
610
|
+
def test_error_in_completion
|
611
|
+
new_ab_test :quick do
|
612
|
+
outcome_is { raise RuntimeError }
|
613
|
+
metrics :coolness
|
614
|
+
end
|
615
|
+
e = experiment(:quick)
|
616
|
+
e.expects(:warn)
|
617
|
+
assert_nothing_raised do
|
618
|
+
e.complete!
|
619
|
+
end
|
620
|
+
end
|
621
|
+
|
595
622
|
def test_outcome_is_returns_nil
|
596
623
|
new_ab_test :quick do
|
597
624
|
outcome_is { nil }
|
@@ -612,7 +639,7 @@ This experiment did not run long enough to find a clear winner.
|
|
612
639
|
|
613
640
|
def test_outcome_is_fails
|
614
641
|
new_ab_test :quick do
|
615
|
-
outcome_is { fail }
|
642
|
+
outcome_is { fail "Testing outcome_is raising exception" }
|
616
643
|
metrics :coolness
|
617
644
|
end
|
618
645
|
experiment(:quick).complete!
|
@@ -669,10 +696,54 @@ This experiment did not run long enough to find a clear winner.
|
|
669
696
|
assert_nil experiment(:quick).outcome
|
670
697
|
end
|
671
698
|
|
699
|
+
def test_chooses_records_participants
|
700
|
+
new_ab_test :simple do
|
701
|
+
alternatives :a, :b, :c
|
702
|
+
metrics :coolness
|
703
|
+
end
|
704
|
+
experiment(:simple).chooses(:b)
|
705
|
+
assert_equal experiment(:simple).alternatives[1].participants, 1
|
706
|
+
end
|
707
|
+
|
708
|
+
def test_chooses_moves_participant_to_new_alternative
|
709
|
+
new_ab_test :simple do
|
710
|
+
alternatives :a, :b, :c
|
711
|
+
metrics :coolness
|
712
|
+
identify { "1" }
|
713
|
+
end
|
714
|
+
val = experiment(:simple).choose.value
|
715
|
+
alternative = experiment(:simple).alternatives.detect {|a| a.value != val }
|
716
|
+
experiment(:simple).chooses(alternative.value)
|
717
|
+
assert_equal experiment(:simple).choose.value, alternative.value
|
718
|
+
experiment(:simple).chooses(val)
|
719
|
+
assert_equal experiment(:simple).choose.value, val
|
720
|
+
end
|
721
|
+
|
722
|
+
def test_chooses_records_participants_only_once
|
723
|
+
new_ab_test :simple do
|
724
|
+
alternatives :a, :b, :c
|
725
|
+
metrics :coolness
|
726
|
+
end
|
727
|
+
2.times { experiment(:simple).chooses(:b) }
|
728
|
+
assert_equal experiment(:simple).alternatives[1].participants, 1
|
729
|
+
end
|
730
|
+
|
731
|
+
def test_chooses_records_participants_for_new_alternatives
|
732
|
+
new_ab_test :simple do
|
733
|
+
alternatives :a, :b, :c
|
734
|
+
metrics :coolness
|
735
|
+
end
|
736
|
+
experiment(:simple).chooses(:b)
|
737
|
+
experiment(:simple).chooses(:c)
|
738
|
+
assert_equal experiment(:simple).alternatives[1].participants, 1
|
739
|
+
assert_equal experiment(:simple).alternatives[2].participants, 1
|
740
|
+
end
|
741
|
+
|
672
742
|
def test_no_collection_and_chooses
|
673
743
|
not_collecting!
|
674
744
|
new_ab_test :simple do
|
675
745
|
alternatives :a, :b, :c
|
746
|
+
metrics :coolness
|
676
747
|
end
|
677
748
|
assert !experiment(:simple).showing?(experiment(:simple).alternatives[1])
|
678
749
|
experiment(:simple).chooses(:b)
|
@@ -684,10 +755,11 @@ This experiment did not run long enough to find a clear winner.
|
|
684
755
|
not_collecting!
|
685
756
|
new_ab_test :simple do
|
686
757
|
alternatives :a, :b, :c
|
758
|
+
metrics :coolness
|
687
759
|
end
|
688
|
-
choice = experiment(:simple).choose
|
760
|
+
choice = experiment(:simple).choose.value
|
689
761
|
assert [:a, :b, :c].include?(choice)
|
690
|
-
assert_equal choice, experiment(:simple).choose
|
762
|
+
assert_equal choice, experiment(:simple).choose.value
|
691
763
|
end
|
692
764
|
|
693
765
|
|
@@ -132,5 +132,19 @@ class ExperimentTest < Test::Unit::TestCase
|
|
132
132
|
new_ab_test(:ice_cream_flavor) { metrics :happiness }
|
133
133
|
experiment(:ice_cream_flavor).complete!
|
134
134
|
end
|
135
|
+
|
136
|
+
# -- completion -- #
|
137
|
+
|
138
|
+
# check_completion is called by derived classes, but since it's
|
139
|
+
# part of the base_test I'm testing it here.
|
140
|
+
def test_error_in_check_completion
|
141
|
+
new_ab_test(:ab) { metrics :happiness }
|
142
|
+
e = experiment(:ab)
|
143
|
+
e.complete_if { true }
|
144
|
+
e.stubs(:complete!).raises(RuntimeError, "A forced error")
|
145
|
+
e.expects(:warn)
|
146
|
+
e.stubs(:identity).returns(:b)
|
147
|
+
e.track!(:a, Time.now, 10)
|
148
|
+
end
|
135
149
|
|
136
150
|
end
|
@@ -3179,3 +3179,168 @@ Completed in 7ms (View: 1 | 200 OK [http://:? ]
|
|
3179
3179
|
Processing MainController#index (for at 2011-04-11 15:57:26) [GET]
|
3180
3180
|
Parameters: {" "=>nil}
|
3181
3181
|
Completed in 7ms (View: 1 | 200 OK [http://:? ]
|
3182
|
+
|
3183
|
+
|
3184
|
+
Processing MainController#index (for at 2011-04-25 19:24:33) [GET]
|
3185
|
+
Parameters: {" "=>nil}
|
3186
|
+
Completed in 6ms (View: 1 | 200 OK [http://:? ]
|
3187
|
+
|
3188
|
+
|
3189
|
+
Processing MainController#index (for at 2011-04-25 19:26:00) [GET]
|
3190
|
+
Parameters: {" "=>nil}
|
3191
|
+
Completed in 6ms (View: 1 | 200 OK [http://:? ]
|
3192
|
+
|
3193
|
+
|
3194
|
+
Processing MainController#index (for at 2011-04-25 19:27:11) [GET]
|
3195
|
+
Parameters: {" "=>nil}
|
3196
|
+
Completed in 8ms (View: 1 | 200 OK [http://:? ]
|
3197
|
+
|
3198
|
+
|
3199
|
+
Processing MainController#index (for at 2011-04-25 19:29:07) [GET]
|
3200
|
+
Parameters: {" "=>nil}
|
3201
|
+
Completed in 7ms (View: 1 | 200 OK [http://:? ]
|
3202
|
+
|
3203
|
+
|
3204
|
+
Processing MainController#index (for at 2011-04-25 19:31:28) [GET]
|
3205
|
+
Parameters: {" "=>nil}
|
3206
|
+
Completed in 7ms (View: 1 | 200 OK [http://:? ]
|
3207
|
+
|
3208
|
+
|
3209
|
+
Processing MainController#index (for at 2011-04-25 19:59:03) [GET]
|
3210
|
+
Parameters: {" "=>nil}
|
3211
|
+
Completed in 5ms (View: 1 | 200 OK [http://:? ]
|
3212
|
+
|
3213
|
+
|
3214
|
+
Processing MainController#index (for at 2011-04-25 19:59:52) [GET]
|
3215
|
+
Parameters: {" "=>nil}
|
3216
|
+
Completed in 5ms (View: 1 | 200 OK [http://:? ]
|
3217
|
+
|
3218
|
+
|
3219
|
+
Processing MainController#index (for at 2011-05-28 21:17:06) [GET]
|
3220
|
+
Parameters: {" "=>nil}
|
3221
|
+
Completed in 5ms (View: 1 | 200 OK [http://:? ]
|
3222
|
+
|
3223
|
+
|
3224
|
+
Processing MainController#index (for at 2011-05-28 21:19:49) [GET]
|
3225
|
+
Parameters: {" "=>nil}
|
3226
|
+
Completed in 11ms (View: 1 | 200 OK [http://:? ]
|
3227
|
+
|
3228
|
+
|
3229
|
+
Processing MainController#index (for at 2011-05-28 21:22:33) [GET]
|
3230
|
+
Parameters: {" "=>nil}
|
3231
|
+
Completed in 5ms (View: 1 | 200 OK [http://:? ]
|
3232
|
+
|
3233
|
+
|
3234
|
+
Processing MainController#index (for at 2011-06-08 21:30:59) [GET]
|
3235
|
+
Parameters: {" "=>nil}
|
3236
|
+
Completed in 5ms (View: 1 | 200 OK [http://:? ]
|
3237
|
+
|
3238
|
+
|
3239
|
+
Processing MainController#index (for at 2011-06-16 10:17:11) [GET]
|
3240
|
+
Parameters: {" "=>nil}
|
3241
|
+
Completed in 5ms (View: 1 | 200 OK [http://:? ]
|
3242
|
+
|
3243
|
+
|
3244
|
+
Processing MainController#index (for at 2011-07-18 20:29:45) [GET]
|
3245
|
+
Parameters: {" "=>nil}
|
3246
|
+
Completed in 6ms (View: 1 | 200 OK [http://:? ]
|
3247
|
+
|
3248
|
+
|
3249
|
+
Processing MainController#index (for at 2011-07-18 20:31:56) [GET]
|
3250
|
+
Parameters: {" "=>nil}
|
3251
|
+
Completed in 3ms (View: 1 | 200 OK [http://:? ]
|
3252
|
+
|
3253
|
+
|
3254
|
+
Processing MainController#index (for at 2011-07-18 20:34:07) [GET]
|
3255
|
+
Parameters: {" "=>nil}
|
3256
|
+
Completed in 6ms (View: 1 | 200 OK [http://:? ]
|
3257
|
+
|
3258
|
+
|
3259
|
+
Processing MainController#index (for at 2011-07-18 20:34:35) [GET]
|
3260
|
+
Parameters: {" "=>nil}
|
3261
|
+
Completed in 5ms (View: 1 | 200 OK [http://:? ]
|
3262
|
+
|
3263
|
+
|
3264
|
+
Processing MainController#index (for at 2011-07-18 20:35:51) [GET]
|
3265
|
+
Parameters: {" "=>nil}
|
3266
|
+
Completed in 2ms (View: 1 | 200 OK [http://:? ]
|
3267
|
+
|
3268
|
+
|
3269
|
+
Processing MainController#index (for at 2011-07-18 20:37:01) [GET]
|
3270
|
+
Parameters: {" "=>nil}
|
3271
|
+
Completed in 5ms (View: 1 | 200 OK [http://:? ]
|
3272
|
+
|
3273
|
+
|
3274
|
+
Processing MainController#index (for at 2011-07-18 20:37:43) [GET]
|
3275
|
+
Parameters: {" "=>nil}
|
3276
|
+
Completed in 3ms (View: 1 | 200 OK [http://:? ]
|
3277
|
+
|
3278
|
+
|
3279
|
+
Processing MainController#index (for at 2011-07-18 20:38:23) [GET]
|
3280
|
+
Parameters: {" "=>nil}
|
3281
|
+
Completed in 10ms (View: 2 | 200 OK [http://:? ]
|
3282
|
+
|
3283
|
+
|
3284
|
+
Processing MainController#index (for at 2011-07-18 20:51:29) [GET]
|
3285
|
+
Parameters: {" "=>nil}
|
3286
|
+
Completed in 9ms (View: 2 | 200 OK [http://:? ]
|
3287
|
+
|
3288
|
+
|
3289
|
+
Processing MainController#index (for at 2011-07-18 20:52:27) [GET]
|
3290
|
+
Parameters: {" "=>nil}
|
3291
|
+
Completed in 4ms (View: 1 | 200 OK [http://:? ]
|
3292
|
+
|
3293
|
+
|
3294
|
+
Processing MainController#index (for at 2011-07-18 23:51:49) [GET]
|
3295
|
+
Parameters: {" "=>nil}
|
3296
|
+
Completed in 3ms (View: 1 | 200 OK [http://:? ]
|
3297
|
+
|
3298
|
+
|
3299
|
+
Processing MainController#index (for at 2011-07-19 09:29:26) [GET]
|
3300
|
+
Parameters: {" "=>nil}
|
3301
|
+
Completed in 3ms (View: 1 | 200 OK [http://:? ]
|
3302
|
+
|
3303
|
+
|
3304
|
+
Processing MainController#index (for at 2011-07-19 10:03:46) [GET]
|
3305
|
+
Parameters: {" "=>nil}
|
3306
|
+
Completed in 2ms (View: 1 | 200 OK [http://:? ]
|
3307
|
+
|
3308
|
+
|
3309
|
+
Processing MainController#index (for at 2011-07-19 10:05:27) [GET]
|
3310
|
+
Parameters: {" "=>nil}
|
3311
|
+
Completed in 3ms (View: 1 | 200 OK [http://:? ]
|
3312
|
+
|
3313
|
+
|
3314
|
+
Processing MainController#index (for at 2011-07-19 10:05:58) [GET]
|
3315
|
+
Parameters: {" "=>nil}
|
3316
|
+
Completed in 2ms (View: 1 | 200 OK [http://:? ]
|
3317
|
+
|
3318
|
+
|
3319
|
+
Processing MainController#index (for at 2011-07-19 10:06:23) [GET]
|
3320
|
+
Parameters: {" "=>nil}
|
3321
|
+
Completed in 8ms (View: 1 | 200 OK [http://:? ]
|
3322
|
+
|
3323
|
+
|
3324
|
+
Processing MainController#index (for at 2011-07-19 10:06:43) [GET]
|
3325
|
+
Parameters: {" "=>nil}
|
3326
|
+
Completed in 2ms (View: 1 | 200 OK [http://:? ]
|
3327
|
+
|
3328
|
+
|
3329
|
+
Processing MainController#index (for at 2011-07-19 10:07:19) [GET]
|
3330
|
+
Parameters: {" "=>nil}
|
3331
|
+
Completed in 2ms (View: 1 | 200 OK [http://:? ]
|
3332
|
+
|
3333
|
+
|
3334
|
+
Processing MainController#index (for at 2011-07-19 10:09:19) [GET]
|
3335
|
+
Parameters: {" "=>nil}
|
3336
|
+
Completed in 4ms (View: 1 | 200 OK [http://:? ]
|
3337
|
+
|
3338
|
+
|
3339
|
+
Processing MainController#index (for at 2011-07-20 11:52:11) [GET]
|
3340
|
+
Parameters: {" "=>nil}
|
3341
|
+
Completed in 2ms (View: 1 | 200 OK [http://:? ]
|
3342
|
+
|
3343
|
+
|
3344
|
+
Processing MainController#index (for at 2011-07-20 11:53:47) [GET]
|
3345
|
+
Parameters: {" "=>nil}
|
3346
|
+
Completed in 6ms (View: 1 | 200 OK [http://:? ]
|
data/test/playground_test.rb
CHANGED
@@ -7,4 +7,14 @@ class PlaygroundTest < Test::Unit::TestCase
|
|
7
7
|
assert_equal instance, Vanity.playground
|
8
8
|
end
|
9
9
|
|
10
|
+
def test_be_use_js
|
11
|
+
assert !Vanity.playground.using_js?
|
12
|
+
Vanity.playground.use_js!
|
13
|
+
assert Vanity.playground.using_js?
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_chooses_path_sets_default
|
17
|
+
assert_equal Vanity.playground.add_participant_path, Vanity::Playground::DEFAULT_ADD_PARTICIPANT_PATH
|
18
|
+
end
|
19
|
+
|
10
20
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "test/test_helper"
|
2
|
+
|
3
|
+
class VanityController < ActionController::Base
|
4
|
+
include Vanity::Rails::Dashboard
|
5
|
+
end
|
6
|
+
|
7
|
+
# Pages accessible to everyone, e.g. sign in, community search.
|
8
|
+
class RailsDashboardTest < ActionController::TestCase
|
9
|
+
tests VanityController
|
10
|
+
|
11
|
+
def setup
|
12
|
+
Vanity.playground.collecting = true
|
13
|
+
metric :sugar_high
|
14
|
+
new_ab_test :food do
|
15
|
+
alternatives :apple, :orange
|
16
|
+
metrics :sugar_high
|
17
|
+
identify { '1' }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_add_participant
|
22
|
+
xhr :post, :add_participant, :e => "food", :a => 0
|
23
|
+
assert_response :success
|
24
|
+
assert @response.body.blank?
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_add_participant_no_params
|
28
|
+
xhr :post, :add_participant
|
29
|
+
assert_response :not_found
|
30
|
+
assert @response.body.blank?
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_chooses
|
34
|
+
xhr :post, :chooses, :e => "food", :a => 0
|
35
|
+
assert_response :success
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "test/test_helper"
|
2
|
+
|
3
|
+
class RailsHelperTest < ActionView::TestCase
|
4
|
+
include Vanity::Rails::Helpers
|
5
|
+
|
6
|
+
def setup
|
7
|
+
super
|
8
|
+
metric :sugar_high
|
9
|
+
new_ab_test :pie_or_cake do
|
10
|
+
metrics :sugar_high
|
11
|
+
identify { '1' }
|
12
|
+
alternatives :pie, :cake
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_ab_test_returns_one_of_the_alternatives
|
17
|
+
assert [:pie, :cake].include?(ab_test(:pie_or_cake))
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_ab_test_using_js_returns_the_same_alternative
|
21
|
+
Vanity.playground.use_js!
|
22
|
+
result = ab_test(:pie_or_cake)
|
23
|
+
assert [:pie, :cake].include?(result)
|
24
|
+
10.times do
|
25
|
+
assert result == ab_test(:pie_or_cake)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/test/rails_test.rb
CHANGED
@@ -21,8 +21,22 @@ class UseVanityTest < ActionController::TestCase
|
|
21
21
|
UseVanityController.class_eval do
|
22
22
|
use_vanity :current_user
|
23
23
|
end
|
24
|
+
if ::Rails.respond_to?(:application) # Rails 3 configuration
|
25
|
+
::Rails.application.config.session_options[:domain] = '.foo.bar'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_chooses_sets_alternatives_for_rails_tests
|
30
|
+
experiment(:pie_or_cake).chooses(true)
|
31
|
+
get :index
|
32
|
+
assert_equal 'true', @response.body
|
33
|
+
|
34
|
+
experiment(:pie_or_cake).chooses(false)
|
35
|
+
get :index
|
36
|
+
assert_equal 'false', @response.body
|
24
37
|
end
|
25
38
|
|
39
|
+
|
26
40
|
def test_vanity_cookie_is_persistent
|
27
41
|
get :index
|
28
42
|
assert cookie = @response["Set-Cookie"].find { |c| c[/^vanity_id=/] }
|
@@ -81,22 +95,28 @@ class UseVanityTest < ActionController::TestCase
|
|
81
95
|
|
82
96
|
def test_sets_choices_from_vanity_query_parameter
|
83
97
|
first = experiment(:pie_or_cake).alternatives.first
|
84
|
-
|
98
|
+
fingerprint = experiment(:pie_or_cake).fingerprint(first)
|
85
99
|
10.times do
|
86
100
|
@controller = nil ; setup_controller_request_and_response
|
87
|
-
get :index, :_vanity=>
|
88
|
-
|
101
|
+
get :index, :_vanity => fingerprint
|
102
|
+
assert_equal experiment(:pie_or_cake).choose, experiment(:pie_or_cake).alternatives.first
|
89
103
|
assert experiment(:pie_or_cake).showing?(first)
|
90
104
|
end
|
91
105
|
end
|
92
106
|
|
93
107
|
def test_does_nothing_with_vanity_query_parameter_for_posts
|
108
|
+
experiment(:pie_or_cake).chooses(experiment(:pie_or_cake).alternatives.last.value)
|
94
109
|
first = experiment(:pie_or_cake).alternatives.first
|
95
|
-
|
110
|
+
fingerprint = experiment(:pie_or_cake).fingerprint(first)
|
111
|
+
post :index, :foo => "bar", :_vanity => fingerprint
|
96
112
|
assert_response :success
|
97
113
|
assert !experiment(:pie_or_cake).showing?(first)
|
98
114
|
end
|
99
115
|
|
116
|
+
def test_cookie_domain_from_rails_configuration
|
117
|
+
get :index
|
118
|
+
assert_equal cookies["vanity_id"][:domain], '.foo.bar' if ::Rails.respond_to?(:application)
|
119
|
+
end
|
100
120
|
|
101
121
|
# -- Load path --
|
102
122
|
|
@@ -160,6 +180,55 @@ $stdout << Vanity.playground.connection
|
|
160
180
|
File.unlink "tmp/config/vanity.yml"
|
161
181
|
end
|
162
182
|
|
183
|
+
def test_mongo_connection_from_yaml
|
184
|
+
FileUtils.mkpath "tmp/config"
|
185
|
+
File.open("tmp/config/vanity.yml", "w") do |io|
|
186
|
+
io.write <<-YML
|
187
|
+
mongodb:
|
188
|
+
adapter: mongodb
|
189
|
+
host: localhost
|
190
|
+
port: 27017
|
191
|
+
database: vanity_test
|
192
|
+
YML
|
193
|
+
end
|
194
|
+
|
195
|
+
ENV["RAILS_ENV"] = "mongodb"
|
196
|
+
assert_equal "mongodb://localhost:27017/vanity_test", load_rails(<<-RB)
|
197
|
+
initializer.after_initialize
|
198
|
+
$stdout << Vanity.playground.connection
|
199
|
+
RB
|
200
|
+
ensure
|
201
|
+
File.unlink "tmp/config/vanity.yml"
|
202
|
+
end
|
203
|
+
|
204
|
+
def test_mongodb_replica_set_connection
|
205
|
+
FileUtils.mkpath "tmp/config"
|
206
|
+
File.open("tmp/config/vanity.yml", "w") do |io|
|
207
|
+
io.write <<-YML
|
208
|
+
mongodb:
|
209
|
+
adapter: mongodb
|
210
|
+
hosts:
|
211
|
+
- localhost
|
212
|
+
port: 27017
|
213
|
+
database: vanity_test
|
214
|
+
YML
|
215
|
+
end
|
216
|
+
|
217
|
+
ENV["RAILS_ENV"] = "mongodb"
|
218
|
+
assert_equal "mongodb://localhost:27017/vanity_test", load_rails(<<-RB)
|
219
|
+
initializer.after_initialize
|
220
|
+
$stdout << Vanity.playground.connection
|
221
|
+
RB
|
222
|
+
|
223
|
+
ENV["RAILS_ENV"] = "mongodb"
|
224
|
+
assert_equal "Mongo::ReplSetConnection", load_rails(<<-RB)
|
225
|
+
initializer.after_initialize
|
226
|
+
$stdout << Vanity.playground.connection.mongo.class
|
227
|
+
RB
|
228
|
+
ensure
|
229
|
+
File.unlink "tmp/config/vanity.yml"
|
230
|
+
end
|
231
|
+
|
163
232
|
def test_connection_from_yaml_url
|
164
233
|
FileUtils.mkpath "tmp/config"
|
165
234
|
ENV["RAILS_ENV"] = "production"
|
data/test/test_helper.rb
CHANGED
@@ -6,6 +6,7 @@ require "test/unit"
|
|
6
6
|
require "mocha"
|
7
7
|
require "action_controller"
|
8
8
|
require "action_controller/test_case"
|
9
|
+
require "action_view/test_case"
|
9
10
|
require "active_record"
|
10
11
|
require "initializer"
|
11
12
|
Rails.configuration = Rails::Configuration.new
|
@@ -21,14 +22,11 @@ if $VERBOSE
|
|
21
22
|
end
|
22
23
|
|
23
24
|
class Test::Unit::TestCase
|
24
|
-
include WebMock
|
25
|
+
include WebMock::API
|
25
26
|
|
26
27
|
def setup
|
27
28
|
FileUtils.mkpath "tmp/experiments/metrics"
|
28
29
|
new_playground
|
29
|
-
#WebMock.after_request do |request_signature, response|
|
30
|
-
# puts "Request #{request_signature} was made and #{response} was returned"
|
31
|
-
#end
|
32
30
|
end
|
33
31
|
|
34
32
|
# Call this on teardown. It wipes put the playground and any state held in it
|
@@ -92,7 +90,7 @@ class Test::Unit::TestCase
|
|
92
90
|
Vanity.context = nil
|
93
91
|
FileUtils.rm_rf "tmp"
|
94
92
|
Vanity.playground.connection.flushdb if Vanity.playground.connected?
|
95
|
-
WebMock.
|
93
|
+
WebMock.reset!
|
96
94
|
end
|
97
95
|
|
98
96
|
end
|
@@ -103,7 +101,7 @@ end
|
|
103
101
|
|
104
102
|
|
105
103
|
ActiveRecord::Base.logger = $logger
|
106
|
-
ActiveRecord::Base.establish_connection :adapter=>"
|
104
|
+
ActiveRecord::Base.establish_connection :adapter=>"mysql", :database=>"vanity_test"
|
107
105
|
|
108
106
|
|
109
107
|
class Array
|
data/vanity.gemspec
CHANGED