tourbus 0.1.5 → 2.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/README.rdoc CHANGED
@@ -45,7 +45,7 @@ better name, these are called Tours.
45
45
  * Make a folder called tours and put a file in it called simple.rb. In
46
46
  it write:
47
47
 
48
- class Simple < Tour
48
+ class Simple < Tourist
49
49
  def test_homepage
50
50
  visit "http://#{@host}/"
51
51
  assert_contain "My Home Page"
@@ -53,7 +53,7 @@ better name, these are called Tours.
53
53
  end
54
54
 
55
55
  * Files in ./tours should have classes that match their names. E.g.
56
- "class BigHairyTest < Tour" belongs in ./tours/big_hairy_test.rb
56
+ "class BigHairyTest < Tourist" belongs in ./tours/big_hairy_test.rb
57
57
 
58
58
  * Think Test::Unit. test_* methods will be found automagically.
59
59
  setup() and teardown() methods will be executed at the appropriate
data/bin/tourbus CHANGED
@@ -18,15 +18,15 @@ config[:rand] ||= nil
18
18
 
19
19
  opts = Trollop.options do
20
20
  opt :host, "Remote hostname to test", :default => config[:host]
21
- opt :concurrency, "Number of simultaneous runs to perform", :type => :integer, :default => config[:concurrency]
22
- opt :number, "Number of times to run the tour (in each concurrent step, so -c 10 -n 10 will run the tour 100 times)", :type => :integer, :default => config[:number]
23
- opt :list, "List tours and runs available. If tours or runs are included, filters the list", :type => :boolean, :default => nil
21
+ opt :concurrency, "Number of simultaneous tourists to run", :type => :integer, :default => config[:concurrency]
22
+ opt :number, "Number of times to run the tourist (in each concurrent step, so -c 10 -n 10 will run the tourist 100 times)", :type => :integer, :default => config[:number]
23
+ opt :list, "List tourists and tours available. If tourists or tours are included, filters the list", :type => :boolean, :default => nil
24
24
  opt :rand, "Random seed", :type => :integer, :default => config[:rand]
25
25
  opt :tests, "Test name(s) filter. The name of the test to run (use --list to see the test names). Use commas, no spaces, for mulitple names", :type => :string, :default => nil
26
26
  end
27
27
 
28
- tours = if ARGV.empty?
29
- Tour.tours
28
+ tourists = if ARGV.empty?
29
+ Tourist.tourists
30
30
  else
31
31
  ARGV
32
32
  end
@@ -34,13 +34,13 @@ tours = if ARGV.empty?
34
34
  srand opts[:rand] || Time.now.to_i
35
35
 
36
36
  if opts[:list]
37
- Tour.tours(ARGV).each do |tour|
38
- puts tour
39
- puts Tour.tests(tour).map {|test| " #{test}"}
37
+ Tourist.tourists(ARGV).each do |tourist|
38
+ puts tourist
39
+ puts Tourist.tours(tourist).map {|test| " #{test}"}
40
40
  end
41
41
  else
42
42
  opts[:tests] = opts[:tests].split(',') if opts[:tests]
43
43
 
44
- TourBus.new(opts[:host], opts[:concurrency], opts[:number], tours, opts[:tests]).run
44
+ TourBus.new(opts[:host], opts[:concurrency], opts[:number], tourists, opts[:tests]).run
45
45
  end
46
46
 
data/bin/tourproxy ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # This proxy logger logs x-amf traffic, and is stolen with gratitude from http://altentee.com/2008/performance-testing-flex-remoting-amf-with-jmeter/
3
+
4
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'tour_proxy'))
5
+
6
+ options = {}
7
+
8
+ proxy = TourProxy.new options
9
+ trap "INT" do proxy.shutdown end
10
+ proxy.start
@@ -7,7 +7,7 @@ Silly little contact app to show you how to tour a website.
7
7
  In addition to tourbus, you will need Sinatra to run
8
8
  this app.
9
9
 
10
- sudo gem install sinatra
10
+ gem install sinatra
11
11
 
12
12
  = Contact App
13
13
 
@@ -1,19 +1,20 @@
1
- class Simple < Tour
2
- def test_home
3
- visit "/"
1
+ require 'ruby-debug'
2
+ class Simple < Tourist
3
+ def tour_home
4
+ visit "#{@host}/"
4
5
  assert_contain "If you click this"
5
6
 
6
7
  click_link "Enter Contact"
