metry 2.0.5 → 2.1.0

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 (44) hide show
  1. data/History.txt +4 -0
  2. data/Manifest.txt +12 -6
  3. data/Rakefile +5 -0
  4. data/TODO +1 -6
  5. data/example/example.rb +1 -1
  6. data/features/app_tracking.feature +1 -2
  7. data/features/basic_tracking.feature +19 -38
  8. data/features/psycho/dashboard.feature +3 -11
  9. data/features/psycho/experiments.feature +28 -0
  10. data/features/psycho/visitor_tracking.feature +4 -4
  11. data/features/step_definitions/experiments.rb +8 -0
  12. data/features/step_definitions/psycho.rb +14 -0
  13. data/features/step_definitions/tracking.rb +56 -24
  14. data/features/support/env.rb +0 -1
  15. data/features/support/helpers.rb +6 -0
  16. data/lib/metry.rb +12 -5
  17. data/lib/metry/cohort.rb +19 -0
  18. data/lib/metry/event.rb +26 -0
  19. data/lib/metry/experiment.rb +36 -13
  20. data/lib/metry/goal.rb +18 -0
  21. data/lib/metry/psycho.rb +24 -93
  22. data/lib/metry/psycho/dashboard.erb +5 -5
  23. data/lib/metry/psycho/edit_goal.erb +1 -1
  24. data/lib/metry/psycho/experiment.erb +25 -0
  25. data/lib/metry/psycho/new_goal.erb +1 -1
  26. data/lib/metry/psycho/visitor.erb +4 -1
  27. data/lib/metry/psycho/visitors.erb +6 -0
  28. data/lib/metry/rack/tracking.rb +19 -18
  29. data/lib/metry/visitor.rb +30 -0
  30. data/radiant/example/features/metry.feature +21 -43
  31. data/radiant/example/features/step_definitions/tracking.rb +56 -24
  32. data/radiant/example/features/step_definitions/web.rb +0 -7
  33. data/radiant/example/features/support/env.rb +7 -3
  34. data/radiant/example/features/support/helpers.rb +6 -0
  35. data/radiant/extension/lib/metry_tags.rb +3 -1
  36. data/test/shared.rb +3 -1
  37. data/test/test_experiment.rb +104 -0
  38. metadata +45 -9
  39. data/features/psycho/goals.feature +0 -53
  40. data/features/step_definitions/goals.rb +0 -3
  41. data/lib/metry/psycho/goal.erb +0 -9
  42. data/lib/metry/storage.rb +0 -142
  43. data/radiant/example/features/step_definitions/experiments.rb +0 -12
  44. data/test/test_storage.rb +0 -25
@@ -1,3 +1,7 @@
1
+ === 2.1.0 / 2009-08-13
2
+
3
+ * Added experiment/cohort analysis.
4
+
1
5
  === 2.0.5 / 2009-08-09
2
6
 
3
7
  * Added missed files.
@@ -8,24 +8,30 @@ example/example.rb
8
8
  features/app_tracking.feature
9
9
  features/basic_tracking.feature
10
10
  features/psycho/dashboard.feature
11
- features/psycho/goals.feature
11
+ features/psycho/experiments.feature
12
12
  features/psycho/visitor_tracking.feature
13
13
  features/sample_application.feature
14
- features/step_definitions/goals.rb
14
+ features/step_definitions/experiments.rb
15
+ features/step_definitions/psycho.rb
15
16
  features/step_definitions/tracking.rb
16
17
  features/step_definitions/web.rb
17
18
  features/support/env.rb
19
+ features/support/helpers.rb
18
20
  lib/metry.rb
21
+ lib/metry/cohort.rb
22
+ lib/metry/event.rb
19
23
  lib/metry/experiment.rb
24
+ lib/metry/goal.rb
20
25
  lib/metry/psycho.rb
21
26
  lib/metry/psycho/dashboard.erb
22
27
  lib/metry/psycho/edit_goal.erb
23
- lib/metry/psycho/goal.erb
28
+ lib/metry/psycho/experiment.erb
24
29
  lib/metry/psycho/layout.erb
25
30
  lib/metry/psycho/new_goal.erb
26
31
  lib/metry/psycho/visitor.erb
32
+ lib/metry/psycho/visitors.erb
27
33
  lib/metry/rack/tracking.rb
