dbrady-tourbus 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/{README.txt → README.rdoc} +56 -6
- data/bin/tourbus +6 -3
- data/lib/runner.rb +18 -11
- data/lib/tour.rb +17 -0
- data/lib/tour_bus.rb +13 -11
- metadata +8 -7
data/{README.txt → README.rdoc}
RENAMED
@@ -6,6 +6,7 @@ Flexible and scalable website testing tool.
|
|
6
6
|
|
7
7
|
* David Brady -- david.brady@leadmediapartners.com
|
8
8
|
* Tim Harper -- tim.harper@leadmediapartners.com
|
9
|
+
* James Britt -- http://github.com/jamesbritt
|
9
10
|
|
10
11
|
== General Info
|
11
12
|
|
@@ -54,22 +55,48 @@ better name, these are called Tours.
|
|
54
55
|
|
55
56
|
=== Example TourBus Run
|
56
57
|
|
57
|
-
tourbus
|
58
|
+
You want to invoke +tourbus+ from the parent directory of the @tours/@ folder.
|
58
59
|
|
59
|
-
|
60
|
+
For example, if you have this project tree ...
|
61
|
+
|
62
|
+
`-- contact_app
|
63
|
+
|-- README.rdoc
|
64
|
+
|-- contact_app.rb
|
65
|
+
`-- tours
|
66
|
+
|-- simple.rb
|
67
|
+
`-- tourbus.yml
|
68
|
+
|
69
|
+
... then you execute +tourbus+ from the +contact_app/+ directory.
|
70
|
+
|
71
|
+
tourbus -c 2 -n 3 simple
|
72
|
+
|
73
|
+
That will run the +simple.rb+ tour file.
|
74
|
+
|
75
|
+
It will create 2 concurrent Tour runners, each of which will run all
|
60
76
|
of the methods in Simple three times.
|
61
77
|
|
62
78
|
* You can specify multiple tours.
|
63
79
|
|
80
|
+
tourbus -c 2 -n 3 simple1 simple2 simple3
|
81
|
+
|
64
82
|
* If you don't specify a tour, all tours in ./tours will be run.
|
65
83
|
|
66
84
|
* tourbus --help will give you more information.
|
67
85
|
|
86
|
+
* You can run tours and filter given tests.
|
87
|
+
|
88
|
+
tourbus -c 2 -n 3 simple -t test_login,test_logout
|
89
|
+
|
90
|
+
Note that if you specify multiple tours and filter tests, the filtered
|
91
|
+
tests will be run on all tours specified. If you do not specify a
|
92
|
+
tour, the filtered tests will be run on all tours found in the
|
93
|
+
+./tours+ folder.
|
94
|
+
|
68
95
|
=== Example TourWatch Run
|
69
96
|
|
70
97
|
On the webserver, you can type
|
71
98
|
|
72
|
-
tourwatch -c 4
|
99
|
+
tourwatch -c 4
|
73
100
|
|
74
101
|
To begin running tourwatch. It's basically a stripped-down version of
|
75
102
|
top with cheesy text graphs. (TourWatch's development cycles were
|
@@ -82,7 +109,7 @@ included in the 2 days for TourBus.)
|
|
82
109
|
|
83
110
|
* You can choose which processes to watch by passing a csv to -p:
|
84
111
|
|
85
|
-
|
112
|
+
tourwatch -p ruby,mongrel
|
86
113
|
|
87
114
|
Each process name is a partial regexp, so the above would match
|
88
115
|
mongrel AND mongrel_rails, etc.
|
@@ -110,7 +137,8 @@ duplications, oversights, and kludges.
|
|
110
137
|
didn't put tests on it. I haven't put tests on it yet because I'm
|
111
138
|
not sure how to go about it. Instead of exercising a web app with a
|
112
139
|
test browser, we need to exercise a test browser with... um... a web
|
113
|
-
app?
|
140
|
+
app? (dbrady notes: Now that we have a contact_app, we could try
|
141
|
+
writing some specs and features to run tourbus against it.)
|
114
142
|
|
115
143
|
* Web-Sickle is another internal app, written by Tim Harper, that
|
116
144
|
works "well enough". Until I open-sourced this project, it was a
|
@@ -118,12 +146,31 @@ duplications, oversights, and kludges.
|
|
118
146
|
from WebSickle itself, so there's a lot of code in Runner that
|
119
147
|
really belongs in WebSickle.
|
120
148
|
|
121
|
-
* Documentation is horrible.
|
149
|
+
* Documentation is <strike>horrible</strike> merely quite bad.
|
122
150
|
|
123
151
|
* There's not much in the way of examples, either. When I removed all
|
124
152
|
the LMP-specific code, all of the examples went with it. Sorry about
|
125
153
|
that. Coming soon.
|
126
154
|
|
155
|
+
== Feature Requests (How You Can Help!)
|
156
|
+
|
157
|
+
* I'd like to beef up the example contact app to show more of TourBus
|
158
|
+
than the simplest possible path. Adding in another page or two, and
|
159
|
+
then adding an additional tour or two would make it more apparent to
|
160
|
+
new users that you can do things like run multiple tours at once.
|
161
|
+
Also, having more than one test_ method in simple.rb would let us
|
162
|
+
demonstrate test filtering as well. (Be aware that at present
|
163
|
+
[2009-04-17], webrat still does not play well with Sinatra sessions
|
164
|
+
so there would be complications. dbrady's fork of webrat combines
|
165
|
+
jferris' fix with the latest webrat, and will be maintained until
|
166
|
+
main webrat includes the feature. That fork is at
|
167
|
+
http://github.com/dbrady/webrat)
|
168
|
+
|
169
|
+
* I'd like to remove WebSickle and replace it with Webrat. There is a
|
170
|
+
webrat branch on the main fork (http://github.com/dbrady/tourbus)
|
171
|
+
that is 90% complete. Once that's done we can start massaging the
|
172
|
+
API to be a little more friendly.
|
173
|
+
|
127
174
|
== Credits
|
128
175
|
|
129
176
|
* Tim Harper camped at my place for a day fixing bugs in WebSickle as
|
@@ -133,6 +180,9 @@ duplications, oversights, and kludges.
|
|
133
180
|
source it. How much do they rock? All the way to 11, that's how much
|
134
181
|
they rock.
|
135
182
|
|
183
|
+
* James Britt jumped on this and revived it as it was gathering dust.
|
184
|
+
Thanks!
|
185
|
+
|
136
186
|
== License
|
137
187
|
|
138
188
|
MIT. See the license file.
|
data/bin/tourbus
CHANGED
@@ -7,7 +7,7 @@ require_all_files_in_folder 'tours'
|
|
7
7
|
config_file = ["./tourbus.yml", "./tours/tourbus.yml", "./config/tourbus.yml", "~/tourbus.yml"].map {|p| File.expand_path(p)}.find {|p| File.exists? p}
|
8
8
|
config = config_file ? YAML::load_file(config_file).symbolize_keys : {}
|
9
9
|
|
10
|
-
config_map = { :host => :to_s, :concurrency => :to_i, :number => :to_i, :rand => :to_i }
|
10
|
+
config_map = { :host => :to_s, :concurrency => :to_i, :number => :to_i, :rand => :to_i, :tests => :to_s }
|
11
11
|
config_map.each {|key,conv| config[key] = config[key].send(conv) if config.key? key }
|
12
12
|
|
13
13
|
# defaults
|
@@ -22,10 +22,11 @@ opts = Trollop.options do
|
|
22
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
23
|
opt :list, "List tours and runs available. If tours or runs are included, filters the list", :type => :boolean, :default => nil
|
24
24
|
opt :rand, "Random seed", :type => :integer, :default => config[:rand]
|
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
|
25
26
|
end
|
26
27
|
|
27
28
|
tours = if ARGV.empty?
|
28
|
-
|
29
|
+
Tour.tours
|
29
30
|
else
|
30
31
|
ARGV
|
31
32
|
end
|
@@ -38,6 +39,8 @@ if opts[:list]
|
|
38
39
|
puts Tour.tests(tour).map {|test| " #{test}"}
|
39
40
|
end
|
40
41
|
else
|
41
|
-
|
42
|
+
opts[:tests] = opts[:tests].split(',')
|
43
|
+
|
44
|
+
TourBus.new(opts[:host], opts[:concurrency], opts[:number], tours, opts[:tests]).run
|
42
45
|
end
|
43
46
|
|
data/lib/runner.rb
CHANGED
@@ -4,23 +4,31 @@ require 'common'
|
|
4
4
|
class Runner
|
5
5
|
attr_reader :host, :tours, :number, :runner_type, :runner_id
|
6
6
|
|
7
|
-
def initialize(host, tours, number, runner_id)
|
8
|
-
@host, @tours, @number, @runner_id = host, tours, number, runner_id
|
7
|
+
def initialize(host, tours, number, runner_id, test_list)
|
8
|
+
@host, @tours, @number, @runner_id, @test_list = host, tours, number, runner_id, test_list
|
9
9
|
@runner_type = self.send(:class).to_s
|
10
10
|
log("Ready to run #{@runner_type}")
|
11
11
|
end
|
12
12
|
|
13
13
|
# Dispatches to subclass run method
|
14
|
-
def run_tours
|
15
|
-
|
14
|
+
def run_tours test_list = []
|
15
|
+
log "Filtering on tests #{test_list.join(', ')}" unless test_list.to_a.empty?
|
16
|
+
tours,tests,passes,fails,errors = 0,0,0,0,0
|
16
17
|
1.upto(number) do |num|
|
17
18
|
log("Starting #{@runner_type} run #{num}/#{number}")
|
18
|
-
@tours.each do |
|
19
|
-
|
20
|
-
|
19
|
+
@tours.each do |tour_name|
|
20
|
+
|
21
|
+
log("Starting run #{number} of Tour #{tour_name}")
|
22
|
+
tours += 1
|
23
|
+
tour = Tour.make_tour(tour_name,@host,@tours,@number,@runner_id)
|
21
24
|
tour.tests.each do |test|
|
25
|
+
|
26
|
+
next if !test_list.empty? && !test_list.include?(test.to_s)
|
27
|
+
|
22
28
|
begin
|
29
|
+
tests += 1
|
23
30
|
tour.run_test test
|
31
|
+
passes += 1
|
24
32
|
rescue TourBusException, WebsickleException => e
|
25
33
|
log("********** FAILURE IN RUN! **********")
|
26
34
|
log e.message
|
@@ -38,14 +46,13 @@ class Runner
|
|
38
46
|
end
|
39
47
|
errors += 1
|
40
48
|
end
|
41
|
-
|
49
|
+
log("Finished run #{number} of Tour #{tour_name}")
|
42
50
|
end
|
43
51
|
end
|
44
|
-
passes += 1
|
45
52
|
log("Finished #{@runner_type} run #{num}/#{number}")
|
46
53
|
end
|
47
|
-
log("Finished all #{@runner_type}
|
48
|
-
[
|
54
|
+
log("Finished all #{@runner_type} tours.")
|
55
|
+
[tours,tests,passes,fails,errors]
|
49
56
|
end
|
50
57
|
|
51
58
|
protected
|
data/lib/tour.rb
CHANGED
@@ -117,5 +117,22 @@ class Tour
|
|
117
117
|
end
|
118
118
|
log "Page body ok (matches #{pattern})"
|
119
119
|
end
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
# True if page does not contain (or match) the given string (or regexp)
|
124
|
+
#
|
125
|
+
# TODO: Refactor me--these were separated out back when Websickle
|
126
|
+
# was a shared submodule and we couldn't pollute it. Now that it's
|
127
|
+
# frozen these probably belong there.
|
128
|
+
def assert_page_body_does_not_contain(pattern)
|
129
|
+
case pattern
|
130
|
+
when String:
|
131
|
+
raise WebsickleException, "Expected page body to not contain String '#{pattern}' but it did. It was #{page.body}" if page.body.to_s.index(pattern)
|
132
|
+
when Regexp:
|
133
|
+
raise WebsickleException, "Expected page body to not match Regexp '#{pattern}' but it did. It was #{page.body}" if page.body.to_s =~ pattern
|
134
|
+
end
|
135
|
+
log "Page body ok (does not match #{pattern})"
|
136
|
+
end
|
120
137
|
end
|
121
138
|
|
data/lib/tour_bus.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'benchmark'
|
2
2
|
|
3
3
|
class TourBus < Monitor
|
4
|
-
attr_reader :host, :concurrency, :number, :tours, :runs, :passes, :fails, :errors, :benchmarks
|
4
|
+
attr_reader :host, :concurrency, :number, :tours, :runs, :tests, :passes, :fails, :errors, :benchmarks
|
5
5
|
|
6
|
-
def initialize(host="localhost", concurrency=1, number=1, tours=[])
|
7
|
-
@host, @concurrency, @number, @tours = host, concurrency, number, tours
|
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
|
8
8
|
@runner_id = 0
|
9
|
-
@runs, @passes, @fails, @errors = 0,0,0,0
|
9
|
+
@runs, @tests, @passes, @fails, @errors = 0,0,0,0,0
|
10
10
|
super()
|
11
11
|
end
|
12
12
|
|
@@ -16,9 +16,10 @@ class TourBus < Monitor
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
def update_stats(runs,passes,fails,errors)
|
19
|
+
def update_stats(runs,tests,passes,fails,errors)
|
20
20
|
synchronize do
|
21
21
|
@runs += runs
|
22
|
+
@tests += tests
|
22
23
|
@passes += passes
|
23
24
|
@fails += fails
|
24
25
|
@errors += errors
|
@@ -48,11 +49,11 @@ class TourBus < Monitor
|
|
48
49
|
log "Starting #{tour_name}"
|
49
50
|
threads << Thread.new do
|
50
51
|
runner_id = next_runner_id
|
51
|
-
runs,passes,fails,errors,start = 0,0,0,0,Time.now.to_f
|
52
|
+
runs,tests,passes,fails,errors,start = 0,0,0,0,0,Time.now.to_f
|
52
53
|
bm = Benchmark.measure do
|
53
|
-
runner = Runner.new(@host, @tours, @number, runner_id)
|
54
|
-
runs,passes,fails,errors = runner.run_tours
|
55
|
-
update_stats runs, passes, fails, errors
|
54
|
+
runner = Runner.new(@host, @tours, @number, runner_id, @test_list)
|
55
|
+
runs,tests,passes,fails,errors = runner.run_tours(@test_list)
|
56
|
+
update_stats runs, tests, passes, fails, errors
|
56
57
|
end
|
57
58
|
log "Runner Finished!"
|
58
59
|
log "Runner finished in %0.3f seconds" % (Time.now.to_f - start)
|
@@ -66,12 +67,13 @@ class TourBus < Monitor
|
|
66
67
|
log '-' * 80
|
67
68
|
log tour_name
|
68
69
|
log "All Runners finished."
|
69
|
-
log "Total
|
70
|
+
log "Total Tours: #{@runs}"
|
71
|
+
log "Total Tests: #{@tests}"
|
70
72
|
log "Total Passes: #{@passes}"
|
71
73
|
log "Total Fails: #{@fails}"
|
72
74
|
log "Total Errors: #{@errors}"
|
73
75
|
log "Elapsed Time: #{finished - started}"
|
74
|
-
log "Speed: %5.3f
|
76
|
+
log "Speed: %5.3f tours/sec" % (@runs / (finished-started))
|
75
77
|
log '-' * 80
|
76
78
|
if @fails > 0 || @errors > 0
|
77
79
|
log '********************************************************************************'
|
metadata
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dbrady-tourbus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Brady
|
8
|
+
- James Britt
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
12
|
|
12
|
-
date: 2009-
|
13
|
+
date: 2009-04-17 00:00:00 -07:00
|
13
14
|
default_executable:
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
@@ -52,7 +53,7 @@ dependencies:
|
|
52
53
|
- !ruby/object:Gem::Version
|
53
54
|
version: "0"
|
54
55
|
version:
|
55
|
-
description: TourBus web stress-testing tool
|
56
|
+
description: TourBus, a web stress-testing tool that combines complex 'tour' definitions with scalable concurrent testing
|
56
57
|
email: github@shinybit.com
|
57
58
|
executables:
|
58
59
|
- tourbus
|
@@ -60,7 +61,7 @@ executables:
|
|
60
61
|
extensions: []
|
61
62
|
|
62
63
|
extra_rdoc_files:
|
63
|
-
- README.
|
64
|
+
- README.rdoc
|
64
65
|
- MIT-LICENSE
|
65
66
|
- examples/contact_app/README.rdoc
|
66
67
|
files:
|
@@ -86,16 +87,16 @@ files:
|
|
86
87
|
- lib/web-sickle/spec/spec_helper.rb
|
87
88
|
- lib/web-sickle/spec/spec_helpers/mechanize_mock_helper.rb
|
88
89
|
- lib/web-sickle/spec/web_sickle_spec.rb
|
89
|
-
- README.
|
90
|
+
- README.rdoc
|
90
91
|
- MIT-LICENSE
|
91
92
|
has_rdoc: true
|
92
|
-
homepage: http://github.com/
|
93
|
+
homepage: http://github.com/jamesbritt/tourbus/
|
93
94
|
post_install_message:
|
94
95
|
rdoc_options:
|
95
96
|
- --line-numbers
|
96
97
|
- --inline-source
|
97
98
|
- --main
|
98
|
-
- README.
|
99
|
+
- README.rdoc
|
99
100
|
- --title
|
100
101
|
- Tourbus - Web Stress Testing in Ruby
|
101
102
|
require_paths:
|