7
- assert_match /\/contacts/, current_page.url
8
+ assert_match /\/contacts/, current_url
8
9
  end
9
10
 
10
- def test_contacts
11
- visit "/contacts"
12
-
11
+ def tour_contacts
12
+ visit "#{@host}/contacts"
13
+
13
14
  fill_in "first_name", :with => "Joe"
14
15
  fill_in "last_name", :with => "Tester"
15
- click_button
16
-
16
+ click_button
17
+
17
18
  assert_contain "Tester, Joe"
18
19
  end
19
20
  end
data/lib/common.rb CHANGED
@@ -13,16 +13,25 @@ gem 'faker', '>= 0.3.1'
13
13
 
14
14
  # TODO: I'd like to remove dependency on Rails. Need to see what all
15
15
  # we're using (like classify) and remove each dependency individually.
16
- require 'activesupport'
16
+ begin
17
+ require 'activesupport'
18
+ rescue Exception
19
+ require 'active_support/all'
20
+ end
17
21
 
18
22
  require 'monitor'
19
23
  require 'faker'
20
24
  require 'tour_bus'
21
25
  require 'runner'
22
- require 'tour'
26
+ require 'tourist'
23
27
 
28
+ # Our common base class for exceptions
24
29
  class TourBusException < Exception; end
25
30
 
31
+ # The common base class for all exceptions raised by Webrat.
32
+ class WebratError < StandardError ; end
33
+
34
+
26
35
  def require_all_files_in_folder(folder, extension = "*.rb")
27
36
  for file in Dir[File.join('.', folder, "**/#{extension}")]
28
37
  require file
data/lib/file.rb ADDED
@@ -0,0 +1,11 @@
1
+ class File
2
+ # Hides all that lovely expand/join/dirname(__FILE__, path) crap
3
+ #
4
+ # E.g.: require File.here("../lib/pants")
5
+ #
6
+ # Splatty version for the OS Agnosts out there:
7
+ # require File.here(%w[.. lib pants])
8
+ def self.here(*args)
9
+ p = File.expand_path(File.join(File.dirname(caller.first.split(':')[0]), *args))
10
+ end
11
+ end
data/lib/runner.rb CHANGED
@@ -1,40 +1,37 @@
1
1
  require 'monitor'
2
2
  require 'common'
3
3
 
4
- # The common base class for all exceptions raised by Webrat.
5
- class WebratError < StandardError ; end
6
-
7
4
  class Runner
8
- attr_reader :host, :tours, :number, :runner_type, :runner_id
5
+ attr_reader :host, :tourists, :number, :runner_type, :runner_id
9
6
 
10
- def initialize(host, tours, number, runner_id, test_list)
11
- @host, @tours, @number, @runner_id, @test_list = host, tours, number, runner_id, test_list
7
+ def initialize(host, tourists, number, runner_id, tour_list)
8
+ @host, @tourists, @number, @runner_id, @tour_list = host, tourists, number, runner_id, tour_list
12
9
  @runner_type = self.send(:class).to_s
13
10
  log("Ready to run #{@runner_type}")
14
11
  end
15
12
 
16
13
  # Dispatches to subclass run method
17
- def run_tours
18
- log "Filtering on tests #{@test_list.join(', ')}" unless @test_list.to_a.empty?
19
- tours,tests,passes,fails,errors = 0,0,0,0,0
14
+ def run_tourists
15
+ log "Filtering on tours #{@tour_list.join(', ')}" unless @tour_list.to_a.empty?
16
+ tourists,tours,passes,fails,errors = 0,0,0,0,0
20
17
  1.upto(number) do |num|
21
18
  log("Starting #{@runner_type} run #{num}/#{number}")
22
- @tours.each do |tour_name|
19
+ @tourists.each do |tourist_name|
23
20
 
24
- log("Starting run #{num}/#{number} of Tour #{tour_name}")
25
- tours += 1
26
- tour = Tour.make_tour(tour_name,@host,@tours,@number,@runner_id)
27
- tour.before_tour
21
+ log("Starting run #{num}/#{number} of Tourist #{tourist_name}")
22
+ tourists += 1
23
+ tourist = Tourist.make_tourist(tourist_name,@host,@tourists,@number,@runner_id)
24
+ tourist.before_tours
28
25
 
29
- tour.tests.each do |test|
26
+ tourist.tours.each do |tour|
30
27
  times = Hash.new {|h,k| h[k] = {}}
31
28
 
32
- next if test_limited_to(test) # test_list && !test_list.empty? && !test_list.include?(test.to_s)
29
+ next if tour_limited_to(tour)
33
30
 
