vanity 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +34 -19
- data/README.rdoc +19 -15
- data/lib/vanity/commands/report.rb +11 -4
- data/lib/vanity/experiment/ab_test.rb +149 -108
- data/lib/vanity/experiment/base.rb +42 -53
- data/lib/vanity/playground.rb +48 -24
- data/lib/vanity/rails.rb +2 -1
- data/lib/vanity/rails/dashboard.rb +15 -0
- data/lib/vanity/rails/helpers.rb +19 -32
- data/lib/vanity/rails/testing.rb +3 -1
- data/lib/vanity/templates/_ab_test.erb +7 -5
- data/lib/vanity/templates/_experiment.erb +5 -0
- data/lib/vanity/templates/_experiments.erb +2 -7
- data/lib/vanity/templates/_report.erb +14 -14
- data/lib/vanity/templates/vanity.css +13 -0
- data/test/ab_test_test.rb +147 -110
- data/test/experiment_test.rb +15 -22
- data/test/experiments/age_and_zipcode.rb +17 -2
- data/test/experiments/null_abc.rb +1 -1
- data/test/playground_test.rb +53 -31
- data/test/rails_test.rb +1 -1
- data/test/test_helper.rb +2 -0
- data/vanity.gemspec +2 -2
- metadata +7 -6
- data/lib/vanity/rails/console.rb +0 -14
- data/lib/vanity/templates/_vanity.css +0 -13
data/test/experiment_test.rb
CHANGED
@@ -1,45 +1,38 @@
|
|
1
1
|
require "test/test_helper"
|
2
2
|
|
3
|
-
class ExperimentTest < MiniTest::
|
4
|
-
|
5
|
-
|
6
|
-
assert_equal "Green Button/Alert",
|
7
|
-
assert_equal :green_button_alert,
|
3
|
+
class ExperimentTest < MiniTest::Unit::TestCase
|
4
|
+
def test_experiment_mapping_name_to_id
|
5
|
+
experiment = Vanity.playground.define("Green Button/Alert", :ab_test) { }
|
6
|
+
assert_equal "Green Button/Alert", experiment.name
|
7
|
+
assert_equal :green_button_alert, experiment.id
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
expects(:xmts).returns("x")
|
13
|
-
end
|
14
|
-
assert_equal "x", experiment(:green_button).xmts
|
15
|
-
end
|
16
|
-
|
17
|
-
it "saves experiments after defining it" do
|
18
|
-
experiment :green_button do
|
10
|
+
def test_saving_experiment_after_definition
|
11
|
+
Vanity.playground.define :simple, :ab_test do
|
19
12
|
expects(:save)
|
20
13
|
end
|
21
14
|
end
|
22
15
|
|
23
|
-
|
24
|
-
|
16
|
+
def test_experiment_has_created_timestamp
|
17
|
+
Vanity.playground.define(:simple, :ab_test) {}
|
25
18
|
assert_instance_of Time, experiment(:simple).created_at
|
26
19
|
assert_in_delta experiment(:simple).created_at.to_i, Time.now.to_i, 1
|
27
20
|
end
|
28
|
-
|
29
|
-
|
21
|
+
|
22
|
+
def test_experiment_keeps_created_timestamp_across_definitions
|
30
23
|
early, late = Time.now - 1.day, Time.now
|
31
24
|
Time.expects(:now).once.returns(early)
|
32
|
-
|
25
|
+
Vanity.playground.define(:simple, :ab_test) {}
|
33
26
|
assert_equal early.to_i, experiment(:simple).created_at.to_i
|
34
27
|
|
35
28
|
new_playground
|
36
29
|
Time.expects(:now).once.returns(late)
|
37
|
-
|
30
|
+
Vanity.playground.define(:simple, :ab_test) {}
|
38
31
|
assert_equal early.to_i, experiment(:simple).created_at.to_i
|
39
32
|
end
|
40
33
|
|
41
|
-
|
42
|
-
|
34
|
+
def test_experiment_has_description
|
35
|
+
Vanity.playground.define :simple, :ab_test do
|
43
36
|
description "Simple experiment"
|
44
37
|
end
|
45
38
|
assert_equal "Simple experiment", experiment(:simple).description
|
@@ -1,3 +1,18 @@
|
|
1
|
-
|
2
|
-
description
|
1
|
+
ab_test "Age and Zipcode" do
|
2
|
+
description <<-TEXT
|
3
|
+
Testing new registration form that asks for age and zipcode. Option A presents
|
4
|
+
the existing form, and option B adds age and zipcode fields.
|
5
|
+
|
6
|
+
We know option B will convert less, but higher quality leads. If we lose less
|
7
|
+
than 20% conversions, we're going to switch to option B.
|
8
|
+
TEXT
|
9
|
+
|
10
|
+
complete_if do
|
11
|
+
alternatives.all? { |alt| alt.participants > 100 }
|
12
|
+
end
|
13
|
+
outcome_is do
|
14
|
+
one_field = alternative(false)
|
15
|
+
three_fields = alternative(true)
|
16
|
+
three_fields.conversion_rate >= 0.8 * one_field.conversion_rate ? three_fields : one_field
|
17
|
+
end
|
3
18
|
end
|
data/test/playground_test.rb
CHANGED
@@ -1,67 +1,89 @@
|
|
1
1
|
require "test/test_helper"
|
2
2
|
|
3
|
-
class PlaygroundTest < MiniTest::
|
4
|
-
|
3
|
+
class PlaygroundTest < MiniTest::Unit::TestCase
|
4
|
+
def setup
|
5
5
|
@namespace = "vanity:0"
|
6
6
|
end
|
7
7
|
|
8
|
-
|
8
|
+
def test_has_one_global_instance
|
9
9
|
assert instance = Vanity.playground
|
10
10
|
assert_equal instance, Vanity.playground
|
11
11
|
end
|
12
12
|
|
13
|
-
|
13
|
+
def test_playground_namespace
|
14
14
|
assert @namespace, Vanity.playground.namespace
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
|
18
|
+
# -- Loading experiments --
|
19
|
+
|
20
|
+
def test_fails_if_cannot_load_named_experiment
|
21
|
+
assert_raises LoadError do
|
19
22
|
experiment("Green button")
|
20
23
|
end
|
21
24
|
end
|
22
25
|
|
23
|
-
|
24
|
-
Vanity.playground.
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
def test_loading_experiment
|
27
|
+
Vanity.playground.load_path = Dir.tmpdir
|
28
|
+
File.open File.join(Dir.tmpdir, "green_button.rb"), "w" do |f|
|
29
|
+
f.write <<-RUBY
|
30
|
+
ab_test "Green Button" do
|
31
|
+
def xmts
|
32
|
+
"x"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
RUBY
|
28
36
|
end
|
37
|
+
assert_equal "x", experiment(:green_button).xmts
|
29
38
|
end
|
30
39
|
|
31
|
-
|
32
|
-
Vanity.playground.
|
40
|
+
def test_fails_if_error_loading_experiment
|
41
|
+
Vanity.playground.load_path = Dir.tmpdir
|
42
|
+
File.open File.join(Dir.tmpdir, "green_button.rb"), "w" do |f|
|
43
|
+
f.write "fail 'yawn!'"
|
44
|
+
end
|
33
45
|
assert_raises LoadError do
|
34
|
-
experiment(
|
46
|
+
experiment(:green_button)
|
35
47
|
end
|
36
48
|
end
|
37
49
|
|
38
|
-
|
39
|
-
playground =
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
50
|
+
def test_complains_if_not_defined_where_expected
|
51
|
+
Vanity.playground.load_path = Dir.tmpdir
|
52
|
+
File.open File.join(Dir.tmpdir, "green_button.rb"), "w" do |f|
|
53
|
+
f.write ""
|
54
|
+
end
|
55
|
+
assert_raises LoadError do
|
56
|
+
experiment("Green button")
|
44
57
|
end
|
45
|
-
assert_equal "x", experiment("Green button").xmts
|
46
58
|
end
|
47
59
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
assert
|
52
|
-
|
60
|
+
def test_reloading_experiments
|
61
|
+
Vanity.playground.define(:ab, :ab_test) {}
|
62
|
+
Vanity.playground.define(:cd, :ab_test) {}
|
63
|
+
assert 2, Vanity.playground.experiments.count
|
64
|
+
Vanity.playground.reload!
|
65
|
+
assert_empty Vanity.playground.experiments
|
53
66
|
end
|
54
67
|
|
55
|
-
|
56
|
-
|
68
|
+
# -- Defining experiment --
|
69
|
+
|
70
|
+
def test_can_access_experiment_by_name_or_id
|
71
|
+
exp = Vanity.playground.define(:green_button, :ab_test) { }
|
72
|
+
assert_equal exp, experiment("Green Button")
|
73
|
+
assert_equal exp, experiment(:green_button)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_fail_when_defining_same_experiment_twice
|
77
|
+
Vanity.playground.define("Green Button", :ab_test) { }
|
57
78
|
assert_raises RuntimeError do
|
58
|
-
|
79
|
+
Vanity.playground.define("Green Button", :ab_test) { }
|
59
80
|
end
|
60
81
|
end
|
61
82
|
|
62
|
-
|
63
|
-
|
83
|
+
def test_uses_playground_namespace_for_experiment
|
84
|
+
Vanity.playground.define(:green_button, :ab_test) { }
|
64
85
|
assert_equal "#{@namespace}:green_button", experiment(:green_button).send(:key)
|
65
86
|
assert_equal "#{@namespace}:green_button:participants", experiment(:green_button).send(:key, "participants")
|
66
87
|
end
|
88
|
+
|
67
89
|
end
|
data/test/rails_test.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -5,6 +5,7 @@ require "minitest/spec"
|
|
5
5
|
require "mocha"
|
6
6
|
require "action_controller"
|
7
7
|
require "action_controller/test_case"
|
8
|
+
require "initializer"
|
8
9
|
require "lib/vanity/rails"
|
9
10
|
MiniTest::Unit.autorun
|
10
11
|
|
@@ -31,3 +32,4 @@ end
|
|
31
32
|
ActionController::Routing::Routes.draw do |map|
|
32
33
|
map.connect ':controller/:action/:id'
|
33
34
|
end
|
35
|
+
Rails.configuration = Rails::Configuration.new
|
data/vanity.gemspec
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "vanity"
|
3
|
-
spec.version = "0.
|
3
|
+
spec.version = "0.4.0"
|
4
4
|
spec.author = "Assaf Arkin"
|
5
5
|
spec.email = "assaf@labnotes.org"
|
6
|
-
spec.homepage = "http://
|
6
|
+
spec.homepage = "http://vanity.labnotes.org"
|
7
7
|
spec.summary = "Experience Driven Development framework for Rails"
|
8
8
|
spec.description = "Mirror, mirror on the wall ..."
|
9
9
|
spec.post_install_message = "To get started run vanity --help"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vanity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Assaf Arkin
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-19 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -29,14 +29,15 @@ files:
|
|
29
29
|
- lib/vanity/experiment/ab_test.rb
|
30
30
|
- lib/vanity/experiment/base.rb
|
31
31
|
- lib/vanity/playground.rb
|
32
|
-
- lib/vanity/rails/
|
32
|
+
- lib/vanity/rails/dashboard.rb
|
33
33
|
- lib/vanity/rails/helpers.rb
|
34
34
|
- lib/vanity/rails/testing.rb
|
35
35
|
- lib/vanity/rails.rb
|
36
36
|
- lib/vanity/templates/_ab_test.erb
|
37
|
+
- lib/vanity/templates/_experiment.erb
|
37
38
|
- lib/vanity/templates/_experiments.erb
|
38
39
|
- lib/vanity/templates/_report.erb
|
39
|
-
- lib/vanity/templates/
|
40
|
+
- lib/vanity/templates/vanity.css
|
40
41
|
- lib/vanity.rb
|
41
42
|
- vendor/redis-0.1/lib/dist_redis.rb
|
42
43
|
- vendor/redis-0.1/lib/hash_ring.rb
|
@@ -61,13 +62,13 @@ files:
|
|
61
62
|
- README.rdoc
|
62
63
|
- vanity.gemspec
|
63
64
|
has_rdoc: true
|
64
|
-
homepage: http://
|
65
|
+
homepage: http://vanity.labnotes.org
|
65
66
|
licenses: []
|
66
67
|
|
67
68
|
post_install_message: To get started run vanity --help
|
68
69
|
rdoc_options:
|
69
70
|
- --title
|
70
|
-
- Vanity 0.
|
71
|
+
- Vanity 0.4.0
|
71
72
|
- --main
|
72
73
|
- README.rdoc
|
73
74
|
- --webcvs
|
data/lib/vanity/rails/console.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
module Vanity
|
2
|
-
module Rails
|
3
|
-
module ConsoleActions
|
4
|
-
def index
|
5
|
-
render Vanity.template("_report"), content_type: Mime::HTML, layout: true
|
6
|
-
end
|
7
|
-
|
8
|
-
def chooses
|
9
|
-
experiment(params[:e]).chooses(experiment(params[:e]).alternatives[params[:a].to_i].value)
|
10
|
-
redirect_to :back
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
<style>
|
2
|
-
.vanity .experiments { list-style: none; margin: 0; padding: 0 }
|
3
|
-
.vanity .experiment { padding-bottom: 1em; margin: 0 0 1em 0; border-bottom: 1px dashed #ddd }
|
4
|
-
.vanity .experiment .type { margin-left: .3em; color: #bbb; font-size: .8em; font-weight: normal }
|
5
|
-
.vanity .experiment table { border-collapse: collapse; table-layout: fixed; width: 100%; border-bottom: 1px solid #ccc; margin: 1em 0 0 0 }
|
6
|
-
.vanity .experiment td { padding: .5em; border-top: 1px solid #ccc }
|
7
|
-
.vanity .experiment .choice td { font-weight: bold; background: #f0f0f8 }
|
8
|
-
.vanity .experiment td.option { width: 5em; white-space: nowrap; overflow: hidden }
|
9
|
-
.vanity .experiment td.value { width: 8em; white-space: nowrap; overflow: hidden }
|
10
|
-
.vanity .experiment td.action { width: 6em; overflow: hidden; text-align: center }
|
11
|
-
.vanity .experiment caption { caption-side: bottom; padding: .5em; background: transparent; margin-bottom: 1em; text-align: left }
|
12
|
-
.vanity .experiment .meta { color: #444; font-style: italic }
|
13
|
-
</style>
|