gas_load_tester 1.0.0

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.
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: []