34
31
  begin
35
- tests += 1
36
- times[test][:started] = Time.now
37
- tour.run_test test
32
+ tours += 1
33
+ times[tour][:started] = Time.now
34
+ tourist.run_tour tour
38
35
  passes += 1
39
36
  rescue TourBusException, WebratError => e
40
37
  log("********** FAILURE IN RUN! **********")
@@ -53,18 +50,18 @@ class Runner
53
50
  end
54
51
  errors += 1
55
52
  ensure
56
- times[test][:finished] = Time.now
57
- times[test][:elapsed] = times[test][:finished] - times[test][:started]
53
+ times[tour][:finished] = Time.now
54
+ times[tour][:elapsed] = times[tour][:finished] - times[tour][:started]
58
55
  end
59
- log("Finished run #{num}/#{number} of Tour #{tour_name}")
56
+ log("Finished run #{num}/#{number} of Tourist #{tourist_name}")
60
57
  end
61
58
 
62
- tour.after_tour
59
+ tourist.after_tours
63
60
  end
64
61
  log("Finished #{@runner_type} run #{num}/#{number}")
65
62
  end
66
- log("Finished all #{@runner_type} tours.")
67
- [tours,tests,passes,fails,errors]
63
+ log("Finished all #{@runner_type} tourists.")
64
+ [tourists,tours,passes,fails,errors]
68
65
  end
69
66
 
70
67
  protected
@@ -73,8 +70,8 @@ class Runner
73
70
  puts "#{Time.now.strftime('%F %H:%M:%S')} Runner ##{@runner_id}: #{message}"
74
71
  end
75
72
 
76
- def test_limited_to(test_name)
77
- @test_list && !@test_list.empty? && !@test_list.include?(test_name.to_s)
73
+ def tour_limited_to(tour_name)
74
+ @tour_list && !@tour_list.empty? && !@tour_list.include?(tour_name.to_s)
78
75
  end
79
76
  end
80
77
 
data/lib/tour_bus.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  require 'benchmark'
2
2
 
3
3
  class TourBus < Monitor
4
- attr_reader :host, :concurrency, :number, :tours, :runs, :tests, :passes, :fails, :errors, :benchmarks
4
+ attr_reader :host, :concurrency, :number, :tourists, :runs, :tests, :passes, :fails, :errors, :benchmarks
5
5
 
6
- def initialize(host="localhost", concurrency=1, number=1, tours=[], test_list=nil)
7
- @host, @concurrency, @number, @tours, @test_list = host, concurrency, number, tours, test_list
6
+ def initialize(host="localhost", concurrency=1, number=1, tourists=[], test_list=nil)
7
+ @host, @concurrency, @number, @tourists, @test_list = host, concurrency, number, tourists, test_list
8
8
  @runner_id = 0
9
9
  @runs, @tests, @passes, @fails, @errors = 0,0,0,0,0
10
10
  super()
@@ -38,7 +38,7 @@ class TourBus < Monitor
38
38
  end
39
39
 
40
40
  def total_runs
41
- tours.size * concurrency * number
41
+ tourists.size * concurrency * number
42
42
  end
43
43
 
44
44
  def run
@@ -46,10 +46,10 @@ class TourBus < Monitor
46
46
  threads_ready = 0
47
47
  start_running = false
48
48
  mutex = Mutex.new
49
- tour_name = "#{total_runs} runs: #{concurrency}x#{number} of #{tours * ','}"
49
+ tourist_name = "#{total_runs} runs: #{concurrency}x#{number} of #{tourists * ','}"
50
50
  started = Time.now.to_f
51
51
  concurrency.times do |conc|
52
- log "Starting #{tour_name}"
52
+ log "Starting #{tourist_name}"
53
53
  threads << Thread.new do
54
54
  runner_id = next_runner_id
55
55
  mutex.lock
@@ -62,8 +62,8 @@ class TourBus < Monitor
62
62
  sleep 0.05 until start_running
63
63
  runs,tests,passes,fails,errors,start = 0,0,0,0,0,Time.now.to_f
64
64
  bm = Benchmark.measure do
65
- runner = Runner.new(@host, @tours, @number, runner_id, @test_list)
66
- runs,tests,passes,fails,errors = runner.run_tours
65
+ runner = Runner.new(@host, @tourists, @number, runner_id, @test_list)
66
+ runs,tests,passes,fails,errors = runner.run_tourists
67
67
  update_stats runs, tests, passes, fails, errors