28
- lib/metry/storage.rb
34
+ lib/metry/visitor.rb
29
35
  radiant/example/CHANGELOG
30
36
  radiant/example/CONTRIBUTORS
31
37
  radiant/example/INSTALL
@@ -43,11 +49,11 @@ radiant/example/config/routes.rb
43
49
  radiant/example/db/schema.rb
44
50
  radiant/example/features/metry.feature
45
51
  radiant/example/features/psycho.feature
46
- radiant/example/features/step_definitions/experiments.rb
47
52
  radiant/example/features/step_definitions/radiant.rb
48
53
  radiant/example/features/step_definitions/tracking.rb
49
54
  radiant/example/features/step_definitions/web.rb
50
55
  radiant/example/features/support/env.rb
56
+ radiant/example/features/support/helpers.rb
51
57
  radiant/example/public/.htaccess
52
58
  radiant/example/public/404.html
53
59
  radiant/example/public/500.html
@@ -114,7 +120,7 @@ radiant/extension/lib/metry_tags.rb
114
120
  radiant/extension/lib/tasks/metry_extension_tasks.rake
115
121
  radiant/extension/metry_extension.rb
116
122
  test/shared.rb
117
- test/test_storage.rb
123
+ test/test_experiment.rb
118
124
  vendor/webrat/.document
119
125
  vendor/webrat/History.txt
120
126
  vendor/webrat/MIT-LICENSE.txt
data/Rakefile CHANGED
@@ -1,9 +1,14 @@
1
+ ENV["RUBY_FLAGS"] = "-I#{%w(lib ext bin test).join(File::PATH_SEPARATOR)}"
2
+
1
3
  require 'rubygems'
2
4
  require 'hoe'
3
5
 
4
6
  Hoe.spec 'metry' do
5
7
  developer('Nathaniel Talbott', 'nathaniel@terralien.com')
6
8
  self.rubyforge_name = 'terralien'
9
+ extra_deps << ['mongomapper', '~> 0.3']
10
+ extra_deps << ['mongodb-mongo', '~> 0.10']
11
+ extra_deps << ['mongodb-mongo_ext', '~> 0.4']
7
12
  end
8
13
 
9
14
  require 'cucumber/rake/task'
data/TODO CHANGED
@@ -1,10 +1,5 @@
1
- Limit visitors on dashboard to 10 most recent
2
- Add full listing of visitors
3
- Show more details about visitors
4
- Add referrer to event display on visitor pages
5
- Add display of last 10 events to dashboard
6
1
  Show goal conversion for each experiment
7
- Allow manually viewing a particular alternatively
2
+ Allow manually viewing a particular alternative
8
3
 
9
4
  More unit tests
10
5
 
@@ -18,5 +18,5 @@ get '/subpage' do
18
18
  end
19
19
 
20
20
  get '/extra' do
21
- request.env["metry.event"]["extra"] = params[:track]
21
+ request.env["metry.event"].extra["extra"] = params[:track]
22
22
  end
@@ -6,6 +6,5 @@ Feature: Application Tracking
6
6
  Scenario: Track an additional facet
7
7
  Given an empty tracking database
8
8
  When I view "/extra?track=stuff"
9
- Then there should be a tracking event "1":
10
- | key | value |
9
+ Then tracking event #1 extra should contain:
11
10
  | extra | stuff |
@@ -20,73 +20,54 @@ Feature: Access Tracking
20
20
  Scenario: Basic request data is tracked
21
21
  When I view "/"
22
22
  And I view "/subpage"
23
- Then there should be a tracking event "1":
24
- | key | value |
23
+ Then tracking event #1 should contain:
25
24
  | path | / |
26
- | time | _exists_ |
27
- And there should be a tracking event "2":
28
- | key | value |
25
+ | created_at | _exists_ |
26
+ And tracking event #2 should contain:
29
27
  | path | /subpage |
30
- | time | _exists_ |
28
+ | created_at | _exists_ |
31
29
 
32
30
  Scenario: New visitor is tracked
33
31
  When I view "/"
34
32
  And I view "/subpage"
