gas_load_tester 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5c19b328e8870dcddf26020d37a2bc6d547080f0
4
+ data.tar.gz: 98af8da36ef41b023618d029ce67025a5142c2ce
5
+ SHA512:
6
+ metadata.gz: a7ad467ea20c608ce278ffb359c6530ea5be1a864ccc41a22f72c9f1515b641a5d3d525cfbf332f5d05fdcd5ba289d9ecd572ba33a46becea253cdfc9754d2c4
7
+ data.tar.gz: e84fd6a45d808d17e161241d1248829dd5a1143abb9e32aa15c035f697a1866a40ae5dfc3dc3708a11152021b9e9231298f67cf0bd522bcc68b83f3d473181be
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.0
5
+ before_install: gem install bundler -v 1.13.7
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gas_load_tester.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Gas unknown developer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all 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,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # GasLoadTester
2
+
3
+ Simple Ruby load test library. Give it a try !
4
+
5
+ **Warning:** High CPU is needed to run this or you will get an unreliable result. If you are an AWS user, I suggest you to look for spot compute instance for this kind of task.
6
+
7
+ ## Installation
8
+
9
+ Install it yourself as:
10
+
11
+ $ gem install gas_load_tester
12
+
13
+ ## Usage
14
+
15
+ #### Require the library
16
+
17
+ ```ruby
18
+ require 'gas_load_tester'
19
+ ```
20
+
21
+ #### For simple usage
22
+
23
+ ```ruby
24
+ simple_test = GasLoadTester::Test.new({user: 10000, time: 60})
25
+ simple_test.run do
26
+ RestClient.get("https://www.mysite.com", {})
27
+ end
28
+ simple_test.results
29
+ ```
30
+
31
+ #### With html output
32
+
33
+ ```ruby
34
+ simple_test = GasLoadTester::Test.new({user: 10000, time: 60})
35
+ simple_test.run(output: true, file: '/mytest/mysite_result') do
36
+ RestClient.get("https://www.mysite.com", {})
37
+ end
38
+ ```
39
+
40
+ ##### Single test outout is shown as below:
41
+
42
+ [![Gas load tester single test](http://i216.photobucket.com/albums/cc229/gastzar/solotest.png)](https://github.com/gastzars/gas_load_tester)
43
+
44
+
45
+ #### Group comparison test
46
+
47
+ ```ruby
48
+ simple_group_test = GasLoadTester::GroupTest.new([
49
+ {"client" => 100, "time" => 5},
50
+ {"client" => 150, "time" => 10},
51
+ {"client" => 160, "time" => 7}
52
+ ])
53
+ simple_group_test.run(output: true, file: '/mytest/mysite_group_result.html') do
54
+ RestClient.get("https://www.mysite.com", {})
55
+ end
56
+ ```
57
+
58
+ ##### Group test outout is shown as below:
59
+
60
+ [![Gas load tester group test](http://i216.photobucket.com/albums/cc229/gastzar/group_test.png)](https://github.com/gastzars/gas_load_tester)
61
+
62
+ ## Development
63
+
64
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
65
+
66
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
67
+
68
+ ## Contributing
69
+
70
+ Bug reports and pull requests are welcome on GitHub at https://github.com/gastzars/gas_load_tester.
71
+
72
+
73
+ ## License
74
+
75
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
76
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "gas_load_tester"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,40 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'gas_load_tester/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "gas_load_tester"
8
+ spec.version = GasLoadTester::VERSION
9
+ spec.authors = ["Tanapat Sainak"]
10
+ spec.email = ["fallen_things@hotmail.com"]
11
+
12
+ spec.summary = %q{Ruby load test library.}
13
+ spec.description = %q{Simple Ruby load test library.}
14
+ spec.homepage = "https://github.com/gastzars/gas_load_tester"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ #if spec.respond_to?(:metadata)
20
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
21
+ #else
22
+ # raise "RubyGems 2.0 or newer is required to protect against " \
23
+ # "public gem pushes."
24
+ #end
25
+
26
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
27
+ f.match(%r{^(test|spec|features)/})
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+
33
+ spec.add_runtime_dependency 'ruby-progressbar', '~> 1.8.1'
34
+ spec.add_runtime_dependency 'chartkick', '~> 2.2.2'
35
+ spec.add_runtime_dependency 'rest-client'
36
+
37
+ spec.add_development_dependency "bundler", "~> 1.13"
38
+ spec.add_development_dependency "rake", "~> 10.0"
39
+ spec.add_development_dependency "rspec", "~> 3.0"
40
+ end
@@ -0,0 +1,271 @@
1
+ require 'chartkick'
2
+
3
+ module GasLoadTester
4
+ include Chartkick::Helper
5
+
6
+ class ChartBuilder
7
+ include Chartkick::Helper
8
+ attr_accessor :file_name, :body
9
+
10
+ DEFAULT_PAGE_HEAD = "<!DOCTYPE html>"\
11
+ "<html>"\
12
+ "<head>"\
13
+ "<script type=\"text/javascript\" src=\"https://www.google.com/jsapi\"></script>"\
14
+ "<script src=\"https://www.gstatic.com/charts/loader.js\"></script>"\
15
+ "<script src=\"https://ankane.github.io/chartkick.js/chartkick.js\"></script>"\
16
+ "</head>"\
17
+ "<body>"
18
+
19
+ DEFAULT_PAGE_TAIL = "<div style=\"display: block; height: 70px; width: 100%;\"></div>"\
20
+ "</body>"\
21
+ "</html>"
22
+
23
+ def initialize(args = {})
24
+ args ||= {}
25
+ args[:file_name] ||= args['file_name']
26
+ self.file_name = args[:file_name]
27
+ end
28
+
29
+ def save
30
+ file_name = self.file_name
31
+ if file_name == ""
32
+ file_name = "load_result_"+Time.now.to_i.to_s+".html"
33
+ elsif !file_name.end_with?(".html")
34
+ file_name = file_name+".html"
35
+ end
36
+ File.open(file_name, 'w') { |file| file.write(self.body) }
37
+ file_name
38
+ end
39
+
40
+ def build_body(test)
41
+ sum_body = build_sum_test(test)
42
+
43
+ self.body = DEFAULT_PAGE_HEAD + sum_body + DEFAULT_PAGE_TAIL
44
+ end
45
+
46
+ def build_group_body(group_test)
47
+ sum_group_body = group_test.tests.collect{|test|
48
+ build_sum_test(test)
49
+ }.join('<hr style="margin-top: 70px; margin-bottom: 70px;">')
50
+
51
+ sum_group_table = build_sum_group_table(group_test)
52
+
53
+ self.body = DEFAULT_PAGE_HEAD + sum_group_table + sum_group_body + DEFAULT_PAGE_TAIL
54
+ end
55
+
56
+ private
57
+
58
+ def build_sum_group_table(group_test)
59
+ "<div style=\"width: 100%; text-align: center; margin-top: 20px; margin-bottom: 20px;\">
60
+ <span style=\"align: center; font-weight: bold; font-size: 20px;\">Comparison summary</span>
61
+ </div>
62
+
63
+ <div style=\"width: 100%; display: flex; margin-top: 30px;\">
64
+ <div style=\"width: 20%;\">
65
+ </div>
66
+ <div style=\"width: 100%;\">
67
+ <table style=\"width:100%; border: 1px solid black; border-collapse: collapse; text-align: center;\">
68
+ <tr style=\"border: 1px solid black; border-collapse: collapse;\">
69
+ <th width=\"10%\" style=\"border: 1px solid black; border-collapse: collapse;\">client</th>
70
+ <th width=\"10%\" style=\"border: 1px solid black; border-collapse: collapse;\">time (sec)</th>
71
+ <th width=\"20%\" style=\"border: 1px solid black; border-collapse: collapse;\">average_time (ms)</th>
72
+ <th width=\"15%\" style=\"border: 1px solid black; border-collapse: collapse;\">min_time (ms)</th>
73
+ <th width=\"15%\" style=\"border: 1px solid black; border-collapse: collapse;\">max_time (ms)</th>
74
+ <th width=\"15%\" style=\"border: 1px solid black; border-collapse: collapse;\">success</th>
75
+ <th width=\"15%\" style=\"border: 1px solid black; border-collapse: collapse;\">error</th>
76
+ </tr>
77
+ #{
78
+ group_data = group_test.tests.collect{|test|
79
+ [
80
+ test.client,
81
+ test.time,
82
+ test.summary_avg_time.round(4),
83
+ test.summary_min_time.round(4),
84
+ test.summary_max_time.round(4),
85
+ test.summary_success,
86
+ test.summary_error
87
+ ]
88
+ }
89
+ min_avg = group_data.collect{|test_data| test_data[2] }.sort.first
90
+ max_avg = group_data.collect{|test_data| test_data[2] }.sort.last
91
+ min_min = group_data.collect{|test_data| test_data[3] }.sort.first
92
+ max_min = group_data.collect{|test_data| test_data[3] }.sort.last
93
+ min_max = group_data.collect{|test_data| test_data[4] }.sort.first
94
+ max_max = group_data.collect{|test_data| test_data[4] }.sort.last
95
+ group_data.collect{|test_data|
96
+ test_data[5] = test_data[0] if test_data[5] > test_data[0]
97
+ "<tr style=\"border: 1px solid black; border-collapse: collapse;\">
98
+ <td style=\"border: 1px solid black; border-collapse: collapse;\">#{test_data[0]}</td>
99
+ <td style=\"border: 1px solid black; border-collapse: collapse;\">#{test_data[1]}</td>
100
+ <td style=\"border: 1px solid black; border-collapse: collapse; #{
101
+ if test_data[2] == min_avg
102
+ "color: green; font-weight:bold;"
103
+ elsif test_data[2] == max_avg
104
+ "color: red; font-weight:bold;"
105
+ end
106
+ }\">#{test_data[2]}</td>
107
+ <td style=\"border: 1px solid black; border-collapse: collapse; #{
108
+ if test_data[3] == min_min
109
+ "color: green; font-weight:bold;"
110
+ elsif test_data[3] == max_min
111
+ "color: red; font-weight:bold;"
112
+ end
113
+ }\">#{test_data[3]}</td>
114
+ <td style=\"border: 1px solid black; border-collapse: collapse; #{
115
+ if test_data[4] == min_max
116
+ "color: green; font-weight:bold;"
117
+ elsif test_data[4] == max_max
118
+ "color: red; font-weight:bold;"
119
+ end
120
+ }\">#{test_data[4]}</td>
121
+ <td style=\"border: 1px solid black; border-collapse: collapse; #{
122
+ "color: green; font-weight:bold;" if test_data[0] == test_data[5]
123
+ }\">#{test_data[5]}</td>
124
+ <td style=\"border: 1px solid black; border-collapse: collapse; #{
125
+ test_data[6] > 0 ? "color: red; font-weight:bold;" : "color: green; font-weight:bold;"
126
+ }\">#{test_data[6]}</td>
127
+ </tr>"
128
+ }.join
129
+ }
130
+ </table>
131
+ </div>
132
+ <div style=\"width: 20%;\">
133
+ </div>
134
+ </div>
135
+ <hr style=\"margin-top: 70px; margin-bottom: 70px;\">"
136
+ end
137
+
138
+ def build_sum_test(test)
139
+ chart_body = build_chart(test)
140
+ summary_body = build_summary(test)
141
+ error_body = build_error_table(test)
142
+
143
+ chart_body + summary_body + error_body
144
+ end
145
+
146
+ def build_summary(test)
147
+ min_time = test.summary_min_time
148
+ max_time = test.summary_max_time
149
+ avg_time = test.summary_avg_time
150
+ success = test.summary_success
151
+ error = test.summary_error
152
+
153
+ "<div style=\"width: 100%; text-align: center; margin-top: 20px; margin-bottom: 20px;\">
154
+ <span style=\"align: center; font-weight: bold;\">Summary</span>
155
+ </div>
156
+ <div style=\"width: 100%; display: flex;\">
157
+ <div style=\"width: 100%;\">
158
+ </div>
159
+ <div id=\"summary_time\" style=\"width: 100%; align: center;\">
160
+ <table style=\"width: 100%;\">
161
+ <tbody>
162
+ <tr>
163
+ <th style=\"font-weight: bold;\">Average</th>
164
+ <td>#{avg_time.round(4)} ms</td>
165
+ </tr>
166
+ <tr>
167
+ <th style=\"font-weight: bold;\">Min/Max</th>
168
+ <td>#{min_time.round(4)} / #{max_time.round(4)} ms</td>
169
+ </tr>
170
+ </tbody>
171
+ </table>
172
+ </div>
173
+ <div id=\"summary_data\" style=\"width: 100%; align: center;\">
174
+ <table style=\"width: 100%;\">
175
+ <tbody>
176
+ <tr>
177
+ <th style=\"font-weight: bold;\">Success</th>
178
+ <td>#{success}</td>
179
+ </tr>
180
+ <tr>
181
+ <th style=\"font-weight: bold;\">Error</th>
182
+ <td>#{error}</td>
183
+ </tr>
184
+ </tbody>
185
+ </table>
186
+ </div>
187
+ <div style=\"width: 100%;\">
188
+ </div>
189
+ </div>"
190
+ end
191
+
192
+ def build_chart(test)
193
+ clients_data = {}
194
+ pass_data = {}
195
+ error_data = {}
196
+ average_time_data = {}
197
+ test.results.each{|key, values|
198
+ clients_data[Time.at(key).utc.strftime("%H:%M:%S")] = values.count
199
+ pass_data[Time.at(key).utc.strftime("%H:%M:%S")] = values.select{|val| val.pass }.count
200
+ error_data[Time.at(key).utc.strftime("%H:%M:%S")] = values.select{|val| !val.pass }.count
201
+ average_time_data[Time.at(key).utc.strftime("%H:%M:%S")] = values.collect(&:time).sum.fdiv(values.size)*1000
202
+ }
203
+
204
+ line_chart(
205
+ [
206
+ {
207
+ name: 'Clients/sec',
208
+ data: clients_data
209
+ },
210
+ {
211
+ name: 'Passed',
212
+ data: pass_data
213
+ },
214
+ {
215
+ name: 'Error',
216
+ data: error_data
217
+ },
218
+ {
219
+ name: 'Average',
220
+ data: average_time_data
221
+ }
222
+ ],
223
+ {
224
+ adapter: "google",
225
+ "colors": ["#FFD919", "#23FF39", "#FF2A27", "#433DFF"],
226
+ "library": {
227
+ title: "Load test's result (Client: #{test.client}, Time: #{test.time} sec.)",
228
+ legend: {position: 'top'},
229
+ vAxes: {
230
+ 0 => {logScale: false, title: 'User (concurrent)'},
231
+ 1 => {logScale: false, title: 'Time (ms)', textStyle: {color: 'blue'}}
232
+ },
233
+ series: {
234
+ 0 => {targetAxisIndex: 0 },
235
+ 1 => {targetAxisIndex: 0 },
236
+ 2 => {targetAxisIndex: 0 },
237
+ 3 => {targetAxisIndex: 1 },
238
+ }
239
+ }
240
+ }
241
+ )
242
+ end
243
+
244
+ def build_error_table(test)
245
+ errors = test.results.collect{|key,values| values.select{|node| node.pass == false}}.flatten
246
+ errors = errors.group_by{|error| "#{error.error.class.to_s}: #{error.error.message}" }
247
+
248
+ "<div style=\"width: 100%; display: flex; margin-top: 30px;\">
249
+ <div style=\"width: 20%;\">
250
+ </div>
251
+ <div style=\"width: 100%;\">
252
+ <table style=\"width:100%; border: 1px solid black; border-collapse: collapse; text-align: center;\">
253
+ <tr style=\"border: 1px solid black; border-collapse: collapse;\">
254
+ <th width=\"80%\">Error</th>
255
+ <th width=\"20%\">Count</th>
256
+ </tr>
257
+ #{errors.collect{|_key, _values|
258
+ "<tr style=\"border: 1px solid black; border-collapse: collapse;\">
259
+ <td>#{_key}</td>
260
+ <td>#{_values.count}</td>
261
+ </tr>"
262
+ }.join}
263
+ </table>
264
+ </div>
265
+ <div style=\"width: 20%;\">
266
+ </div>
267
+ </div>"
268
+ end
269
+
270
+ end
271
+ end
@@ -0,0 +1,5 @@
1
+ module GasLoadTester
2
+ class Error < StandardError
3
+ # Nothing here
4
+ end
5
+ end
@@ -0,0 +1,36 @@
1
+ module GasLoadTester
2
+ class GroupTest
3
+ attr_accessor :tests
4
+ def initialize(args)
5
+ raise Error.new('An argument should be an Array') unless args.instance_of?(Array)
6
+ self.tests = args.collect{|test_object|
7
+ if test_object.instance_of?(Test)
8
+ test_object
9
+ else
10
+ Test.new test_object
11
+ end
12
+ }
13
+ end
14
+
15
+ def run(args = {}, &block)
16
+ args[:output] ||= args['output']
17
+ args[:file_name] ||= args['file_name']
18
+ not_run_tests = self.tests.select{|test| !test.is_run? }
19
+ not_run_tests.each_with_index do |test, index|
20
+ print "[#{index+1}/#{not_run_tests.count}] "
21
+ test.run(nil, &block) unless test.is_run?
22
+ end
23
+ if args[:output]
24
+ export_file({file_name: args[:file_name]})
25
+ end
26
+ end
27
+
28
+ def export_file(args = {})
29
+ file = args[:file_name] || ''
30
+ chart_builder = GasLoadTester::ChartBuilder.new(file_name: file)
31
+ chart_builder.build_group_body(self)
32
+ chart_builder.save
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,10 @@
1
+ module GasLoadTester
2
+ class Result
3
+ attr_accessor :pass, :time, :error
4
+ def initialize(args)
5
+ self.pass = args[:pass]
6
+ self.time = args[:time]
7
+ self.error = args[:error]
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,120 @@
1
+ require 'ruby-progressbar'
2
+ require 'thwait'
3
+
4
+ module GasLoadTester
5
+ class Test
6
+ attr_accessor :client, :time, :results
7
+
8
+ DEFAULT = {
9
+ client: 1000,
10
+ time: 300
11
+ }
12
+
13
+ def initialize(args = {})
14
+ args ||= {}
15
+ args[:client] ||= args['client']
16
+ args[:time] ||= args['time']
17
+ args.reject!{|key, value| value.nil? }
18
+ args = DEFAULT.merge(args)
19
+
20
+ self.client = args[:client]
21
+ self.time = args[:time]
22
+ self.results = {}
23
+ @run = false
24
+ end
25
+
26
+ def run(args = {}, &block)
27
+ args ||= {}
28
+ args[:output] ||= args['output']
29
+ args[:file_name] ||= args['file_name']
30
+ puts "Running test (client: #{self.client}, time: #{self.time})"
31
+ @progressbar = ProgressBar.create(
32
+ :title => "Load test",
33
+ :starting_at => 0,
34
+ :total => self.time+10,
35
+ :format => "%a %b\u{15E7}%i %p%% %t",
36
+ :progress_mark => ' ',
37
+ :remainder_mark => "\u{FF65}"
38
+ )
39
+ load_test(block)
40
+ if args[:output]
41
+ export_file({file_name: args[:file_name]})
42
+ end
43
+ ensure
44
+ @run = true
45
+ end
46
+
47
+ def is_run?
48
+ @run
49
+ end
50
+
51
+ def request_per_second
52
+ (self.client/self.time.to_f).ceil
53
+ end
54
+
55
+ def export_file(args = {})
56
+ args ||= {}
57
+ file = args[:file_name] || ''
58
+ chart_builder = GasLoadTester::ChartBuilder.new(file_name: file)
59
+ chart_builder.build_body(self)
60
+ chart_builder.save
61
+ end
62
+
63
+ def summary_min_time
64
+ all_result_time.sort.first*1000
65
+ end
66
+
67
+ def summary_max_time
68
+ all_result_time.sort.last*1000
69
+ end
70
+
71
+ def summary_avg_time
72
+ all_result_time.sum.fdiv(all_result_time.size)*1000
73
+ end
74
+
75
+ def summary_success
76
+ self.results.collect{|key, values| values.select{|val| val.pass }.count }.flatten.sum
77
+ end
78
+
79
+ def summary_error
80
+ self.results.collect{|key, values| values.select{|val| !val.pass }.count }.flatten.sum
81
+ end
82
+
83
+ private
84
+
85
+ def all_result_time
86
+ self.results.collect{|key, values| values.collect(&:time) }.flatten
87
+ end
88
+
89
+ def load_test(block)
90
+ threads = []
91
+ rps = request_per_second
92
+ self.time.times do |index|
93
+ self.results[index] = []
94
+ start_index_time = Time.now
95
+ rps.times do
96
+ threads << Thread.new do
97
+ begin
98
+ start_time = Time.now
99
+ block.call
100
+ self.results[index] << build_result({pass: true, time: Time.now-start_time})
101
+ rescue => error
102
+ self.results[index] << build_result({pass: false, error: error, time: Time.now-start_time})
103
+ end
104
+ end
105
+ end
106
+ cal_sleep = 1-(Time.now-start_index_time)
107
+ cal_sleep = 0 if cal_sleep < 0
108
+ sleep(cal_sleep)
109
+ @progressbar.increment
110
+ end
111
+ ThreadsWait.all_waits(*threads)
112
+ @progressbar.progress += 10
113
+ end
114
+
115
+ def build_result(args)
116
+ Result.new(args)
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,3 @@
1
+ module GasLoadTester
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,10 @@
1
+ require "gas_load_tester/version"
2
+
3
+ require_relative 'gas_load_tester/test'
4
+ require_relative 'gas_load_tester/group_test'
5
+ require_relative 'gas_load_tester/result'
6
+ require_relative 'gas_load_tester/chart_builder'
7
+
8
+ module GasLoadTester
9
+ # Your code goes here
10
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gas_load_tester
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Tanapat Sainak
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-01-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ruby-progressbar
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.8.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.8.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: chartkick
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.2.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.2.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: rest-client
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.13'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.13'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ description: Simple Ruby load test library.
98
+ email:
99
+ - fallen_things@hotmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".rspec"
106
+ - ".travis.yml"
107
+ - Gemfile
108
+ - LICENSE.txt
109
+ - README.md
110
+ - Rakefile
111
+ - bin/console
112
+ - bin/setup
113
+ - gas_load_tester.gemspec
114
+ - lib/gas_load_tester.rb
115
+ - lib/gas_load_tester/chart_builder.rb
116
+ - lib/gas_load_tester/error.rb
117
+ - lib/gas_load_tester/group_test.rb
118
+ - lib/gas_load_tester/result.rb
119
+ - lib/gas_load_tester/test.rb
120
+ - lib/gas_load_tester/version.rb
121
+ homepage: https://github.com/gastzars/gas_load_tester
122
+ licenses:
123
+ - MIT
124
+ metadata: {}
125
+ post_install_message:
126
+ rdoc_options: []
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 2.6.8
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: Ruby load test library.
145
+ test_files: []