68
68
  end
69
69
  log "Runner Finished!"
@@ -76,9 +76,9 @@ class TourBus < Monitor
76
76
  threads.each {|t| t.join }
77
77
  finished = Time.now.to_f
78
78
  log '-' * 80
79
- log tour_name
79
+ log tourist_name
80
80
  log "All Runners finished."
81
- log "Total Tours: #{@runs}"
81
+ log "Total Tourists: #{@runs}"
82
82
  log "Total Tests: #{@tests}"
83
83
  log "Total Passes: #{@passes}"
84
84
  log "Total Fails: #{@fails}"
data/lib/tour_proxy.rb ADDED
@@ -0,0 +1,82 @@
1
+ require 'webrick/httpproxy'
2
+ require 'ruby-debug'
3
+
4
+ class TourProxy
5
+ # Initialize the proxy object.
6
+ #
7
+ # @param [Hash] options list of options to configure the proxy.
8
+ # @option options [Fixnum] :port Port number to listen on
9
+ # @option options [Hash] :hostnames hostnames by name => url
10
+ # @option options [IO] :output_buffer IO object to write output to
11
+ def initialize(options={})
12
+ @server = nil
13
+ @output_buffer = options[:output_buffer] || STDOUT
14
+ @server = WEBrick::HTTPProxyServer.new(
15
+ :Port => options[:port] || 8080,
16
+ :RequestCallback => Proc.new do |req,res|
17
+ log_request_as_webrat(req)
18
+ # dump_request(req)
19
+ # puts(("<" * 100) + " END CALLBACK")
20
+ end
21
+ )
22
+ end
23
+
24
+ def log_request_as_webrat(request)
25
+ return unless @output_buffer
26
+ # puts "> log_request_as_webrat"
27
+ body = request.body
28
+ if body
29
+ items = body.split(/&/)
30
+ pairs = items.map{ |e| e.split(/=/,2)}
31
+ hash = Hash[pairs]
32
+ @output_buffer.puts "visit '#{request.request_uri}', :#{request.request_method.downcase}, #{hash.inspect}"
33
+ else
34
+ @output_buffer.puts "visit '#{request.request_uri}', :#{request.request_method.downcase}"
35
+ end
36
+ # puts "< log_request_as_webrat"
37
+ end
38
+
39
+ # Dumps an HTTPRequest object
40
+ def dump_request(request)
41
+ return unless @output_buffer
42
+ puts "> dump_request"
43
+ terms = %w(request_uri request_line raw_header body)
44
+ longest = terms.map(&:size).max
45
+
46
+ @output_buffer.puts '-' * 80
47
+ @output_buffer.puts "Request:"
48
+ terms.each do |term|
49
+ @output_buffer.puts " %#{longest}s:" % [term] # , request.send(term).to_s.length]
50
+ end
51
+ @output_buffer.puts '-' * 80
52
+ @output_buffer.flush
53
+ puts "< dump_request"
54
+ end
55
+
56
+ # Dumps an HTTPResponse object
57
+ def dump_response(response)
58
+ return unless @output_buffer
59
+ puts "> dump_response"
60
+ terms = %w()
61
+ longest = terms.map(&:size).max
62
+
63
+ @output_buffer.puts '-' * 80
64
+ @output_buffer.puts "Response:"
65
+ terms.each do |term|
66
+ @output_buffer.puts " %#{longest}s: %s" % [term, response.send(term).to_s]
67
+ end
68
+ @output_buffer.puts '-' * 80
69
+ @output_buffer.flush
70
+ puts "< dump_response"
71
+ end
72
+
73
+ def start
74
+ @server.start
75
+ end
76
+
77
+ def shutdown
78
+ @server.shutdown
79
+ end
80
+ end
81
+
82
+
data/lib/tour_rat.rb ADDED
@@ -0,0 +1,70 @@
1
+ require 'forwardable'
2
+ require 'webrat'
3
+
4
+ module TourRat
5
+ module ClassMethods
6
+
7
+ end
8
+
9
+ module InstanceMethods
10
+
11
+ end
12
+
13
+ def self.included(receiver)
14
+ receiver.extend ClassMethods
15
+ receiver.send :include, InstanceMethods
16
+ end
17
+ end
18
+
19
+ # Webrat::Scope
20
+ # 1. attach_file
21
+ # 2. check
22
+ # 3. choose
23
+ # 4. click_area
24
+ # 5. click_button
25
+ # 6. click_link
26
+ # 7. fill_in
27
+ # 8. select
28
+ # 9. select_date
29
+ # 10. select_datetime
30
+ # 11. select_time
31
+ # 12. set_hidden_field
32
+ # 13. submit_form
33
+ # 14. uncheck
34
+ #
35
+ #
36
+ # Webrat::Session
37
+ # 1. automate
38
+ # 2. basic_auth
39
+ # 3. check_for_infinite_redirects
40
+ # 4. click_link_within
41
+ # 5. dom
42
+ # 6. header
43
+ # 7. http_accept
44
+ # 8. infinite_redirect_limit_exceeded?
45
+ # 9. internal_redirect?
46
+ # 10. redirected_to
47
+ # 11. reload
48
+ # 12. simulate
49
+ # 13. visit
50
+ # 14. within
51
+ # 15. xml_content_type?
52
+ #
53
+ # Webrat::HaveTagMatcher
54
+ # 1. assert_have_no_tag
55
+ # 2. assert_have_tag
56
+ # 3. have_tag
57
+ # 4. match_tag
58
+ #
59
+ # Webrat::Matchers
60
+ # 1. assert_contain
61
+ # 2. assert_have_no_selector
62
+ # 3. assert_have_no_xpath
63
+ # 4. assert_have_selector
64
+ # 5. assert_have_xpath
65
+ # 6. assert_not_contain
66
+ # 7. contain
67
+ # 8. have_selector
68
+ # 9. have_xpath
69
+ # 10. match_selector
70
+ # 11. match_xpath
data/lib/tour_watch.rb CHANGED
@@ -29,10 +29,10 @@ class TourWatch
29
29
  @mac ? fields_mac(parts) : fields_linux(parts)