35
- Then there should be a tracking event "1":
36
- | key | value |
37
- | visitor | 1 |
38
- And there should be a tracking event "2":
39
- | key | value |
40
- | visitor | 1 |
41
- And there should be a visitor "1"
33
+ Then there should be a tracking event #1 with visitor #1
34
+ And there should be a tracking event #2 with visitor #1
35
+ And there should be a visitor #1
42
36
 
43
37
  Scenario: Two visitors are tracked
44
38
  Given I view "/"
45
39
  When I am a new visitor
46
40
  Given I view "/"
47
- Then there should be a tracking event "1":
48
- | key | value |
49
- | visitor | 1 |
50
- And there should be a tracking event "2":
51
- | key | value |
52
- | visitor | 2 |
41
+ Then there should be a tracking event #1 with visitor #1
42
+ Then there should be a tracking event #2 with visitor #2
53
43
  And there should be 2 visitors
54
- And there should be a visitor "1"
55
- And there should be a visitor "2"
56
44
 
57
45
  Scenario: All facets should be tracked
58
46
  When I view "/"
59
- Then there should be a tracking event "1":
60
- | key | value |
61
- | path | / |
62
- | time | _exists_ |
63
- | ip | 127.0.0.1 |
64
- | host | example.org |
47
+ Then tracking event #1 should contain:
48
+ | path | / |
49
+ | created_at | _exists_ |
50
+ | ip | 127.0.0.1 |
51
+ | host | www.example.com |
65
52
 
66
53
  Scenario: path should include query string
67
54
  When I view "/?here=there"
68
- Then there should be a tracking event "1":
69
- | key | value |
55
+ Then tracking event #1 should contain:
70
56
  | path | /?here=there |
71
57
 
72
58
  Scenario: Should track status codes
73
59
  When I view "/"
74
60
  And I view "/missing"
75
- Then there should be a tracking event "1":
76
- | key | value |
61
+ Then tracking event #1 should contain:
77
62
  | status | 200 |
78
- Then there should be a tracking event "2":
79
- | key | value |
63
+ Then tracking event #2 should contain:
80
64
  | status | 404 |
81
65
 
82
66
  Scenario: Should track method
83
67
  When I view "/"
84
68
  And I post to "/post":
85
- | key | value |
86
69
  | bogus | bogus |
87
- Then there should be a tracking event "1":
88
- | key | value |
70
+ Then tracking event #1 should contain:
89
71
  | method | GET |
90
- Then there should be a tracking event "2":
91
- | key | value |
72
+ Then tracking event #2 should contain:
92
73
  | method | POST |
@@ -2,16 +2,8 @@ Feature: Psycho Dashboard
2
2
 
3
3
  Scenario: Basics
4
4
  Given an empty tracking database
5
- And I add a goal named "sweet" with path "/"
6
- And I am a new visitor
7
- And I view "/"
8
- And I view "/subpage"
9
- And I am a new visitor
10
- And I view "/"
5
+ And I add an experiment "sweet"
11
6
  When I view "/admin/metry"
12
- Then I should see "Goals"
13
- And I should see "sweet: 2 visits"
14
- And I should see "Recent Visitors"
15
- And I should see "Visitor 1"
16
- And I should see "Visitor 2"
7
+ Then I should see "Experiments"
8
+ And I should see "sweet"
17
9
 
@@ -0,0 +1,28 @@
1
+ Feature: Track Experiments
2
+
3
+ Background:
4
+ Given an empty tracking database
5
+ And I add an experiment "Fred"
6
+
7
+ Scenario: Add a goal
8
+ Given I view "/admin/metry"
9
+ And I follow "Fred"
10
+ And I follow "New Goal"
11
+ And I fill in "name" with "Cool"
12
+ And I fill in "path" with "/goal"
13
+ And I press "Create"
14
+ Then I should be on the page for experiment #1
15
+ And I should see "Cool"
16
+ And I should see "Path: /goal"
17
+
18
+ Scenario: Edit a Goal
19
+ Given I add a goal named "Bogus" to experiment "Fred" with path "/"
20
+ When I view "/admin/metry"
21
+ And I follow "Fred"
22
+ And I follow "Edit"
23
+ And I fill in "name" with "Right"
24
+ And I fill in "path" with "/subpage"
25
+ And I press "Save"
26
+ Then I should be on the page for experiment #1
27
+ And I should see "Right"
28
+ And I should see "Path: /subpage"
@@ -12,8 +12,8 @@ Feature: Psycho Visitor Tracking
12
12
  And I am a new visitor
