celluloid-benchmark 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +20 -0
- data/README.md +132 -0
- data/bin/celluloid-benchmark +16 -0
- data/lib/celluloid_benchmark.rb +5 -0
- data/test/files/runner_test_session.rb +2 -0
- data/test/integration/config.ru +9 -0
- data/test/integration/html/404.html +10 -0
- data/test/integration/html/index.html +10 -0
- data/test/integration/integration_test.rb +55 -0
- data/test/integration/test_session.rb +2 -0
- data/test/unit/benchmark_run_test.rb +130 -0
- data/test/unit/benchmark_test.rb +107 -0
- data/test/unit/runner_test.rb +24 -0
- data/test/unit/visitor_test.rb +64 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a8b43cb7f1b3f835c28eef1361299b99b8188a1e
|
4
|
+
data.tar.gz: 2025783e8cc49d76300263cc7df9ba991af36120
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1e1bf981e517e15d3c6698c42b7bd5bc388266203bc7a82f09e2824bef6c95d67fef09d0b213113577c6100528c0e7ed107b43c1b9993c65f0c79d65109ba3ad
|
7
|
+
data.tar.gz: b970a27dba6d16cb152c486077cc879de84d6827444ddf968abbb9cd981a5b6c4a8f056510a6a774efd7bce91bbb36f8978b025fa897f9fdf0037ff0d6864eef
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Scott Willson
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
Celluloid Benchmark realistically load tests websites.
|
2
|
+
|
3
|
+
Write expressive, concise load tests in Ruby. Use [Rubinius](http://rubini.us) and [Celluloid](https://github.com/celluloid/celluloid)
|
4
|
+
for high concurrency. Use [Mechanize](http://mechanize.rubyforge.org) for a realistic (albeit non-JavaScript) browser client.
|
5
|
+
|
6
|
+
Getting Started
|
7
|
+
===============
|
8
|
+
celluloid-benchmark test/files/runner_test_session.rb
|
9
|
+
|
10
|
+
Congrats! You just load-tested the project's Github page.
|
11
|
+
|
12
|
+
For your own tests, create a session file and pass its path to celluloid-benchmark.
|
13
|
+
|
14
|
+
Simple scenario
|
15
|
+
---------------
|
16
|
+
benchmark :home_page, 1
|
17
|
+
get "https://github.com/scottwillson/celluloid-benchmark"
|
18
|
+
|
19
|
+
`benchmark :label, duration` means "measure the following requests and group them under 'label'".
|
20
|
+
Duration is optional and defaults to 0.3 seconds.
|
21
|
+
|
22
|
+
Find and click a link
|
23
|
+
---------------------
|
24
|
+
page = get "/offer/1"
|
25
|
+
buy_now_link = page.links_with(class: "buy_button").first
|
26
|
+
|
27
|
+
benchmark :purchase_new
|
28
|
+
page = get(buy_now_link.href)
|
29
|
+
|
30
|
+
Forms
|
31
|
+
-----
|
32
|
+
form = page.forms_with(class: "simple_form purchase_form").first
|
33
|
+
form["CARDNO"] = "4111111111111111"
|
34
|
+
submit(form)
|
35
|
+
|
36
|
+
HTTP auth
|
37
|
+
---------
|
38
|
+
add_auth "https://staging.example.com", "qa", "password"
|
39
|
+
|
40
|
+
|
41
|
+
Simulate AJAX
|
42
|
+
-------------
|
43
|
+
transact do
|
44
|
+
get "https://example.com/post_zones/AAA1NNN", [], nil, {
|
45
|
+
"Accept" => "application/json, text/javascript, */*; q=0.01",
|
46
|
+
"X-Requested-With" => "XMLHttpRequest"
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
Test data
|
51
|
+
---------
|
52
|
+
Because test scenarios are plain Ruby, you can drive tests in many different ways. The
|
53
|
+
[Faker gem](http://rubydoc.info/github/stympy/faker/master/frames) is handy
|
54
|
+
for random, realistic test data:
|
55
|
+
|
56
|
+
require "faker"
|
57
|
+
first_name = Faker::Name.first_name
|
58
|
+
last_name = Faker::Name.last_name
|
59
|
+
post_town = Faker::Address.city
|
60
|
+
|
61
|
+
form["CN"] = "#{first_name} #{last_name}"
|
62
|
+
form["c[addr][post_town]"] = post_town
|
63
|
+
|
64
|
+
The [Forgery gem](http://sevenwire.github.io/forgery/) is good, too.
|
65
|
+
|
66
|
+
Celluloid Benchmark can also pull random test data from CSV files. For example:
|
67
|
+
|
68
|
+
get "https://example.com/post_zones/#{random_data(:post_zone)}"
|
69
|
+
|
70
|
+
`random_data(:post_zone)` pulls a random line from tmp/data/post_zones.csv
|
71
|
+
|
72
|
+
Celluloid Benchmark agents delegate calls to Mechanize. If you need something more complicated
|
73
|
+
than the examples, check out the [Mechanize API](http://mechanize.rubyforge.org/HTTP/Agent.html) and call it directly with `browser.` in your test scenario.
|
74
|
+
|
75
|
+
For a longer test, pass in a second duration argument (seconds):
|
76
|
+
celluloid-benchmark my_test_session.rb 180
|
77
|
+
|
78
|
+
Why
|
79
|
+
===
|
80
|
+
I need to simulate a lot of realistic traffic against preproduction code.
|
81
|
+
There are many good tools that can put a high load on a static URL (e.g., [ab](http://httpd.apache.org/docs/2.2/programs/ab.html)), and there are a few tools
|
82
|
+
(e.g., [Tsung](http://tsung.erlang-projects.org)) that can generate realistic multiple-URL loads. By "realistic" I mean: follow links, maintain
|
83
|
+
session state from one page to the next, simulate different types of simultaneous visitors (5% admin users + 10%
|
84
|
+
business customers + 75% consumers). I found it difficult to maintain complex scenarios. Our Tsung tests,
|
85
|
+
for instance, exploded into many ERB files that concatenated into a giant Tsung XML config (with some custom Erlang
|
86
|
+
functions). I also wanted control over recording and displaying test results.
|
87
|
+
|
88
|
+
Wouldn't it be nice to just write Ruby?
|
89
|
+
|
90
|
+
Yes, expect for that Ruby GIL issue. Which led me to Rubinius and Celluloid.
|
91
|
+
|
92
|
+
Rubinius is a concurrency-friendly implementation of Ruby, and Celluloid is a nice Ruby actor framework.
|
93
|
+
|
94
|
+
Celluloid also works with MRI 1.9 and 2.0, though Celluloid Benchmark can generate more concurrent load with
|
95
|
+
Rubinius. [JRuby](http://jruby.org) should also work well, maybe better.
|
96
|
+
|
97
|
+
I've just added features I need, but it should be easy to add more. For example:
|
98
|
+
|
99
|
+
* Pull specific keys/columns from CSV files
|
100
|
+
* Add random "think times" for visitors to pause on pages
|
101
|
+
|
102
|
+
Alternatives
|
103
|
+
============
|
104
|
+
|
105
|
+
Simple
|
106
|
+
------
|
107
|
+
[ab (Apache Bench)](http://httpd.apache.org/docs/2.2/programs/ab.html)
|
108
|
+
|
109
|
+
[httperf](http://www.hpl.hp.com/research/linux/httperf/)
|
110
|
+
|
111
|
+
[siege](http://freecode.com/projects/siege)
|
112
|
+
|
113
|
+
|
114
|
+
Complex
|
115
|
+
-------
|
116
|
+
[Tsung](http://tsung.erlang-projects.org)
|
117
|
+
|
118
|
+
[The Grinder](http://grinder.sourceforge.net)
|
119
|
+
|
120
|
+
[JMeter](http://jmeter.apache.org)
|
121
|
+
|
122
|
+
|
123
|
+
Develop
|
124
|
+
=======
|
125
|
+
ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"
|
126
|
+
curl -L https://get.rvm.io | bash
|
127
|
+
rvm install rbx-2.2.1
|
128
|
+
git clone git@github.com:scottwillson/celluloid-benchmark.git
|
129
|
+
cd celluloid-benchmark
|
130
|
+
rvm gemset use celluloid-benchmark --create
|
131
|
+
bundle
|
132
|
+
rake
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative "../lib/celluloid_benchmark"
|
4
|
+
|
5
|
+
benchmark_run = CelluloidBenchmark::Runner.run ARGV[0], (ARGV[1] || 20).to_i
|
6
|
+
|
7
|
+
p benchmark_run
|
8
|
+
puts
|
9
|
+
p "#{benchmark_run.requests / benchmark_run.elapsed_time} requests per second. #{benchmark_run.requests} requests in #{benchmark_run.elapsed_time} seconds by #{Celluloid::Actor[:visitor_pool].size} visitors."
|
10
|
+
|
11
|
+
puts
|
12
|
+
benchmark_run.benchmarks.each do |trans|
|
13
|
+
puts "#{trans.ok? ? '[ OK ]' : '[FAIL]'} #{trans.label}"
|
14
|
+
end
|
15
|
+
|
16
|
+
exit benchmark_run.ok?
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require "minitest/autorun"
|
2
|
+
require_relative "../../lib/celluloid_benchmark"
|
3
|
+
|
4
|
+
module CelluloidBenchmark
|
5
|
+
class IntegrationTest < Minitest::Test
|
6
|
+
def setup
|
7
|
+
# minitest and Celluloid both use at_exit
|
8
|
+
Celluloid.boot
|
9
|
+
|
10
|
+
start_target_webserver
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown
|
14
|
+
stop_target_webserver
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_happy_path
|
18
|
+
assert target_webserver_responsive?, "Test web server did not respond OK"
|
19
|
+
|
20
|
+
session_path = File.expand_path(File.dirname(__FILE__) + "/test_session.rb")
|
21
|
+
duration = 5
|
22
|
+
benchmark_run = CelluloidBenchmark::Runner.run(session_path, duration)
|
23
|
+
|
24
|
+
assert benchmark_run.ok?, "Run should be OK"
|
25
|
+
end
|
26
|
+
|
27
|
+
def start_target_webserver
|
28
|
+
`thin --threaded --rackup test/integration/config.ru --daemonize --port 8000 start`
|
29
|
+
end
|
30
|
+
|
31
|
+
def stop_target_webserver
|
32
|
+
`thin stop`
|
33
|
+
end
|
34
|
+
|
35
|
+
def target_webserver_responsive?
|
36
|
+
require "net/http"
|
37
|
+
require "uri"
|
38
|
+
|
39
|
+
uri = URI.parse("http://localhost:8000/")
|
40
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
41
|
+
Timeout::timeout(5) do
|
42
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
43
|
+
begin
|
44
|
+
response = http.request(request)
|
45
|
+
if response.code.to_i == 200
|
46
|
+
return true
|
47
|
+
end
|
48
|
+
rescue Errno::ECONNREFUSED, Net::HTTP::Persistent::Error
|
49
|
+
# Ignore. Server might be starting up.
|
50
|
+
end
|
51
|
+
sleep 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require "minitest/autorun"
|
2
|
+
require "timecop"
|
3
|
+
require_relative "../../lib/celluloid_benchmark/benchmark_run"
|
4
|
+
|
5
|
+
module CelluloidBenchmark
|
6
|
+
class BenchmarkRunTest < Minitest::Test
|
7
|
+
def setup
|
8
|
+
# minitest and Celluloid both use at_exit
|
9
|
+
Celluloid.boot
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_new
|
13
|
+
BenchmarkRun.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_inspect
|
17
|
+
BenchmarkRun.new.inspect
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_log
|
21
|
+
benchmark_run = BenchmarkRun.new
|
22
|
+
logger = Minitest::Mock.new
|
23
|
+
logger.expect :info, true, [ "200 1 search"]
|
24
|
+
benchmark_run.logger = logger
|
25
|
+
benchmark_run.log 200, 1, 2, "search", 3
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_response_times
|
29
|
+
benchmark_run = BenchmarkRun.new
|
30
|
+
assert_equal Hash.new, benchmark_run.response_times
|
31
|
+
|
32
|
+
benchmark_run.log 200, 3, 4, "search", 0
|
33
|
+
assert_equal({ "search" => [ 1 ] }, benchmark_run.response_times)
|
34
|
+
|
35
|
+
benchmark_run.log 200, 40, 100, "search", 3
|
36
|
+
search_times = benchmark_run.response_times[ "search" ]
|
37
|
+
assert_equal [ 1, 60 ], search_times.sort
|
38
|
+
|
39
|
+
benchmark_run.log 404, 1000, 2000, "home", 3
|
40
|
+
search_times = benchmark_run.response_times[ "search" ]
|
41
|
+
assert_equal [ 1, 60 ], search_times.sort
|
42
|
+
assert_equal [ 1000 ], benchmark_run.response_times[ "home" ]
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_response_codes
|
46
|
+
benchmark_run = BenchmarkRun.new
|
47
|
+
assert_equal Hash.new, benchmark_run.response_codes
|
48
|
+
|
49
|
+
benchmark_run.log 200, 3, 4, "search", 0
|
50
|
+
assert_equal({ "search" => [ 200 ] }, benchmark_run.response_codes)
|
51
|
+
|
52
|
+
benchmark_run.log 302, 40, 100, "search", 3
|
53
|
+
search_codes = benchmark_run.response_codes[ "search" ]
|
54
|
+
assert_equal [ 200, 302 ], search_codes.sort
|
55
|
+
|
56
|
+
benchmark_run.log 404, 1000, 2000, "home", 3
|
57
|
+
search_codes = benchmark_run.response_codes[ "search" ]
|
58
|
+
assert_equal [ 200, 302 ], search_codes.sort
|
59
|
+
assert_equal [ 404 ], benchmark_run.response_codes[ "home" ]
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_requests
|
63
|
+
benchmark_run = BenchmarkRun.new
|
64
|
+
assert_equal 0, benchmark_run.requests
|
65
|
+
|
66
|
+
benchmark_run.log 200, 3, 4, "search", 0
|
67
|
+
assert_equal 1, benchmark_run.requests
|
68
|
+
|
69
|
+
benchmark_run.log 200, 3, 4, "search", 0
|
70
|
+
assert_equal 2, benchmark_run.requests
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_benchmarks
|
74
|
+
benchmark_run = BenchmarkRun.new
|
75
|
+
assert_equal 0, benchmark_run.benchmarks.size
|
76
|
+
assert benchmark_run.benchmarks.empty?
|
77
|
+
|
78
|
+
benchmark_run.log 200, 3, 4, "search", 0.01
|
79
|
+
assert_equal 1, benchmark_run.benchmarks.size
|
80
|
+
benchmark = benchmark_run.benchmarks.first
|
81
|
+
assert_equal "search", benchmark.label, "benchmark label"
|
82
|
+
assert_equal 0.01, benchmark.threshold, "benchmark threshold"
|
83
|
+
assert_equal [ 1 ], benchmark.response_times, "benchmark response_times"
|
84
|
+
assert_equal [ 200 ], benchmark.response_codes, "benchmark response_codes"
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_mark_start
|
88
|
+
benchmark_run = BenchmarkRun.new
|
89
|
+
assert_equal nil, benchmark_run.started_at, "started_at"
|
90
|
+
|
91
|
+
Timecop.freeze(Time.new(2001, 4, 5, 18, 30)) do
|
92
|
+
benchmark_run.mark_start
|
93
|
+
end
|
94
|
+
|
95
|
+
assert_equal Time.new(2001, 4, 5, 18, 30), benchmark_run.started_at
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_mark_end
|
99
|
+
benchmark_run = BenchmarkRun.new
|
100
|
+
assert_equal nil, benchmark_run.ended_at, "ended_at"
|
101
|
+
|
102
|
+
Timecop.freeze(Time.new(2001, 4, 5, 18, 30)) do
|
103
|
+
benchmark_run.mark_end
|
104
|
+
end
|
105
|
+
|
106
|
+
assert_equal Time.new(2001, 4, 5, 18, 30), benchmark_run.ended_at
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_ok
|
110
|
+
benchmark_run = BenchmarkRun.new
|
111
|
+
assert benchmark_run.ok?
|
112
|
+
|
113
|
+
benchmark_run.stub :benchmarks, [ Minitest::Mock.new.expect(:ok?, true) ] do
|
114
|
+
assert benchmark_run.ok?
|
115
|
+
end
|
116
|
+
|
117
|
+
benchmark_run.stub :benchmarks, [ Minitest::Mock.new.expect(:ok?, true), Minitest::Mock.new.expect(:ok?, true) ] do
|
118
|
+
assert benchmark_run.ok?
|
119
|
+
end
|
120
|
+
|
121
|
+
benchmark_run.stub :benchmarks, [ Minitest::Mock.new.expect(:ok?, false), Minitest::Mock.new.expect(:ok?, true) ] do
|
122
|
+
assert !benchmark_run.ok?
|
123
|
+
end
|
124
|
+
|
125
|
+
benchmark_run.stub :benchmarks, [ Minitest::Mock.new.expect(:ok?, false), Minitest::Mock.new.expect(:ok?, false) ] do
|
126
|
+
assert !benchmark_run.ok?
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require "minitest/autorun"
|
2
|
+
require_relative "../../lib/celluloid_benchmark/benchmark"
|
3
|
+
|
4
|
+
module CelluloidBenchmark
|
5
|
+
class BenchmarkTest < Minitest::Test
|
6
|
+
def test_require_label
|
7
|
+
assert_raises ArgumentError do
|
8
|
+
Benchmark.new(nil, 1, [], [])
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_require_threshold_above_zero
|
13
|
+
assert_raises ArgumentError do
|
14
|
+
Benchmark.new("homepage", 0, nil, nil)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_defaults
|
19
|
+
benchmark = Benchmark.new("homepage", nil, nil, nil)
|
20
|
+
|
21
|
+
assert_equal 3, benchmark.threshold, "default threshold"
|
22
|
+
|
23
|
+
assert !benchmark.response_codes.nil?, "response_codes default"
|
24
|
+
assert benchmark.response_codes.empty?, "response_codes default"
|
25
|
+
|
26
|
+
assert !benchmark.response_times.nil?, "response_times default"
|
27
|
+
assert benchmark.response_times.empty?, "response_times default"
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_response_times_ok_for_empty_benchmark
|
31
|
+
benchmark = Benchmark.new("homepage", nil, nil, nil)
|
32
|
+
assert benchmark.ok?, "Empty Benchmark should be OK"
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_ok_if_response_codes_and_times_ok
|
36
|
+
benchmark = Benchmark.new("homepage", nil, nil, nil)
|
37
|
+
|
38
|
+
benchmark.stub(:response_times_ok?, true) do
|
39
|
+
benchmark.stub(:response_codes_ok?, true) do
|
40
|
+
assert benchmark.ok?, "Benchmark.ok? times OK and codes OK"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
benchmark.stub(:response_times_ok?, false) do
|
45
|
+
benchmark.stub(:response_codes_ok?, true) do
|
46
|
+
assert !benchmark.ok?, "Benchmark.ok? times not OK and codes OK"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
benchmark.stub(:response_times_ok?, true) do
|
51
|
+
benchmark.stub(:response_codes_ok?, false) do
|
52
|
+
assert !benchmark.ok?, "Benchmark.ok? times OK and codes not OK"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
benchmark.stub(:response_times_ok?, false) do
|
57
|
+
benchmark.stub(:response_codes_ok?, false) do
|
58
|
+
assert !benchmark.ok?, "Benchmark.ok? times not OK and codes not OK"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_blank_response_time_ok
|
64
|
+
benchmark = Benchmark.new("homepage", nil, nil, nil)
|
65
|
+
assert benchmark.response_times_ok?
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_blank_response_codes_ok
|
69
|
+
benchmark = Benchmark.new("homepage", nil, nil, nil)
|
70
|
+
assert benchmark.response_codes_ok?
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_response_times
|
74
|
+
benchmark = Benchmark.new("test", 1, [ 0.99, 0.9, 1.01 ], nil)
|
75
|
+
assert benchmark.response_times_ok?
|
76
|
+
|
77
|
+
benchmark = Benchmark.new("test", 1, [ 1.000001, 1, 1 ], nil)
|
78
|
+
assert !benchmark.response_times_ok?
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_response_codes
|
82
|
+
benchmark = Benchmark.new("test", nil, [], [])
|
83
|
+
assert benchmark.response_codes_ok?
|
84
|
+
|
85
|
+
benchmark = Benchmark.new("test", nil, [], [ 500 ])
|
86
|
+
assert !benchmark.response_codes_ok?
|
87
|
+
|
88
|
+
benchmark = Benchmark.new("test", nil, [], [ 200 ])
|
89
|
+
assert benchmark.response_codes_ok?
|
90
|
+
|
91
|
+
benchmark = Benchmark.new("test", nil, [], [ 200, 500 ])
|
92
|
+
assert !benchmark.response_codes_ok?
|
93
|
+
|
94
|
+
benchmark = Benchmark.new("test", nil, [], [ 200, 302, 304, 401 ])
|
95
|
+
assert benchmark.response_codes_ok?
|
96
|
+
|
97
|
+
benchmark = Benchmark.new("test", nil, [], [ 403, 200, 302, 401 ])
|
98
|
+
assert !benchmark.response_codes_ok?
|
99
|
+
|
100
|
+
benchmark = Benchmark.new("test", nil, [], [ 410, 200, 302, 401 ])
|
101
|
+
assert !benchmark.response_codes_ok?
|
102
|
+
|
103
|
+
benchmark = Benchmark.new("test", nil, [], [ 309, 200, 302, 401 ])
|
104
|
+
assert !benchmark.response_codes_ok?
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "minitest/autorun"
|
2
|
+
require_relative "../../lib/celluloid_benchmark/runner"
|
3
|
+
require "fakeweb"
|
4
|
+
|
5
|
+
FakeWeb.allow_net_connect = false
|
6
|
+
|
7
|
+
module CelluloidBenchmark
|
8
|
+
class BenchmarkRunnerTest < Minitest::Test
|
9
|
+
def setup
|
10
|
+
# minitest and Celluloid both use at_exit
|
11
|
+
Celluloid.boot
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_run
|
15
|
+
FakeWeb.register_uri(:get, "https://github.com/scottwillson/celluloid-benchmark", :body => "<html>OK</html>")
|
16
|
+
benchmark_run = Runner.run(File.dirname(__FILE__) + "/../files/runner_test_session.rb", 0.1)
|
17
|
+
|
18
|
+
benchmarks = benchmark_run.benchmarks
|
19
|
+
assert_equal 1, benchmarks.size
|
20
|
+
benchmark = benchmarks.first
|
21
|
+
assert benchmark.ok?, "benchmark.ok?"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "minitest/autorun"
|
2
|
+
require "celluloid"
|
3
|
+
require_relative "../../lib/celluloid_benchmark/visitor"
|
4
|
+
|
5
|
+
module CelluloidBenchmark
|
6
|
+
# Visitor#run_session is the central purpose of this gem, but best tested in an integration test,
|
7
|
+
# not a unit test
|
8
|
+
class VisitorTest < Minitest::Test
|
9
|
+
class MockBrowser
|
10
|
+
attr_accessor :post_connect_hooks, :pre_connect_hooks, :uris
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@pre_connect_hooks = []
|
14
|
+
@post_connect_hooks = []
|
15
|
+
@uris = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def get(uri)
|
19
|
+
uris << uri
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def setup
|
24
|
+
# minitest and Celluloid both use at_exit
|
25
|
+
Celluloid.boot
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_run_session
|
29
|
+
browser = MockBrowser.new
|
30
|
+
visitor = Visitor.new(browser)
|
31
|
+
session = File.read(File.dirname(__FILE__) + "/../files/runner_test_session.rb")
|
32
|
+
|
33
|
+
elapsed_time = visitor.run_session(session, nil, 0.01)
|
34
|
+
|
35
|
+
assert !elapsed_time.nil?, "elapsed_time should not be nil"
|
36
|
+
assert elapsed_time > 0, "elapsed_time should be greater than zero, but was #{elapsed_time}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_benchmark
|
40
|
+
browser = MockBrowser.new
|
41
|
+
visitor = Visitor.new(browser)
|
42
|
+
|
43
|
+
visitor.benchmark("purchase_page", 0.25)
|
44
|
+
|
45
|
+
assert_equal "purchase_page", visitor.current_request_label, "current_request_label"
|
46
|
+
assert_equal 0.25, visitor.current_request_threshold, "current_request_threshold"
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_random_data
|
50
|
+
browser = MockBrowser.new
|
51
|
+
visitor = Visitor.new(browser)
|
52
|
+
|
53
|
+
data_sources = Minitest::Mock.new
|
54
|
+
data_source = Minitest::Mock.new
|
55
|
+
|
56
|
+
data_source.expect :sample, 3
|
57
|
+
data_sources.expect :[], data_source, [ String ]
|
58
|
+
|
59
|
+
visitor.data_sources = data_sources
|
60
|
+
|
61
|
+
assert_equal 3, visitor.random_data("ids")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: celluloid-benchmark
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Scott Willson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2014-01-09 00:00:00 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: celluloid
|
16
|
+
prerelease: false
|
17
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: "0.15"
|
22
|
+
type: :runtime
|
23
|
+
version_requirements: *id001
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: mechanize
|
26
|
+
prerelease: false
|
27
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ~>
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: "2.7"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id002
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: racc
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ~>
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: "1"
|
42
|
+
type: :runtime
|
43
|
+
version_requirements: *id003
|
44
|
+
description: |-
|
45
|
+
Celluloid Benchmark realistically load tests websites. Write expressive, concise load tests in Ruby. Use Rubinius and Celluloid
|
46
|
+
forpec high concurrency. Use Mechanize for a realistic (albeit non-JavaScript) browser client.
|
47
|
+
email: scott.willson@gmail.com
|
48
|
+
executables:
|
49
|
+
- celluloid-benchmark
|
50
|
+
extensions: []
|
51
|
+
|
52
|
+
extra_rdoc_files: []
|
53
|
+
|
54
|
+
files:
|
55
|
+
- LICENSE
|
56
|
+
- README.md
|
57
|
+
- bin/celluloid-benchmark
|
58
|
+
- lib/celluloid_benchmark.rb
|
59
|
+
- test/files/runner_test_session.rb
|
60
|
+
- test/integration/config.ru
|
61
|
+
- test/integration/html/404.html
|
62
|
+
- test/integration/html/index.html
|
63
|
+
- test/integration/integration_test.rb
|
64
|
+
- test/integration/test_session.rb
|
65
|
+
- test/unit/benchmark_run_test.rb
|
66
|
+
- test/unit/benchmark_test.rb
|
67
|
+
- test/unit/runner_test.rb
|
68
|
+
- test/unit/visitor_test.rb
|
69
|
+
homepage: https://github.com/scottwillson/celluloid-benchmark
|
70
|
+
licenses:
|
71
|
+
- MIT
|
72
|
+
metadata: {}
|
73
|
+
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- &id004
|
82
|
+
- ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: "0"
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- *id004
|
88
|
+
requirements: []
|
89
|
+
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 2.2.1
|
92
|
+
signing_key:
|
93
|
+
specification_version: 4
|
94
|
+
summary: Pure Ruby, realistic, website load test tool
|
95
|
+
test_files:
|
96
|
+
- test/files/runner_test_session.rb
|
97
|
+
- test/integration/config.ru
|
98
|
+
- test/integration/integration_test.rb
|
99
|
+
- test/integration/test_session.rb
|
100
|
+
- test/unit/benchmark_run_test.rb
|
101
|
+
- test/unit/benchmark_test.rb
|
102
|
+
- test/unit/runner_test.rb
|
103
|
+
- test/unit/visitor_test.rb
|
104
|
+
- test/integration/html/404.html
|
105
|
+
- test/integration/html/index.html
|