30
30
  end
31
31
 
32
- # Note: MacOSX is so awesome I just cacked. Top will report 0.0% cpu
33
- # the first time you run top, every time. The only way to get actual
34
- # CPU% here is to wait for it to send another page and then throw
35
- # away the first page. Isn't that just awesome?!? I KNOW!!!
32
+ # Note: MacOSX is so laaaame. Top will report 0.0% cpu the first
33
+ # time you run top, every time. The only way to get actual CPU% here
34
+ # is to wait for it to send another page and then throw away the
35
+ # first page. Isn't that just awesome?!? I KNOW!!!
36
36
  def top_mac
37
37
  top = `top -l 1 | grep -E '(#{@processes})'`
38
38
  end
data/lib/tourist.rb ADDED
@@ -0,0 +1,101 @@
1
+ require 'forwardable'
2
+ require 'monitor'
3
+ require 'common'
4
+ require 'webrat'
5
+ require 'webrat/adapters/mechanize'
6
+ require 'test/unit/assertions'
7
+
8
+ # A tourist is essentially a test suite file. A Tourist subclass
9
+ # encapsulates a set of tours that can be done, and may contain helper
10
+ # and support methods for a given task. If you have a two or three
11
+ # paths through a specific area of your website, define a tourist for
12
+ # that area and create tour_ methods for each type of tour to be done.
13
+
14
+ Webrat.configure do |config|
15
+ config.mode = :mechanize
16
+ end
17
+
18
+ class Tourist
19
+ extend Forwardable
20
+ include Webrat::Methods
21
+ include Webrat::Matchers
22
+ include Webrat::SaveAndOpenPage
23
+ include Test::Unit::Assertions
24
+
25
+ attr_reader :host, :tours, :number, :tour_type, :tourist_id
26
+
27
+ def initialize(host, tours, number, tourist_id)
28
+ @host, @tours, @number, @tourist_id = host, tours, number, tourist_id
29
+ @tour_type = self.send(:class).to_s
30
+ end
31
+
32
+ # before_tour runs once per tour, before any tours get run
33
+ def before_tours; end
34
+
35
+ # after_tour runs once per tour, after all the tours have run
36
+ def after_tours; end
37
+
38
+ def setup
39
+ end
40
+
41
+ def teardown
42
+ end
43
+
44
+ def wait(time)
45
+ sleep time.to_i
46
+ end
47
+
48
+ # Lists tourists in tours folder. If a string is given, filters the
49
+ # list by that string. If an array of filter strings is given,
50
+ # returns items that match ANY filter string in the array.
51
+ def self.tourists(filter=[])
52
+ filter = [filter].flatten
53
+ # All files in tours folder, stripped to basename, that match any item in filter
54
+ # I do loves me a long chain. This returns an array containing
55
+ # 1. All *.rb files in tour folder (recursive)
56
+ # 2. Each filename stripped to its basename
57
+ # 3. If you passed in any filters, these basenames are rejected unless they match at least one filter
58
+ # 4. The filenames remaining are then checked to see if they define a class of the same name that inherits from Tourist
59
+ Dir[File.join('.', 'tours', '**', '*.rb')].map {|fn| File.basename(fn, ".rb")}.select {|fn| filter.size.zero? || filter.any?{|f| fn =~ /#{f}/}}.select {|tour| Tourist.tourist? tour }
60
+ end
61
+
62
+ def self.tours(tourist_name)
63
+ Tourist.make_tourist(tourist_name).tours
64
+ end
65
+
66
+ # Returns true if the given tourist name can be found in the tours folder, and defines a similarly-named subclass of Tourist
67
+ def self.tourist?(tourist_name)
68
+ Object.const_defined?(tourist_name.classify) && tourist_name.classify.constantize.ancestors.include?(Tourist)
69
+ end
70
+
71
+ # Factory method, creates the named child class instance
72
+ def self.make_tourist(tourist_name,host="http://localhost:3000",tours=[],number=1,tourist_id=nil)
73
+ tourist_name.classify.constantize.new(host,tours,number,tourist_id)
74
+ end
75
+
76
+ # Returns list of tours this tourist knows about. (Meant to be run on a subclass
77
+ # instance; returns the list of tours available).
78
+ def tours
79
+ methods.grep(/^tour_/).map {|m| m.sub(/^tour_/,'')}
80
+ end
81
+
82
+ def run_tour(tour_name)
83
+ @current_tour = "tour_#{tour_name}"
84
+ raise TourBusException.new("run_tour couldn't run tour '#{tour_name}' because this tourist did not respond to :#{@current_tour}") unless respond_to? @current_tour
85
+ setup
86
+ send @current_tour
87
+ teardown
88
+ end
89
+
90
+ protected
91
+
92
+ def session
93
+ @session ||= Webrat::MechanizeSession.new
94
+ end
95
+
96
+ def log(message)
97
+ puts "#{Time.now.strftime('%F %H:%M:%S')} Tourist ##{@tourist_id}: (#{@current_tour}) #{message}"
98
+ end
99
+
100
+ end
101
+
@@ -0,0 +1,19 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe TourProxy do
4
+ it "should replace known hostnames"
5
+ # given a list of known hostnames,
6
+ # when I process a request matching a hosts,
7
+ # then the request uri should be rewritten with the variable's expansion
8
+
9
+ it "should emit AMF blobs"
10
+ it "should emit get/post blobs for unrecognized types"
11
+
12
+ # when doing an html get
13
+ # with no params
14
+ # it should log "visit 'url'"
15
+ # and should not log "visit 'url', :get" etc
16
+
17
+
18
+ end
19
+
@@ -0,0 +1,22 @@
1
+ # This file is copied to ~/spec when you run 'ruby script/generate rspec'
2
+ # from the project root directory.
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '../lib/file'))
4
+ require 'spec/autorun'
5
+ require 'ruby-debug'
6
+ # require File.here('../features/factories/fixjour_definitions')
7
+ # require File.here('../test/bdrb_test_helper')
8
+
9
+ # Requires all files in a folder relative to .. (project root).
10
+ def require_all_files_in_folder(folder, extension = '*.rb')
11
+ for file in Dir[File.join(File.expand_path(File.dirname(__FILE__)), '..', folder, "**/#{extension}")]
12
+ require file
13
+ end
14
+ end
15
+
16
+ # Uncomment the next line to use webrat's matchers
17
+ #require 'webrat/integrations/rspec-rails'
18
+
19
+ # Requires supporting files with custom matchers and macros, etc,
20
+ # in ./support/ and its subdirectories.
21
+ require_all_files_in_folder "spec/support"
22
+ require_all_files_in_folder "lib"
metadata CHANGED
@@ -1,12 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tourbus
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 1
8
- - 5
9
- version: 0.1.5
4
+ prerelease:
5
+ version: 2.0.1
10
6
  platform: ruby