13
13
  And I view "/"
14
14
  When I view "/admin/metry"
15
- Then I should see "Visitor 1"
16
- And I should see "Visitor 2"
15
+ Then I should see visitor #1
16
+ And I should see visitor #2
17
17
 
18
18
  Scenario: View visitor detail
19
19
  Given I view "/"
@@ -21,7 +21,7 @@ Feature: Psycho Visitor Tracking
21
21
  And I am a new visitor
22
22
  And I view "/"
23
23
  When I view "/admin/metry"
24
- And I follow "Visitor 1"
24
+ And I follow "Visitor"
25
25
  Then I should see "/"
26
26
  And I should see "/subpage"
27
27
 
@@ -29,4 +29,4 @@ Feature: Psycho Visitor Tracking
29
29
  Given I view "/admin/metry"
30
30
  And I view "/admin/metry"
31
31
  When I view "/admin/metry"
32
- Then I should not see "Visitor 1"
32
+ Then I should see "0 events"
@@ -0,0 +1,8 @@
1
+ Given /^I add an experiment "([^\"]*)"$/ do |name|
2
+ Metry::Experiment.create(:name => name)
3
+ end
4
+
5
+ Given /^I add a goal named "([^\"]*)" to experiment "([^\"]*)" with path "([^\"]*)"$/ do |name, experiment, path|
6
+ experiment = Metry::Experiment.find(:first, :conditions => {:name => experiment})
7
+ experiment.goals << Metry::Goal.create(:name => name, :path => path)
8
+ end
@@ -0,0 +1,14 @@
1
+ Then /^I should see visitor #(\d+)$/ do |index|
2
+ visitor = at(Metry::Visitor, index)
3
+ assert_contain "Visitor #{visitor.id}"
4
+ end
5
+
6
+ Then /^I should not see visitor #(\d+)$/ do |index|
7
+ visitor = at(Metry::Visitor, index)
8
+ assert_not_contain "Visitor #{visitor.id}"
9
+ end
10
+
11
+ Then /^I should be on the page for experiment #(\d+)$/ do |index|
12
+ experiment = at(Metry::Experiment, index)
13
+ assert_equal "/admin/metry/experiments/#{experiment.id}", current_url
14
+ end
@@ -1,43 +1,75 @@
1
1
  Given /^an empty tracking database$/ do
2
- Metry.current.clear
2
+ Metry.clear
3
3
  end
4
4
 
5
5
  Then /^there should be (\d+) tracking events?$/ do |event_count|
6
- assert_equal(event_count.to_i, Metry.current.event_count)
6
+ assert_equal(event_count.to_i, Metry::Event.count)
7
7
  end
8
8
 
9
9
  Then /^there should be (\d+) visitors$/ do |visitor_count|
10
- assert_equal(visitor_count.to_i, Metry.current.visitor_count)
10
+ assert_equal(visitor_count.to_i, Metry::Visitor.count)
11
11
  end
12
12
 
13
- When /^there should be a tracking event "(\d+)":$/ do |id, table|
14
- event = Metry.current.event(id)
15
- assert event, "Unable to lookup event #{id}."
16
- table.hashes.each do |hash|
17
- expected = hash["value"]
13
+ Then /^tracking event #(\d+) should contain:$/ do |index, table|
14
+ event = at(Metry::Event, index)
15
+ assert event, "Unable to lookup event at #{index}."
16
+ table.rows_hash.each do |key, expected|
18
17
  case expected
19
18
  when "_exists_"
20
- assert event[hash["key"]], "Key #{hash["key"]} does not exist."
19
+ assert event.send(key), "Key #{key} does not exist."
21
20
  else
22
- assert_equal expected, event[hash["key"]], "Key #{hash["key"]} does not match."
21
+ assert_equal expected, event.send(key), "Key #{key} does not match."
23
22
  end
24
23
  end
25
24
  end
26
25
 
