abcrunch 0.0.4

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.
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ describe "AbCrunch::StrategyBestConcurrency" do
4
+
5
+ describe "#run" do
6
+ before :each do
7
+ @test_page = AbCrunchSpec.new_page
8
+ @fake_result = AbCrunchSpec.new_result
9
+
10
+ stub(AbCrunch::BestRun).of_avg_response_time { @fake_result }
11
+ stub(AbCrunch::StrategyBestConcurrency).find_best_concurrency { @fake_result }
12
+ stub(AbCrunch::Logger).log
13
+ end
14
+
15
+ it "should get the baseline using the global options merged with the page" do
16
+ page = AbCrunch::Config.best_concurrency_options.merge(@test_page)
17
+ mock(AbCrunch::BestRun).of_avg_response_time(page[:num_baseline_runs], page)
18
+
19
+ AbCrunch::StrategyBestConcurrency.run(@test_page)
20
+ end
21
+
22
+ it "should use page option overrides" do
23
+ in_page = @test_page.merge({:num_baseline_runs => 17})
24
+ expected_page = AbCrunch::Config.best_concurrency_options.merge(in_page)
25
+ mock(AbCrunch::BestRun).of_avg_response_time(17, expected_page) {@fake_result}
26
+ proxy(AbCrunch::Config.best_concurrency_options).merge(in_page)
27
+
28
+ AbCrunch::StrategyBestConcurrency.run(in_page)
29
+ end
30
+
31
+ it "should find the max concurrency" do
32
+ expected_page = AbCrunch::Config.best_concurrency_options.merge(@test_page)
33
+ mock(AbCrunch::StrategyBestConcurrency).find_best_concurrency(expected_page, @fake_result) {@fake_result}
34
+
35
+ AbCrunch::StrategyBestConcurrency.run(@test_page)
36
+ end
37
+ end
38
+
39
+ describe "#calc_threshold" do
40
+ describe "when max latency is higher than the base response time plus the percent margin" do
41
+ it "should return the base response time plus the percent margin" do
42
+ AbCrunch::StrategyBestConcurrency.calc_threshold(100, 0.2, 200).should == 120.0
43
+ end
44
+ end
45
+ describe "when max latency is lower than the base response time plus the percent margin" do
46
+ it "should return the max latency" do
47
+ AbCrunch::StrategyBestConcurrency.calc_threshold(190, 0.2, 200).should == 200.0
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "#find_best_concurrency" do
53
+ before :each do
54
+ @test_page = AbCrunchSpec.new_page({:num_requests => 50})
55
+ @fake_result = AbCrunchSpec.new_result
56
+
57
+ stub(AbCrunch::Logger).log
58
+ end
59
+
60
+ describe "when performance degrades" do
61
+ it "should return the ab result for the run with the highest concurrency before response time degrades" do
62
+ input_page = AbCrunch::Config.best_concurrency_options.merge(@test_page).merge({:num_concurrency_runs => 3})
63
+ test_page_1 = input_page.clone.merge({:concurrency => 1})
64
+ test_result_1 = @fake_result.clone
65
+ test_result_1.ab_options = test_page_1
66
+
67
+ test_page_2 = input_page.clone.merge({:concurrency => 2})
68
+ test_result_2 = @fake_result.clone
69
+ test_result_2.ab_options = test_page_2
70
+
71
+ test_page_3 = input_page.clone.merge({:concurrency => 3})
72
+ desired_result = @fake_result.clone
73
+ desired_result.ab_options = test_page_3
74
+ stub(desired_result).avg_response_time { 90.3 }
75
+
76
+ test_page_4 = input_page.clone.merge({:concurrency => 4})
77
+ degraded_result = @fake_result.clone
78
+ degraded_result.ab_options = test_page_4
79
+ stub(degraded_result).avg_response_time { 9999.3 }
80
+
81
+ stub(AbCrunch::BestRun).of_avg_response_time(3, test_page_1) { test_result_1 }
82
+ stub(AbCrunch::BestRun).of_avg_response_time(3, test_page_2) { test_result_2 }
83
+ stub(AbCrunch::BestRun).of_avg_response_time(3, test_page_3) { desired_result }
84
+ stub(AbCrunch::BestRun).of_avg_response_time(3, test_page_4) { degraded_result }
85
+
86
+ result = AbCrunch::StrategyBestConcurrency.find_best_concurrency(input_page, @fake_result)
87
+
88
+ result.ab_options[:concurrency].should == 3
89
+ result.avg_response_time.should == 90.3
90
+ result.should == desired_result
91
+ end
92
+ end
93
+
94
+ describe "when concurrency exceeds num requests before performance degrades" do
95
+ it "should return the latest result" do
96
+ input_page = AbCrunch::Config.best_concurrency_options.merge(@test_page).merge({:num_concurrency_runs => 3, :num_requests => 3})
97
+ test_page_1 = input_page.clone.merge({:concurrency => 1})
98
+ test_result_1 = @fake_result.clone
99
+ test_result_1.ab_options = test_page_1
100
+
101
+ test_page_2 = input_page.clone.merge({:concurrency => 2})
102
+ test_result_2 = @fake_result.clone
103
+ test_result_2.ab_options = test_page_2
104
+
105
+ test_page_3 = input_page.clone.merge({:concurrency => 3})
106
+ desired_result = @fake_result.clone
107
+ desired_result.ab_options = test_page_3
108
+ stub(desired_result).avg_response_time { 90.3 }
109
+
110
+ stub(AbCrunch::BestRun).of_avg_response_time(3, test_page_1) { test_result_1 }
111
+ stub(AbCrunch::BestRun).of_avg_response_time(3, test_page_2) { test_result_2 }
112
+ stub(AbCrunch::BestRun).of_avg_response_time(3, test_page_3) { desired_result }
113
+
114
+ result = AbCrunch::StrategyBestConcurrency.find_best_concurrency(input_page, @fake_result)
115
+
116
+ result.ab_options[:concurrency].should == 3
117
+ result.avg_response_time.should == 90.3
118
+ result.should == desired_result
119
+ end
120
+ end
121
+
122
+ end
123
+
124
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe "AbCrunch::Tester" do
4
+ before :each do
5
+ stub(AbCrunch::Logger).log
6
+
7
+ @test_pages = [
8
+ AbCrunchSpec.new_page,
9
+ AbCrunchSpec.new_page,
10
+ AbCrunchSpec.new_page,
11
+ ]
12
+
13
+ @fake_page_results = [
14
+ [true, AbCrunchSpec.new_result, []],
15
+ [true, AbCrunchSpec.new_result, []],
16
+ [true, AbCrunchSpec.new_result, []],
17
+ ]
18
+
19
+ @fake_failed_page_results = [
20
+ [true, AbCrunchSpec.new_result, []],
21
+ [true, AbCrunchSpec.new_result, []],
22
+ [false, AbCrunchSpec.new_result, ['some error','another']],
23
+ ]
24
+ end
25
+
26
+ describe "#test" do
27
+ it "should test each of the given pages" do
28
+ tested_pages = []
29
+
30
+ stub(AbCrunch::PageTester).test do |page|
31
+ tested_pages << page
32
+ @fake_page_results[0]
33
+ end
34
+
35
+ AbCrunch::Tester.test(@test_pages)
36
+
37
+ tested_pages.should == @test_pages
38
+ end
39
+
40
+ it "should collect and return the results for every page" do
41
+ expected_test_results = @fake_page_results.each_with_index.map do |page_result, idx|
42
+ {
43
+ :page => @test_pages[idx],
44
+ :passed => page_result[0],
45
+ :qps_result => page_result[1],
46
+ :errors => page_result[2]
47
+ }
48
+ end
49
+
50
+ call_idx = -1
51
+ stub(AbCrunch::PageTester).test do
52
+ call_idx += 1
53
+ @fake_page_results[call_idx]
54
+ end
55
+
56
+ test_results = AbCrunch::Tester.test(@test_pages)
57
+
58
+ test_results.should == expected_test_results
59
+ end
60
+
61
+ it "should raise an error if there are any load test failures" do
62
+ call_idx = -1
63
+ stub(AbCrunch::PageTester).test do
64
+ call_idx += 1
65
+ @fake_failed_page_results[call_idx]
66
+ end
67
+
68
+ lambda do
69
+ AbCrunch::Tester.test(@test_pages)
70
+ end.should raise_error "Load tests FAILED\nsome error\nanother"
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,7 @@
1
+ RSpec.configure do |conf|
2
+ conf.mock_with :rr
3
+ end
4
+
5
+ require File.join(File.dirname(__FILE__), "../lib/abcrunch")
6
+
7
+ Dir[File.join(File.dirname(__FILE__), "helpers/**/*.rb")].each { |f| require f }
@@ -0,0 +1,15 @@
1
+ require "rspec/core/rake_task"
2
+
3
+ spec_tasks = Dir['spec/*/'].map { |d| File.basename(d) } - ["javascripts"]
4
+
5
+ spec_tasks.each do |folder|
6
+ RSpec::Core::RakeTask.new("spec:#{folder}") do |t|
7
+ t.pattern = "./spec/#{folder}/**/*_spec.rb"
8
+ t.rspec_opts = %w(-fs --color)
9
+ end
10
+ end
11
+
12
+ desc "Run complete application spec suite"
13
+ task 'spec' do
14
+ spec_tasks.each { |f| Rake::Task["spec:#{f}"].invoke }
15
+ end
metadata ADDED
@@ -0,0 +1,141 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: abcrunch
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chris Lichti
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-25 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &2155910360 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2155910360
25
+ - !ruby/object:Gem::Dependency
26
+ name: rr
27
+ requirement: &2155909940 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2155909940
36
+ - !ruby/object:Gem::Dependency
37
+ name: colorize
38
+ requirement: &2155909520 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *2155909520
47
+ description: ! 'The idea behind Ab Crunch is that basic performance metrics and standards
48
+ should
49
+
50
+ be effortless, first-class citizens in the development process, with frequent visibility
51
+
52
+ and immediate feedback when performance issues are introduced.
53
+
54
+
55
+ Ab Crunch uses Apache Bench to run various strategies for load testing web projects,
56
+
57
+ and provides rake tasks for analyzing performance and enforcing performance
58
+
59
+ standards on CI.
60
+
61
+ '
62
+ email:
63
+ - kai@truecar.com
64
+ executables: []
65
+ extensions: []
66
+ extra_rdoc_files: []
67
+ files:
68
+ - .gitignore
69
+ - .rvmrc
70
+ - Gemfile
71
+ - Gemfile.lock
72
+ - README
73
+ - Rakefile
74
+ - ab_honk.rb
75
+ - abcrunch.gemspec
76
+ - lib/abcrunch.rb
77
+ - lib/abcrunch/ab_result.rb
78
+ - lib/abcrunch/ab_runner.rb
79
+ - lib/abcrunch/best_run.rb
80
+ - lib/abcrunch/config.rb
81
+ - lib/abcrunch/log_console_writer.rb
82
+ - lib/abcrunch/logger.rb
83
+ - lib/abcrunch/page.rb
84
+ - lib/abcrunch/page_tester.rb
85
+ - lib/abcrunch/strategy_best_concurrency.rb
86
+ - lib/abcrunch/tasks/default.rake
87
+ - lib/abcrunch/tasks/example.rake
88
+ - lib/abcrunch/tasks/generated.rake
89
+ - lib/abcrunch/tester.rb
90
+ - lib/abcrunch/version.rb
91
+ - spec/helpers/page_helper.rb
92
+ - spec/lib/ab_result_spec.rb
93
+ - spec/lib/ab_runner_spec.rb
94
+ - spec/lib/best_run_spec.rb
95
+ - spec/lib/config_spec.rb
96
+ - spec/lib/log_console_writer_spec.rb
97
+ - spec/lib/logger_spec.rb
98
+ - spec/lib/page_spec.rb
99
+ - spec/lib/page_tester_spec.rb
100
+ - spec/lib/strategy_best_concurrency_spec.rb
101
+ - spec/lib/tester_spec.rb
102
+ - spec/spec_helper.rb
103
+ - spec/tasks/spec.rake
104
+ homepage: https://github.com/kurisu/abcrunch
105
+ licenses: []
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ! '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ! '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubyforge_project: abcrunch
124
+ rubygems_version: 1.8.6
125
+ signing_key:
126
+ specification_version: 3
127
+ summary: Automated load testing in ruby
128
+ test_files:
129
+ - spec/helpers/page_helper.rb
130
+ - spec/lib/ab_result_spec.rb
131
+ - spec/lib/ab_runner_spec.rb
132
+ - spec/lib/best_run_spec.rb
133
+ - spec/lib/config_spec.rb
134
+ - spec/lib/log_console_writer_spec.rb
135
+ - spec/lib/logger_spec.rb
136
+ - spec/lib/page_spec.rb
137
+ - spec/lib/page_tester_spec.rb
138
+ - spec/lib/strategy_best_concurrency_spec.rb
139
+ - spec/lib/tester_spec.rb
140
+ - spec/spec_helper.rb
141
+ - spec/tasks/spec.rake