11
7
  authors:
12
8
  - David Brady
@@ -18,20 +14,17 @@ autorequire:
18
14
  bindir: bin
19
15
  cert_chain: []
20
16
 
21
- date: 2010-03-29 00:00:00 -06:00
17
+ date: 2010-09-23 00:00:00 -06:00
22
18
  default_executable:
23
19
  dependencies:
24
20
  - !ruby/object:Gem::Dependency
25
21
  name: mechanize
26
22
  prerelease: false
27
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
28
25
  requirements:
29
26
  - - ">="
30
27
  - !ruby/object:Gem::Version
31
- segments:
32
- - 1
33
- - 0
34
- - 0
35
28
  version: 1.0.0
36
29
  type: :runtime
37
30
  version_requirements: *id001
@@ -39,11 +32,10 @@ dependencies:
39
32
  name: trollop
40
33
  prerelease: false
41
34
  requirement: &id002 !ruby/object:Gem::Requirement
35
+ none: false
42
36
  requirements:
43
37
  - - ">="
44
38
  - !ruby/object:Gem::Version
45
- segments:
46
- - 0
47
39
  version: "0"
48
40
  type: :runtime
49
41
  version_requirements: *id002
@@ -51,11 +43,10 @@ dependencies:
51
43
  name: faker
52
44
  prerelease: false