27
- Then /^there should be a visitor "([^\"]*)":$/ do |id, table|
28
- visitor = Metry.current.visitor(id)
29
- assert visitor, "Unable to lookup visitor #{id}."
30
- table.hashes.each do |hash|
31
- expected = hash["value"]
32
- case expected
33
- when "_exists_"
34
- assert visitor[hash["key"]], "Key #{hash["key"]} does not exist."
35
- else
36
- assert_equal expected, visitor[hash["key"]], "Key #{hash["key"]} does not match."
37
- end
26
+ Then /^tracking event #(\d+) extra should contain:$/ do |index, table|
27
+ event = at(Metry::Event, index)
28
+ table.rows_hash.each do |key, expected|
29
+ assert_equal expected, event.extra[key]
38
30
  end
39
31
  end
40
32
 
41
- Then /^there should be a visitor "([^\"]*)"$/ do |id|
42
- assert Metry.current.visitor(id)
43
- end
33
+ Then /^there should be a tracking event #(\d+) with visitor #(\d+)$/ do |event_index, visitor_index|
34
+ event = at(Metry::Event, event_index)
35
+ visitor = at(Metry::Visitor, visitor_index)
36
+ assert_equal event.visitor, visitor
37
+ end
38
+
39
+ Then /^there should be a visitor #(\d+)$/ do |index|
40
+ assert at(Metry::Visitor, index)
41
+ end
42
+
43
+ Then /^visitor #(\d+) should have experiment "([^\"]*)" with "([^\"]*)"$/ do |index, experiment, alternative|
44
+ visitor = at(Metry::Visitor, index)
45
+ experiment = Metry::Experiment.find(:first, :conditions => {:name => experiment})
46
+ assert experiment.cohort_for(visitor)
47
+ end
48
+
49
+ Then /^event #(\d+) should have experiment "([^\"]*)" with "([^\"]*)"$/ do |index, experiment, alternative|
50
+ event = at(Metry::Event, index)
51
+ experiment = Metry::Experiment.find(:first, :conditions => {:name => experiment})
52
+ assert_equal alternative, event.experiments[experiment.id]
53
+ end
54
+
55
+ Then /^I should see the same page (\d+) times$/ do |count|
56
+ expected_body = webrat.response_body
57
+ count.to_i.times do
58
+ When(%(I view "#{current_url}"))
59
+ assert_equal expected_body, webrat.response_body
60
+ end
61
+ end
62
+
63
+ When /^(\d+) visitors view "([^\"]*)"$/ do |count, path|
64
+ @alternatives = Hash.new(0)
65
+ count.to_i.times do
66
+ visit(path)
67
+ @alternatives[webrat.response_body] += 1
68
+ clear_cookies
69
+ end
70
+ end
71
+
72
+ Then /^there should be (\d+) alternatives each displayed at least (\d+) times$/ do |alternatives, minimum|
73
+ assert_equal alternatives.to_i, @alternatives.size
74
+ assert @alternatives.values.all?{|e| e >= minimum.to_i}
75
+ end
@@ -16,7 +16,6 @@ World(Webrat::Methods)
16
16
  World(Webrat::Matchers)
17
17
 
18
18
  require 'metry'
19
- Metry::Storage.predictable_keys = true
20
19
 
21
20
  require File.dirname(__FILE__) + '/../../example/example.rb'
22
21
  def app
@@ -0,0 +1,6 @@
1
+ module CucumberHelpers
2
+ def at(model, index)
3
+ model.find(:all, :order => 'created_at')[index.to_i-1]
4
+ end
5
+ end
6
+ World(CucumberHelpers)
@@ -1,18 +1,25 @@
1
1
  $: << File.dirname(__FILE__)
2
2
 
3
- require 'metry/storage'
3
+ require 'mongomapper'
4
+
5
+ require 'metry/event'
6
+ require 'metry/visitor'
7
+ require 'metry/goal'
4
8
  require 'metry/rack/tracking'
5
9
  require 'metry/experiment'
10
+ require 'metry/cohort'
6
11
  require 'metry/psycho'
7
12
 
8
13
  module Metry
9
- VERSION = '2.0.5'
14
+ VERSION = '2.1.0'
10
15
 
11
16
  def self.init(dbname)
12
- @storage = Storage.new(dbname)
17
+ MongoMapper.database = dbname
13
18
  end
14
19
 
15
- def self.current
16
- @storage
20
+ def self.clear
21
+ [Metry::Event, Metry::Visitor, Metry::Goal, Metry::Experiment].each do |m|
22
+ m.delete_all
23
+ end
17
24
  end
18
25
  end