traffic_patterns 0.0.0 → 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.
- data/Rakefile +4 -1
- data/VERSION +1 -1
- data/lib/traffic_patterns.rb +64 -0
- data/test/fixtures/four_actions.log +54 -0
- data/test/fixtures/two_actions.log +15 -0
- data/test/test_traffic_patterns.rb +83 -2
- data/traffic_patterns.gemspec +9 -4
- metadata +15 -3
    
        data/Rakefile
    CHANGED
    
    | @@ -10,8 +10,9 @@ begin | |
| 10 10 | 
             
                gem.email = "nick@smartlogicsolutions.com"
         | 
| 11 11 | 
             
                gem.homepage = "http://github.com/ngauthier/traffic_patterns"
         | 
| 12 12 | 
             
                gem.authors = ["Nick Gauthier"]
         | 
| 13 | 
            -
                gem.add_development_dependency " | 
| 13 | 
            +
                gem.add_development_dependency "shoulda", ">= 2.10.2"
         | 
| 14 14 | 
             
                gem.add_dependency "slow-actions", ">= 0.3.4"
         | 
| 15 | 
            +
                gem.add_dependency "Ruby-yUML", ">= 0.1.0"
         | 
| 15 16 | 
             
                # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
         | 
| 16 17 | 
             
              end
         | 
| 17 18 | 
             
              Jeweler::GemcutterTasks.new
         | 
| @@ -52,3 +53,5 @@ Rake::RDocTask.new do |rdoc| | |
| 52 53 | 
             
              rdoc.rdoc_files.include('README*')
         | 
| 53 54 | 
             
              rdoc.rdoc_files.include('lib/**/*.rb')
         | 
| 54 55 | 
             
            end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
             | 
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            0.0. | 
| 1 | 
            +
            0.0.1
         | 
    
        data/lib/traffic_patterns.rb
    CHANGED
    
    | @@ -0,0 +1,64 @@ | |
| 1 | 
            +
            require 'slow_actions'
         | 
| 2 | 
            +
            require 'yuml'
         | 
| 3 | 
            +
            class TrafficPatterns < SlowActions
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              def parse_file(*args)
         | 
| 6 | 
            +
                super(*args)
         | 
| 7 | 
            +
                find_exits
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              def find_exits
         | 
| 11 | 
            +
                sessions.each do |s|
         | 
| 12 | 
            +
                  s.log_entries.inject do |previous, current|
         | 
| 13 | 
            +
                    previous.action.exits ||= []
         | 
| 14 | 
            +
                    p_exit = previous.action.exits.detect{|e| 
         | 
| 15 | 
            +
                      e.destination == current.action
         | 
| 16 | 
            +
                    }
         | 
| 17 | 
            +
                    unless p_exit
         | 
| 18 | 
            +
                      p_exit = TrafficPattern::Exit.new
         | 
| 19 | 
            +
                      p_exit.frequency = 0
         | 
| 20 | 
            +
                      p_exit.destination = current.action
         | 
| 21 | 
            +
                      previous.action.exits << p_exit
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
                    p_exit.frequency += 1
         | 
| 24 | 
            +
                    previous = current
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                actions.each do |a|
         | 
| 29 | 
            +
                  a.exits ||= []
         | 
| 30 | 
            +
                  total_freq = a.exits.inject(0){|sum, e| sum += e.frequency}
         | 
| 31 | 
            +
                  a.exits.each do |e|
         | 
| 32 | 
            +
                    e.probability = e.frequency.to_f / total_freq.to_f
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              def to_png(file_path)    
         | 
| 38 | 
            +
                tp = self
         | 
| 39 | 
            +
                YUML::useCaseDiagram( :scruffy, :scale => 100 ) {
         | 
| 40 | 
            +
                  tp.actions.each do |a|
         | 
| 41 | 
            +
                    a.exits.each do |e|
         | 
| 42 | 
            +
                      source = a.controller.name+"#"+a.name
         | 
| 43 | 
            +
                      target = e.destination.controller.name+"#"+e.destination.name
         | 
| 44 | 
            +
                      midpoint = "#{source}_#{target}_#{e.probability}"
         | 
| 45 | 
            +
                      _(source) > _(midpoint)
         | 
| 46 | 
            +
                      _(midpoint) >_(target)
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
                }.to_png( file_path )
         | 
| 50 | 
            +
              end
         | 