53
45
  requirement: &id003 !ruby/object:Gem::Requirement
46
+ none: false
54
47
  requirements:
55
48
  - - ">="
56
49
  - !ruby/object:Gem::Version
57
- segments:
58
- - 0
59
50
  version: "0"
60
51
  type: :runtime
61
52
  version_requirements: *id003
@@ -63,11 +54,10 @@ dependencies:
63
54
  name: hpricot
64
55
  prerelease: false
65
56
  requirement: &id004 !ruby/object:Gem::Requirement
57
+ none: false
66
58
  requirements:
67
59
  - - ">="
68
60
  - !ruby/object:Gem::Version
69
- segments:
70
- - 0
71
61
  version: "0"
72
62
  type: :runtime
73
63
  version_requirements: *id004
@@ -75,21 +65,30 @@ dependencies:
75
65
  name: webrat
76
66
  prerelease: false
77
67
  requirement: &id005 !ruby/object:Gem::Requirement
68
+ none: false
78
69
  requirements:
79
70
  - - ">="
80
71
  - !ruby/object:Gem::Version
81
- segments:
82
- - 0
83
- - 7
84
- - 0
85
72
  version: 0.7.0
86
73
  type: :runtime
87
74
  version_requirements: *id005
88
- description: TourBus, a web stress-testing tool that combines complex 'tour' definitions with scalable concurrent testing
75
+ - !ruby/object:Gem::Dependency
76
+ name: activesupport
77
+ prerelease: false
78
+ requirement: &id006 !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: 3.0.0
84
+ type: :runtime
85
+ version_requirements: *id006
86
+ description: TourBus, a web load-testing tool that combines complex 'tour' definitions with scalable, concurrent testing
89
87
  email: github@shinybit.com
90
88
  executables:
91
89
  - tourbus
92
90
  - tourwatch
91
+ - tourproxy
93
92
  extensions: []
94
93
 
95
94
  extra_rdoc_files:
@@ -98,16 +97,22 @@ extra_rdoc_files:
98
97
  - examples/contact_app/README.rdoc
99
98
  files:
100
99
  - bin/tourbus
100
+ - bin/tourproxy
101
101
  - bin/tourwatch
102
102
  - examples/contact_app/README.rdoc
103
103
  - examples/contact_app/contact_app.rb
104
104
  - examples/contact_app/tours/simple.rb
105
105
  - examples/contact_app/tours/tourbus.yml
106
106
  - lib/common.rb
107
+ - lib/file.rb
107
108
  - lib/runner.rb
108
- - lib/tour.rb
109
109
  - lib/tour_bus.rb
110
+ - lib/tour_proxy.rb
111
+ - lib/tour_rat.rb
110
112
  - lib/tour_watch.rb
113
+ - lib/tourist.rb
114
+ - spec/lib/tourproxy_spec.rb
115
+ - spec/spec_helper.rb
111
116
  - README.rdoc
112
117
  - MIT-LICENSE
113
118
  has_rdoc: true
@@ -121,27 +126,25 @@ rdoc_options:
121
126
  - --main
122
127
  - README.rdoc
123
128
  - --title
124
- - Tourbus - Web Stress Testing in Ruby
129
+ - Tourbus - Web Load Testing in Ruby
125
130
  require_paths:
126
131
  - lib
127
132
  required_ruby_version: !ruby/object:Gem::Requirement
133
+ none: false
128
134
  requirements:
129
135
  - - ">="
130
136
  - !ruby/object:Gem::Version
