dbrady-tourbus 0.0.7 → 0.0.8
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.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:
|