| 51 | 
            +
            end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            class SlowActions::Action
         | 
| 54 | 
            +
              attr_accessor :exits
         | 
| 55 | 
            +
            end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            module TrafficPattern
         | 
| 58 | 
            +
              class Exit
         | 
| 59 | 
            +
                attr_accessor :probability
         | 
| 60 | 
            +
                attr_accessor :destination
         | 
| 61 | 
            +
                attr_accessor :frequency
         | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
            end
         | 
| 64 | 
            +
             | 
| @@ -0,0 +1,54 @@ | |
| 1 | 
            +
            Processing UsersController#index (for 76.120.186.153 at 2009-02-23 22:15:07) [GET]
         | 
| 2 | 
            +
              Session ID: a0dfedb797521bb9f4749c76bef89d8d
         | 
| 3 | 
            +
              Parameters: {"action"=>"index", "controller"=>"users"}
         | 
| 4 | 
            +
            Redirected to https://play.scavengrnet.com/
         | 
| 5 | 
            +
            Completed in 0.00010 (10000 reqs/sec) | DB: 0.25601 (256014%) | 302 Found [https://play.scavengrnet.com/hunters_lodge]
         | 
| 6 | 
            +
             | 
| 7 | 
            +
             | 
| 8 | 
            +
            Processing StaticPagesController#static_hunters_lodge (for 76.120.186.153 at 2009-02-23 22:15:08) [GET]
         | 
| 9 | 
            +
              Session ID: a0dfedb797521bb9f4749c76bef89d8d
         | 
| 10 | 
            +
              Parameters: {"action"=>"static_hunters_lodge", "controller"=>"static_pages"}
         | 
| 11 | 
            +
            Redirected to http://play.scavengrnet.com/
         | 
| 12 | 
            +
            Filter chain halted as [:ensure_proper_protocol] rendered_or_redirected.
         | 
| 13 | 
            +
            Completed in 0.00010 (10000 reqs/sec) | DB: 0.00000 (0%) | 302 Found [https://play.scavengrnet.com/]
         | 
| 14 | 
            +
             | 
| 15 | 
            +
             | 
| 16 | 
            +
            Processing UsersController#index (for 76.120.186.153 at 2009-02-23 22:15:07) [GET]
         | 
| 17 | 
            +
              Session ID: a0dfedb797521bb9f4749c76bef89d8d
         | 
| 18 | 
            +
              Parameters: {"action"=>"index", "controller"=>"users"}
         | 
| 19 | 
            +
            Redirected to https://play.scavengrnet.com/
         | 
| 20 | 
            +
            Completed in 0.00010 (10000 reqs/sec) | DB: 0.25601 (256014%) | 302 Found [https://play.scavengrnet.com/hunters_lodge]
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            Processing UsersController#index (for 76.120.186.153 at 2009-02-23 22:15:07) [GET]
         | 
| 23 | 
            +
              Session ID: a0dfedb797521bb9f4749c76bef89d8d
         | 
| 24 | 
            +
              Parameters: {"action"=>"index", "controller"=>"users"}
         | 
| 25 | 
            +
            Redirected to https://play.scavengrnet.com/
         | 
| 26 | 
            +
            Completed in 0.00010 (10000 reqs/sec) | DB: 0.25601 (256014%) | 302 Found [https://play.scavengrnet.com/hunters_lodge]
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            Processing UsersController#index (for 76.120.186.153 at 2009-02-23 22:15:07) [GET]
         | 
| 29 | 
            +
              Session ID: beta
         | 
| 30 | 
            +
              Parameters: {"action"=>"index", "controller"=>"users"}
         | 
| 31 | 
            +
            Redirected to https://play.scavengrnet.com/
         | 
| 32 | 
            +
            Completed in 0.00010 (10000 reqs/sec) | DB: 0.25601 (256014%) | 302 Found [https://play.scavengrnet.com/hunters_lodge]
         | 
| 33 | 
            +
             | 
| 34 | 
            +
             | 
| 35 | 
            +
            Processing StaticPagesController#static_hunters_lodge (for 76.120.186.153 at 2009-02-23 22:15:08) [GET]
         | 
| 36 | 
            +
              Session ID: beta
         | 
| 37 | 
            +
              Parameters: {"action"=>"static_hunters_lodge", "controller"=>"static_pages"}
         | 
| 38 | 
            +
            Redirected to http://play.scavengrnet.com/
         | 
| 39 | 
            +
            Filter chain halted as [:ensure_proper_protocol] rendered_or_redirected.
         | 
| 40 | 
            +
            Completed in 0.00010 (10000 reqs/sec) | DB: 0.00000 (0%) | 302 Found [https://play.scavengrnet.com/]
         | 
| 41 | 
            +
             | 
| 42 | 
            +
             | 
| 43 | 
            +
            Processing UsersController#index (for 76.120.186.153 at 2009-02-23 22:15:07) [GET]
         | 
| 44 | 
            +
              Session ID: beta
         | 
| 45 | 
            +
              Parameters: {"action"=>"index", "controller"=>"users"}
         | 
| 46 | 
            +
            Redirected to https://play.scavengrnet.com/
         | 
| 47 | 
            +
            Completed in 0.00010 (10000 reqs/sec) | DB: 0.25601 (256014%) | 302 Found [https://play.scavengrnet.com/hunters_lodge]
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            Processing UsersController#index (for 76.120.186.153 at 2009-02-23 22:15:07) [GET]
         | 
| 50 | 
            +
              Session ID: beta
         | 
| 51 | 
            +
              Parameters: {"action"=>"index", "controller"=>"users"}
         | 
| 52 | 
            +
            Redirected to https://play.scavengrnet.com/
         | 
| 53 | 
            +
            Completed in 0.00010 (10000 reqs/sec) | DB: 0.25601 (256014%) | 302 Found [https://play.scavengrnet.com/hunters_lodge]
         | 
| 54 | 
            +
             | 
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            Processing UsersController#index (for 76.120.186.153 at 2009-02-23 22:15:07) [GET]
         | 
| 2 | 
            +
              Session ID: a0dfedb797521bb9f4749c76bef89d8d
         | 
| 3 | 
            +
              Parameters: {"action"=>"index", "controller"=>"users"}
         | 
| 4 | 
            +
            Redirected to https://play.scavengrnet.com/
         | 
| 5 | 
            +
            Completed in 0.00010 (10000 reqs/sec) | DB: 0.25601 (256014%) | 302 Found [https://play.scavengrnet.com/hunters_lodge]
         | 
| 6 | 
            +
             | 
| 7 | 
            +
             | 
| 8 | 
            +
            Processing StaticPagesController#static_hunters_lodge (for 76.120.186.153 at 2009-02-23 22:15:08) [GET]
         | 
| 9 | 
            +
              Session ID: a0dfedb797521bb9f4749c76bef89d8d
         | 
| 10 | 
            +
              Parameters: {"action"=>"static_hunters_lodge", "controller"=>"static_pages"}
         | 
| 11 | 
            +
            Redirected to http://play.scavengrnet.com/
         | 
| 12 | 
            +
            Filter chain halted as [:ensure_proper_protocol] rendered_or_redirected.
         | 
| 13 | 
            +
            Completed in 0.00010 (10000 reqs/sec) | DB: 0.00000 (0%) | 302 Found [https://play.scavengrnet.com/]
         | 
| 14 | 
            +
             | 
| 15 | 
            +
             | 
| @@ -1,7 +1,88 @@ | |
| 1 1 | 
             
            require 'helper'
         | 
| 2 2 |  | 
| 3 3 | 
             
            class TestTrafficPatterns < Test::Unit::TestCase
         | 
| 4 | 
            -
               | 
| 5 | 
            -
                 | 
| 4 | 
            +
              context "traffic patterns" do
         | 
| 5 | 
            +
                setup do
         | 
| 6 | 
            +
                  @tp = TrafficPatterns.new
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
                context "run on a log file with one action leading to the next" do
         | 
| 9 | 
            +
                  setup do
         | 
| 10 | 
            +
                    @tp.parse_file(fixture_file('two_actions.log'))
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                  should "have two actions" do
         | 
| 13 | 
            +
                    assert_equal 2, @tp.actions.size
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                  context "with the index action" do
         | 
| 16 | 
            +
                    setup do
         | 
| 17 | 
            +
                      @index = @tp.actions.detect{|a| a.name == "index"}
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                    should "have one edge" do
         | 
| 20 | 
            +
                      assert @index.exits.size == 1
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                    should "have a probability of one to the next of 100%" do
         | 
| 23 | 
            +
                      assert_equal 1.0, @index.exits.first.probability
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                  context "with the hunters_lodge action" do
         | 
| 27 | 
            +
                    setup do
         | 
| 28 | 
            +
                      @hl = @tp.actions.detect{|a| a.name == "static_hunters_lodge"}
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
                    should "not have an exit from the second to the first of 0%" do
         | 
| 31 | 
            +
                      assert_equal 0, @hl.exits.size
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                context "run on a log file with four entries per two sessions" do
         | 
| 37 | 
            +
                  setup do
         | 
| 38 | 
            +
                    @tp.parse_file(fixture_file('four_actions.log'))
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  should "have two actions" do
         | 
| 42 | 
            +
                    assert_equal 2, @tp.actions.size
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
                  context "with actions found" do
         | 
| 45 | 
            +
                    setup do
         | 
| 46 | 
            +
                      @index = @tp.actions.detect{|a| a.name == "index"}
         | 
| 47 | 
            +
                      @hl = @tp.actions.detect{|a| a.name == "static_hunters_lodge"}
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
                    should "have two exits on index" do
         | 
| 50 | 
            +
                      assert_equal 2, @index.exits.size
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
                    should "have one exit on hunters lodge" do
         | 
| 53 | 
            +
                      assert_equal 1, @hl.exits.size
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    should "have p(index => index) = 0.50" do
         | 
| 57 | 
            +
                      @exit = @index.exits.detect{|e|
         | 
| 58 | 
            +
                        e.destination == @index
         | 
| 59 | 
            +
                      }
         | 
| 60 | 
            +
                      assert_not_nil @exit
         | 
| 61 | 
            +
                      assert_equal 0.50, @exit.probability
         | 
| 62 | 
            +
                    end
         | 
| 63 | 
            +
                    should "have p(index => hl) = 0.50" do
         | 
| 64 | 
            +
                      @exit = @index.exits.detect{|e|
         | 
| 65 | 
            +
                        e.destination == @hl
         | 
| 66 | 
            +
                      }
         | 
| 67 | 
            +
                      assert_not_nil @exit
         | 
| 68 | 
            +
                      assert_equal 0.50, @exit.probability
         | 
| 69 | 
            +
                    end
         | 
| 70 | 
            +
                    should "have p(hl => index) = 1.0" do
         | 
| 71 | 
            +
                      @exit = @hl.exits.detect{|e|
         | 
| 72 | 
            +
                        e.destination == @index
         | 
| 73 | 
            +
                      }
         | 
| 74 | 
            +
                      assert_not_nil @exit
         | 
| 75 | 
            +
                      assert_equal 1.0, @exit.probability
         | 
| 76 | 
            +
                    end
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
             | 
| 83 | 
            +
              private
         | 
| 84 | 
            +
             | 
| 85 | 
            +
              def fixture_file(path_to_file)
         | 
| 86 | 
            +
                File.join(File.dirname(__FILE__), 'fixtures', path_to_file)
         | 
| 6 87 | 
             
              end
         | 
| 7 88 | 
             
            end
         | 
    
        data/traffic_patterns.gemspec
    CHANGED
    
    | @@ -5,7 +5,7 @@ | |
| 5 5 |  | 
| 6 6 | 
             
            Gem::Specification.new do |s|
         | 
| 7 7 | 
             
              s.name = %q{traffic_patterns}
         | 
| 8 | 
            -
              s.version = "0.0. | 
| 8 | 
            +
              s.version = "0.0.1"
         | 
| 9 9 |  | 
| 10 10 | 
             
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         | 
| 11 11 | 
             
              s.authors = ["Nick Gauthier"]
         | 
| @@ -24,6 +24,8 @@ Gem::Specification.new do |s| | |
| 24 24 | 
             
                 "Rakefile",
         | 
| 25 25 | 
             
                 "VERSION",
         | 
| 26 26 | 
             
                 "lib/traffic_patterns.rb",
         | 
| 27 | 
            +
                 "test/fixtures/four_actions.log",
         | 
| 28 | 
            +
                 "test/fixtures/two_actions.log",
         | 
| 27 29 | 
             
                 "test/helper.rb",
         | 
| 28 30 | 
             
                 "test/test_traffic_patterns.rb",
         | 
| 29 31 | 
             
                 "traffic_patterns.gemspec"
         | 
| @@ -43,15 +45,18 @@ Gem::Specification.new do |s| | |
| 43 45 | 
             
                s.specification_version = 3
         | 
| 44 46 |  | 
| 45 47 | 
             
                if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
         | 
| 46 | 
            -
                  s.add_development_dependency(%q< | 
| 48 | 
            +
                  s.add_development_dependency(%q<shoulda>, [">= 2.10.2"])
         | 
| 47 49 | 
             
                  s.add_runtime_dependency(%q<slow-actions>, [">= 0.3.4"])
         | 
| 50 | 
            +
                  s.add_runtime_dependency(%q<Ruby-yUML>, [">= 0.1.0"])
         | 
| 48 51 | 
             
                else
         | 
| 49 | 
            -
                  s.add_dependency(%q< | 
| 52 | 
            +
                  s.add_dependency(%q<shoulda>, [">= 2.10.2"])
         | 
| 50 53 | 
             
                  s.add_dependency(%q<slow-actions>, [">= 0.3.4"])
         | 
| 54 | 
            +
                  s.add_dependency(%q<Ruby-yUML>, [">= 0.1.0"])
         | 
| 51 55 | 
             
                end
         | 
| 52 56 | 
             
              else
         | 
| 53 | 
            -
                s.add_dependency(%q< | 
| 57 | 
            +
                s.add_dependency(%q<shoulda>, [">= 2.10.2"])
         | 
| 54 58 | 
             
                s.add_dependency(%q<slow-actions>, [">= 0.3.4"])
         | 
| 59 | 
            +
                s.add_dependency(%q<Ruby-yUML>, [">= 0.1.0"])
         | 
| 55 60 | 
             
              end
         | 
| 56 61 | 
             
            end
         | 
| 57 62 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: traffic_patterns
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
              version: 0.0. | 
| 4 | 
            +
              version: 0.0.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors: 
         | 
| 7 7 | 
             
            - Nick Gauthier
         | 
| @@ -13,14 +13,14 @@ date: 2009-12-15 00:00:00 -05:00 | |
| 13 13 | 
             
            default_executable: 
         | 
| 14 14 | 
             
            dependencies: 
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| 16 | 
            -
              name:  | 
| 16 | 
            +
              name: shoulda
         | 
| 17 17 | 
             
              type: :development
         | 
| 18 18 | 
             
              version_requirement: 
         | 
| 19 19 | 
             
              version_requirements: !ruby/object:Gem::Requirement 
         | 
| 20 20 | 
             
                requirements: 
         | 
| 21 21 | 
             
                - - ">="
         | 
| 22 22 | 
             
                  - !ruby/object:Gem::Version 
         | 
| 23 | 
            -
                    version:  | 
| 23 | 
            +
                    version: 2.10.2
         | 
| 24 24 | 
             
                version: 
         | 
| 25 25 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| 26 26 | 
             
              name: slow-actions
         | 
| @@ -32,6 +32,16 @@ dependencies: | |
| 32 32 | 
             
                  - !ruby/object:Gem::Version 
         | 
| 33 33 | 
             
                    version: 0.3.4
         | 
| 34 34 | 
             
                version: 
         | 
| 35 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 36 | 
            +
              name: Ruby-yUML
         | 
| 37 | 
            +
              type: :runtime
         | 
| 38 | 
            +
              version_requirement: 
         | 
| 39 | 
            +
              version_requirements: !ruby/object:Gem::Requirement 
         | 
| 40 | 
            +
                requirements: 
         | 
| 41 | 
            +
                - - ">="
         | 
| 42 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 43 | 
            +
                    version: 0.1.0
         | 
| 44 | 
            +
                version: 
         | 
| 35 45 | 
             
            description: Analyze your rails application's log files to figure out where your users go
         | 
| 36 46 | 
             
            email: nick@smartlogicsolutions.com
         | 
| 37 47 | 
             
            executables: []
         | 
| @@ -49,6 +59,8 @@ files: | |
| 49 59 | 
             
            - Rakefile
         | 
| 50 60 | 
             
            - VERSION
         | 
| 51 61 | 
             
            - lib/traffic_patterns.rb
         | 
| 62 | 
            +
            - test/fixtures/four_actions.log
         | 
| 63 | 
            +
            - test/fixtures/two_actions.log
         | 
| 52 64 | 
             
            - test/helper.rb
         | 
| 53 65 | 
             
            - test/test_traffic_patterns.rb
         | 
| 54 66 | 
             
            - traffic_patterns.gemspec
         |