131
- segments:
132
- - 0
133
137
  version: "0"
134
138
  required_rubygems_version: !ruby/object:Gem::Requirement
139
+ none: false
135
140
  requirements:
136
141
  - - ">="
137
142
  - !ruby/object:Gem::Version
138
- segments:
139
- - 0
140
143
  version: "0"
141
144
  requirements: []
142
145
 
143
146
  rubyforge_project:
144
- rubygems_version: 1.3.6
147
+ rubygems_version: 1.6.2
145
148
  signing_key:
146
149
  specification_version: 3
147
150
  summary: TourBus web stress-testing tool
data/lib/tour.rb DELETED
@@ -1,100 +0,0 @@
1
- require 'forwardable'
2
- require 'monitor'
3
- require 'common'
4
- require 'webrat'
5
- require 'webrat/adapters/mechanize'
6
- require 'test/unit/assertions'
7
-
8
- # A tour is essentially a test suite file. A Tour subclass
9
- # encapsulates a set of tests that can be done, and may contain helper
10
- # and support methods for a given task. If you have a two or three
11
- # paths through a specific area of your website, define a tour for
12
- # that area and create test_ methods for each type of test to be done.
13
-
14
- Webrat.configure do |config|
15
- config.mode = :mechanize
16
- end
17
-
18
- class Tour
19
- extend Forwardable
20
- include Webrat::Methods
21
- include Webrat::Matchers
22
- include Webrat::SaveAndOpenPage
23
- include Test::Unit::Assertions
24
-
25
- attr_reader :host, :tours, :number, :tour_type, :tour_id
26
-
27
- def initialize(host, tours, number, tour_id)
28
- @host, @tours, @number, @tour_id = host, tours, number, tour_id
29
- @tour_type = self.send(:class).to_s
30
- end
31
-
32
- # before_tour runs once per tour, before any tests get run
33
- def before_tour; end
34
-
35
- # after_tour runs once per tour, after all the tests have run
36
- def after_tour; end
37
-
38
- def setup
39
- end
40
-
41
- def teardown
42
- end
43
-
44
- def wait(time)
45
- sleep time.to_i
46
- end
47
-
48
- # Lists tours in tours folder. If a string is given, filters the
49
- # list by that string. If an array of filter strings is given,
50
- # returns items that match ANY filter string in the array.
51
- def self.tours(filter=[])
52
- filter = [filter].flatten
53
- # All files in tours folder, stripped to basename, that match any item in filter
54
- # I do loves me a long chain. This returns an array containing
55
- # 1. All *.rb files in tour folder (recursive)
56
- # 2. Each filename stripped to its basename
57
- # 3. If you passed in any filters, these basenames are rejected unless they match at least one filter
58
- # 4. The filenames remaining are then checked to see if they define a class of the same name that inherits from Tour
59
- Dir[File.join('.', 'tours', '**', '*.rb')].map {|fn| File.basename(fn, ".rb")}.select {|fn| filter.size.zero? || filter.any?{|f| fn =~ /#{f}/}}.select {|tour| Tour.tour? tour }
60
- end
61
-
62
- def self.tests(tour_name)
63
- Tour.make_tour(tour_name).tests
64
- end
65
-
66
- def self.tour?(tour_name)
67
- Object.const_defined?(tour_name.classify) && tour_name.classify.constantize.ancestors.include?(Tour)
68
- end
69
-
70
- # Factory method, creates the named child class instance
71
- def self.make_tour(tour_name,host="http://localhost:3000",tours=[],number=1,tour_id=nil)
72
- tour_name.classify.constantize.new(host,tours,number,tour_id)
73
- end
74
-
75
- # Returns list of tests in this tour. (Meant to be run on a subclass
76
- # instance; returns the list of tests available).
77
- def tests
78
- methods.grep(/^test_/).map {|m| m.sub(/^test_/,'')}
79
- end
80
-
81
- def run_test(test_name)
82
- @test = "test_#{test_name}"
83
- raise TourBusException.new("run_test couldn't run test '#{test_name}' because this tour did not respond to :#{@test}") unless respond_to? @test
84
- setup
85
- send @test
86
- teardown
87
- end
88
-
89
- protected
90
-
91
- def session
92
- @session ||= Webrat::MechanizeSession.new
93
- end
94
-
95
- def log(message)
96
- puts "#{Time.now.strftime('%F %H:%M:%S')} Tour ##{@tour_id}: (#{@test}) #{message}"
97
- end
98
-
99
- end
100
-