cucumber-performance 0.0.1
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: 8eddf6da7cf0384c9d1f1a75915fbc6da78b5e40
|
4
|
+
data.tar.gz: c1d9f5293a4cfe56d585ec1f7ffc5adec4635a33
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1fe508fa273977c721e1feef7c06aa2e11192244a23780455d8cec2ab6038caaa6dc483ada85a2e1c6219b6dc0bbe5f8461b809c66df45c8ed4c136a1f4f46cd
|
7
|
+
data.tar.gz: 53c7adade63b1f52a63f97b068acb02b5229013e32fc5614e9b3703b425ea37193d57703cc452947d3c3e265955c80a4387a5a7bb525ea43b58e99ecdbfa9d75
|
@@ -0,0 +1,226 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
|
3
|
+
Given(/^I want to run a performance$/) do
|
4
|
+
|
5
|
+
# This variable prevents any functions being called to produce meta data
|
6
|
+
$PERFROMANCETEST = true
|
7
|
+
|
8
|
+
# Result hash for trasctions
|
9
|
+
$results_transactions = Hash.new()
|
10
|
+
# Result hash for scenarios
|
11
|
+
$results_scenarios = Hash.new()
|
12
|
+
|
13
|
+
# Result hash for transctions in a form dumpable for the transactions graph
|
14
|
+
$results_transactions_graph = Hash.new()
|
15
|
+
# Result hash for scenarios in a form dumpable for the transactions graph
|
16
|
+
$results_scenarios_graph = Hash.new()
|
17
|
+
|
18
|
+
# How many v_users are currently running
|
19
|
+
$running_v_users = 0
|
20
|
+
|
21
|
+
# V Users change over time, this will keep track every second
|
22
|
+
$results_vusers = Hash.new()
|
23
|
+
|
24
|
+
# How long the before one v user finishes and they restart
|
25
|
+
$scriptdelaytime = 0
|
26
|
+
|
27
|
+
# Start time of the test
|
28
|
+
$starttime = Time.new.to_i
|
29
|
+
|
30
|
+
# How many failures
|
31
|
+
$total_failures = 0
|
32
|
+
|
33
|
+
# an Array of error messages
|
34
|
+
$error_log = []
|
35
|
+
|
36
|
+
# Start the graph x axes
|
37
|
+
$max_x = 3
|
38
|
+
|
39
|
+
# Start a controller, this is a GUI to allow you to monitor the test.
|
40
|
+
# This uses sinatra and is accessable by: http://localhost:4567
|
41
|
+
controller_thread = Thread.new{controller}
|
42
|
+
|
43
|
+
# Runs Cucumber to get a list of tests. This will be reworked in the future
|
44
|
+
args = []
|
45
|
+
args << '--dry-run'
|
46
|
+
args << '--format'
|
47
|
+
args << 'json'
|
48
|
+
|
49
|
+
@in = StringIO.new
|
50
|
+
@out = StringIO.new
|
51
|
+
@err = StringIO.new
|
52
|
+
|
53
|
+
begin
|
54
|
+
cuke = Cucumber::Cli::Main.new(args, @in, @out, @err).execute!
|
55
|
+
rescue Exception=>e
|
56
|
+
# Do nothing!
|
57
|
+
end
|
58
|
+
|
59
|
+
$features_hash = {}
|
60
|
+
|
61
|
+
$scenario_steps = {}
|
62
|
+
|
63
|
+
JSON.parse(@out.string).each do |features|
|
64
|
+
features['elements'].each do |scenarios|
|
65
|
+
$features_hash[scenarios['name'].to_s] = features['uri'].to_s + ':' + scenarios['line'].to_s
|
66
|
+
$scenario_steps[features['uri'].to_s + ':' + scenarios['line'].to_s] = []
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
Given(/^I have the following scenarios$/) do |table|
|
73
|
+
|
74
|
+
# This will use the cucumber call above to work out if the scenario you've enter
|
75
|
+
# is valid and can be run.
|
76
|
+
$running_scenarios_hash = {}
|
77
|
+
|
78
|
+
$running_scenarios_hash_name = {}
|
79
|
+
|
80
|
+
$amount_of_users = 0
|
81
|
+
|
82
|
+
$vuser_scenarios = []
|
83
|
+
|
84
|
+
table.raw.each do |value|
|
85
|
+
if (!$features_hash[value[0]].nil?)
|
86
|
+
$amount_of_users = $amount_of_users + value[1].to_i
|
87
|
+
$running_scenarios_hash[$features_hash[value[0]]] = value[1].to_i
|
88
|
+
$running_scenarios_hash_name[$features_hash[value[0]]] = value[0]
|
89
|
+
|
90
|
+
for i in 0..value[1].to_i - 1
|
91
|
+
$vuser_scenarios << $features_hash[value[0]]
|
92
|
+
end
|
93
|
+
|
94
|
+
# begin
|
95
|
+
load File.expand_path('performanceTests/' + value[0].gsub('(','').gsub(')', '').gsub(/ /, '_').capitalize.downcase + '.rb')
|
96
|
+
#require_relative '../../performanceTests/' + value[0].gsub('(','').gsub(')', '').gsub(/ /, '_').capitalize.downcase + '.rb'
|
97
|
+
#rescue Exception=>e
|
98
|
+
# raise "Unable to load: " + value[0].gsub('(','').gsub(')', '').gsub(/ /, '_').capitalize.downcase + '.rb'
|
99
|
+
#end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
$vuser_scenarios.shuffle
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
Given(/^I run for (\d+) minute(s|)$/) do |duration, word|
|
109
|
+
# Define the duration of the test
|
110
|
+
$duration = duration.to_i * 60
|
111
|
+
end
|
112
|
+
|
113
|
+
Given(/^I ramp up (\d+) user every (\d+) seconds$/) do |rampup_users, rampup_time|
|
114
|
+
# The space between each user starts up.
|
115
|
+
$ramp_up_time = rampup_time.to_i
|
116
|
+
# How many users to start up per every interval defined above.
|
117
|
+
$ramp_up_users = rampup_users
|
118
|
+
end
|
119
|
+
|
120
|
+
When(/^I run the performance test$/) do
|
121
|
+
|
122
|
+
# The duration needs adjusting to include the ramp up time
|
123
|
+
# This will include the amount of users * interval
|
124
|
+
$duration = $duration + ($amount_of_users * $ramp_up_time)
|
125
|
+
|
126
|
+
# creates an array to manage the threads
|
127
|
+
threads = Array.new()
|
128
|
+
|
129
|
+
# We need to get a unique list of the performance test names
|
130
|
+
$list_of_tests = Array.new()
|
131
|
+
|
132
|
+
# This block of code below loops though each of the v users to get a unique
|
133
|
+
# list of test file names
|
134
|
+
$vuser_scenarios.each do |value|
|
135
|
+
found = false
|
136
|
+
for i in 0..($list_of_tests.count - 1)
|
137
|
+
if ($list_of_tests[i] == value) then
|
138
|
+
found = true
|
139
|
+
end
|
140
|
+
end
|
141
|
+
if (found == false) then
|
142
|
+
$list_of_tests << value
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# We need to know which test we're v user we're up to.
|
147
|
+
$vuser_inc = 0
|
148
|
+
|
149
|
+
# We now need to start each of the v users as seperate threads
|
150
|
+
# This means each vuser can run indepedently
|
151
|
+
for i in 0..($amount_of_users - 1)
|
152
|
+
# Calls the loadtest() function
|
153
|
+
threads.push(Thread.new{loadtest()})
|
154
|
+
end
|
155
|
+
|
156
|
+
# Whilst the v users are running, we need to keep track of what the v users are doing
|
157
|
+
# This block of code below will keep a count of second how many v users are running
|
158
|
+
cur_time = 0
|
159
|
+
|
160
|
+
running = true
|
161
|
+
|
162
|
+
# There is three ways of knowing if the performance testing is still running
|
163
|
+
# if the variable running is true (this gets set to valse when $running_v_users goes above 0, meaning the test has started)
|
164
|
+
# The current time is less than the start time plus the duration
|
165
|
+
# #running_v_users is above 0
|
166
|
+
|
167
|
+
while (((Time.new.to_i) < ($starttime + $duration)) || ($running_v_users > 0) || (running == true)) do
|
168
|
+
|
169
|
+
# Increase current time by 1 (1 second)
|
170
|
+
cur_time = cur_time + 1
|
171
|
+
|
172
|
+
# $graph_time is the yavis max, as v users exit, this can go above the
|
173
|
+
# duration, so this expands the yaxis
|
174
|
+
$graph_time = $duration
|
175
|
+
if (cur_time > $duration) then
|
176
|
+
$graph_time = cur_time
|
177
|
+
end
|
178
|
+
|
179
|
+
# Build the $results_vusers with the current amount of running v users
|
180
|
+
for i in 0..((Time.new.to_i - $starttime + 1))
|
181
|
+
if ($results_vusers[i + 1].nil? == true) then
|
182
|
+
$results_vusers[i + 1] = $running_v_users
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# If $running_v_users is above 0, set the value to true
|
187
|
+
if ($running_v_users == 0) then
|
188
|
+
running = false
|
189
|
+
else
|
190
|
+
running = true
|
191
|
+
end
|
192
|
+
|
193
|
+
# sleep for a second
|
194
|
+
sleep(1)
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
# Joining threads means the system will wait for them to finish. This means the v users stop
|
199
|
+
for i in 0..($amount_of_users - 1)
|
200
|
+
threads[i].join
|
201
|
+
end
|
202
|
+
|
203
|
+
# Once the performance test has finished the sinatra app stops,
|
204
|
+
# this gets around that by visiting the page and producing a pdf output
|
205
|
+
visit('http://localhost:4567')
|
206
|
+
save_screenshot("performance-#{Time.new.to_i}.pdf")
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
Then(/^I expect less than (\d+) failures$/) do |failures|
|
211
|
+
# Checks if the total failures is below the threadhold.
|
212
|
+
assert_operator $total_failures, :<, failures.to_i, 'The failures weren\'t below the threshold'
|
213
|
+
end
|
214
|
+
|
215
|
+
Then(/^the scenarios response times were below:$/) do |table|
|
216
|
+
# Loop through each of the scenarios to see if they were below the threshold
|
217
|
+
table.raw.each do |value|
|
218
|
+
if (value[0] != 'SCENARIO')
|
219
|
+
# We need to get the average of the scenarios and then devide that by 1000 because they are in miliseconds
|
220
|
+
response_time = ($results_scenarios[$features_hash[value[0]]].inject{ |sum, el| sum + el }.to_f / $results_scenarios[$features_hash[value[0]]].size) / 1000
|
221
|
+
# Assert to see if the response time is below the threshold
|
222
|
+
assert_operator response_time, :<, value[1].to_i, 'The average response time wasn\'t below the threshold (' + value[0] + ')'
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
@@ -0,0 +1,348 @@
|
|
1
|
+
#####
|
2
|
+
## Function: loadtest
|
3
|
+
## Inputs: None
|
4
|
+
## Outputs: None
|
5
|
+
## Description: This function should be called when a v user thread is created,
|
6
|
+
## this will open the scripts in steps_definitions\performance
|
7
|
+
## and run the v_action() in there.
|
8
|
+
#####
|
9
|
+
def loadtest()
|
10
|
+
|
11
|
+
# Redirect $stdout (Console output) to nil
|
12
|
+
|
13
|
+
# Workout the delay time of the script
|
14
|
+
$scriptdelaytime = $scriptdelaytime + $ramp_up_time
|
15
|
+
|
16
|
+
# Sleep for that delay time, so we can start ramping up users incrementally
|
17
|
+
sleep $scriptdelaytime
|
18
|
+
|
19
|
+
# Get which cucumber scenario by using the $vuser_inc variable.
|
20
|
+
cucumber_scenario = $vuser_scenarios[$vuser_inc]
|
21
|
+
# Increase this variable by 1 so the other scenarios can use it
|
22
|
+
$vuser_inc = $vuser_inc + 1
|
23
|
+
|
24
|
+
# convervate the cucumber scenario name, into the class name
|
25
|
+
scenario_name = $running_scenarios_hash_name[cucumber_scenario].gsub('(','').gsub(')', '').gsub(/ /, '_').capitalize
|
26
|
+
|
27
|
+
# create an instance of the class from the (step_defitions/performance) file
|
28
|
+
script = Module.const_get(scenario_name).new
|
29
|
+
|
30
|
+
# Increase the variable which keeps track of running virtual users
|
31
|
+
$running_v_users = $running_v_users + 1
|
32
|
+
|
33
|
+
iteration = 0
|
34
|
+
|
35
|
+
# Loop through for the duration of the test, this will run the test each time it loops
|
36
|
+
while ((Time.new.to_i) < ($starttime + $duration)) do
|
37
|
+
|
38
|
+
iteration += 1
|
39
|
+
|
40
|
+
# Works out the start time of the current test (iteration)
|
41
|
+
scriptstart_time = Time.now
|
42
|
+
|
43
|
+
# We'll run the test in a try/except block to ensure it doesn't kill the thread
|
44
|
+
begin
|
45
|
+
# Call the threads action step
|
46
|
+
script.v_action()
|
47
|
+
|
48
|
+
rescue Exception=>e
|
49
|
+
# If it fails, keep a log of why, then carry on
|
50
|
+
|
51
|
+
error = {}
|
52
|
+
error['error_message'] = e
|
53
|
+
error['error_iteration'] = iteration
|
54
|
+
error['error_script'] = cucumber_scenario
|
55
|
+
|
56
|
+
|
57
|
+
$error_log << error
|
58
|
+
|
59
|
+
$total_failures = $total_failures + 1
|
60
|
+
$stdout.puts e
|
61
|
+
end
|
62
|
+
|
63
|
+
# As the test has finished, work out the duration
|
64
|
+
script_duration = (Time.now - scriptstart_time) * 1000
|
65
|
+
|
66
|
+
# If the duration is above the x axis current value, let's increase it
|
67
|
+
if ((script_duration / 1000) > $max_x) then
|
68
|
+
$max_x = (script_duration / 1000).ceil + 1
|
69
|
+
end
|
70
|
+
|
71
|
+
# If the current cucumber scenario have no results, lets define their arrays
|
72
|
+
if ($results_scenarios[cucumber_scenario].nil?) then
|
73
|
+
$results_scenarios[cucumber_scenario] = []
|
74
|
+
$results_scenarios_graph[cucumber_scenario] = {}
|
75
|
+
end
|
76
|
+
|
77
|
+
# Add the duration of the test to an array so we can work our max/min/avg etc...
|
78
|
+
$results_scenarios[cucumber_scenario] << script_duration
|
79
|
+
|
80
|
+
# For each second we need to build up an average, so need to build up another array
|
81
|
+
# based on the current time
|
82
|
+
current_time_id = $duration - (($starttime + $duration) - Time.new.to_i) + 1
|
83
|
+
|
84
|
+
# If the array doesn't exist for the current time, then lets define it
|
85
|
+
if($results_scenarios_graph[cucumber_scenario][current_time_id].nil? == true) then
|
86
|
+
$results_scenarios_graph[cucumber_scenario][current_time_id] = Array.new()
|
87
|
+
end
|
88
|
+
|
89
|
+
# Add the value to the array
|
90
|
+
$results_scenarios_graph[cucumber_scenario][current_time_id].push(script_duration)
|
91
|
+
|
92
|
+
# Sleep a second between each scenario. This will need to be parametised soon
|
93
|
+
sleep(1)
|
94
|
+
|
95
|
+
end
|
96
|
+
# Once the test has finished, lets decrease the $running_v_users value
|
97
|
+
$running_v_users = $running_v_users - 1
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
#####
|
104
|
+
## Function: start_traction
|
105
|
+
## Inputs: step_name (String)
|
106
|
+
## Outputs: current time (dateTime)
|
107
|
+
## Description: This is to get the time at a certain points to work out the
|
108
|
+
## response time of certain parts of the load test
|
109
|
+
#####
|
110
|
+
def start_traction(step_name)
|
111
|
+
|
112
|
+
scriptstart_time = Time.now
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
#####
|
117
|
+
## Function: start_traction
|
118
|
+
## Inputs: step_name (String)
|
119
|
+
## Outputs: current time (dateTime)
|
120
|
+
## Description: This is to get the time at a certain points to work out the
|
121
|
+
## response time of certain parts of the load test
|
122
|
+
#####
|
123
|
+
def end_traction(step_name, start_time)
|
124
|
+
|
125
|
+
# This uses the value from start_traction() and finds how long the test took.
|
126
|
+
transaction_duration = (Time.now - start_time) * 1000
|
127
|
+
|
128
|
+
# If the current transaction have no results, lets define their arrays
|
129
|
+
if ($results_transactions[step_name].nil?) then
|
130
|
+
$results_transactions[step_name] = []
|
131
|
+
$results_transactions_graph[step_name] = {}
|
132
|
+
end
|
133
|
+
|
134
|
+
# Add the duration of the test to an array so we can work our max/min/avg etc...
|
135
|
+
$results_transactions[step_name] << transaction_duration
|
136
|
+
|
137
|
+
# For each second we need to build up an average, so need to build up another array
|
138
|
+
# based on the current time
|
139
|
+
current_time_id = $duration - (($starttime + $duration) - Time.new.to_i) + 1
|
140
|
+
|
141
|
+
# If the array doesn't exist for the current time, then lets define it
|
142
|
+
if($results_transactions_graph[step_name][current_time_id].nil? == true) then
|
143
|
+
$results_transactions_graph[step_name][current_time_id] = Array.new()
|
144
|
+
end
|
145
|
+
|
146
|
+
# Add the value to the array
|
147
|
+
$results_transactions_graph[step_name][current_time_id].push(transaction_duration)
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
#####
|
152
|
+
## Function: http_get
|
153
|
+
## Inputs: curl (Curl::Easy Instance) data (Hash of headers) url (String of the url)
|
154
|
+
## Outputs: current time (dateTime)
|
155
|
+
## Description: Performs a http get command for the user specified
|
156
|
+
#####
|
157
|
+
def http_get(curl, data, url)
|
158
|
+
|
159
|
+
#puts 'GET: ' + url
|
160
|
+
|
161
|
+
# Define the url we want to hit
|
162
|
+
curl.url=url
|
163
|
+
|
164
|
+
# Specify the headers we want to hit
|
165
|
+
curl.headers = data['header']
|
166
|
+
|
167
|
+
# perform the call
|
168
|
+
curl.http_get
|
169
|
+
|
170
|
+
# Set headers to nil so none get reused elsewhere
|
171
|
+
curl.headers = nil
|
172
|
+
|
173
|
+
# return the curl object
|
174
|
+
return curl
|
175
|
+
end
|
176
|
+
|
177
|
+
#####
|
178
|
+
## Function: http_post
|
179
|
+
## Inputs: curl (Curl::Easy Instance) data (Hash of headers and posts) url (String of the url)
|
180
|
+
## Outputs: current time (dateTime)
|
181
|
+
## Description: Performs a http get command for the user specified
|
182
|
+
#####
|
183
|
+
def http_post(curl, data, url)
|
184
|
+
|
185
|
+
# Define the post data
|
186
|
+
data2 = ''
|
187
|
+
|
188
|
+
# Loop through the data["post_data"] passed in to build up the post data string
|
189
|
+
data["post_data"].each do |key, value|
|
190
|
+
if (data2 != '') then
|
191
|
+
data2 = data2 + '&'
|
192
|
+
end
|
193
|
+
# If the value is null we don't just want it to look like: item=
|
194
|
+
if (value.nil?) then
|
195
|
+
data2 = data2 + CGI::escape(key.to_s) + '='
|
196
|
+
else
|
197
|
+
data2 = data2 + CGI::escape(key.to_s) + '=' + CGI::escape(value.to_s)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# Define the url we want to hit
|
202
|
+
curl.url = url
|
203
|
+
# Specify the headers we want to hit
|
204
|
+
curl.headers = data['header']
|
205
|
+
|
206
|
+
# perform the call
|
207
|
+
curl.post(data2)
|
208
|
+
|
209
|
+
curl.headers = nil
|
210
|
+
|
211
|
+
# Set headers to nil so none get reused elsewhere
|
212
|
+
curl.headers = nil
|
213
|
+
|
214
|
+
# return the curl object
|
215
|
+
return curl
|
216
|
+
|
217
|
+
end
|
218
|
+
|
219
|
+
#####
|
220
|
+
## Function: assert_http_status
|
221
|
+
## Inputs: curl (Curl::Easy Instance) status (expected http status code)
|
222
|
+
## Outputs: current time (dateTime)
|
223
|
+
## Description: Performs a http get command for the user specified
|
224
|
+
#####
|
225
|
+
def assert_http_status(curl, status)
|
226
|
+
|
227
|
+
# If the status doesn't match, then raise an exception
|
228
|
+
if (curl.response_code != status) then
|
229
|
+
raise curl.url + ': Expected response of ' + status.to_s + ' but was ' + curl.response_code.to_s
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
#####
|
235
|
+
## Function: controller
|
236
|
+
## Inputs: None
|
237
|
+
## Outputs: None
|
238
|
+
## Description: This is the controller thread for running the sinatra app, monitoring the run
|
239
|
+
#####
|
240
|
+
def controller()
|
241
|
+
|
242
|
+
# Create a Sinatra isntance
|
243
|
+
$sinatra_instance = Sinatra.new()
|
244
|
+
|
245
|
+
# Get a localhost/data url defined (used by ajax)
|
246
|
+
$sinatra_instance.get '/data' do
|
247
|
+
|
248
|
+
# we need to turn the data object into a json response at the end
|
249
|
+
data = {}
|
250
|
+
|
251
|
+
# This is the array of data for each scenario for the graph
|
252
|
+
data['graph_data'] = []
|
253
|
+
|
254
|
+
# The array for the erros
|
255
|
+
data['error_log'] = $error_log
|
256
|
+
|
257
|
+
# Define the graph data objects
|
258
|
+
for i in 0..10
|
259
|
+
data['graph_data'][i] = []
|
260
|
+
end
|
261
|
+
|
262
|
+
# Work out the xmax and ymax
|
263
|
+
data['graph_xmax'] = (($graph_time || 0) * 1.05).ceil.to_s
|
264
|
+
data['graph_ymax'] = (($amount_of_users || 0) * 1.2).ceil.to_s
|
265
|
+
|
266
|
+
# Sets the graph data for [0] (vusers) to 0, stops an error
|
267
|
+
data['graph_data'][0][0] = 0
|
268
|
+
|
269
|
+
# Loops through each second to get the graph data
|
270
|
+
for i in 0..((Time.new.to_i - $starttime ))
|
271
|
+
|
272
|
+
# The [0] is for v users
|
273
|
+
data['graph_data'][0][i] = $results_vusers[i + 1]
|
274
|
+
|
275
|
+
num = 0
|
276
|
+
# Anthing above [0] is for the running tests
|
277
|
+
$results_scenarios_graph.each do |key, results2|
|
278
|
+
num = num + 1
|
279
|
+
if (results2[i + 1].nil? == false) then
|
280
|
+
|
281
|
+
sum = 0
|
282
|
+
results2[i + 1].each { |a| sum+=a }
|
283
|
+
|
284
|
+
# Add the results to the json object
|
285
|
+
data['graph_data'][num][i] = ((sum / results2[i + 1].size.to_f) / 1000).round(2)
|
286
|
+
data['graph_y2max'] = ($max_x * 1.1)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
|
292
|
+
|
293
|
+
# Define the objects for the overview of the cucumber scenarios (table below graph)
|
294
|
+
data['graph_details_name'] = []
|
295
|
+
data['graph_details_min'] = []
|
296
|
+
data['graph_details_max'] = []
|
297
|
+
data['graph_details_avg'] = []
|
298
|
+
|
299
|
+
data['graph_details_name'][0] = 'Vusers'
|
300
|
+
|
301
|
+
# If the data exists then use it, otherwise set it to 0
|
302
|
+
if (!data['graph_data'].nil?) then
|
303
|
+
data['graph_details_min'][0] = data['graph_data'][0].min.round(2)
|
304
|
+
data['graph_details_max'][0] = data['graph_data'][0].max.round(2)
|
305
|
+
data['graph_details_avg'][0] = (data['graph_data'][0].inject{ |sum, el| sum + el }.to_f / data['graph_data'][0].size).round(2)
|
306
|
+
else
|
307
|
+
data['graph_details_min'][0] = 0
|
308
|
+
data['graph_details_max'][0] = 0
|
309
|
+
data['graph_details_avg'][0] = 0
|
310
|
+
end
|
311
|
+
|
312
|
+
# This is the same as above, but for tests, not the vusers
|
313
|
+
for i in 0..($list_of_tests.count - 1)
|
314
|
+
|
315
|
+
data['graph_details_name'][i + 1] = $list_of_tests[i]
|
316
|
+
|
317
|
+
if (!$results_scenarios[$list_of_tests[i]].nil?) then
|
318
|
+
|
319
|
+
data['graph_details_min'][i + 1] = ($results_scenarios[$list_of_tests[i]].min / 1000).round(2)
|
320
|
+
data['graph_details_max'][i + 1] = ($results_scenarios[$list_of_tests[i]].max / 1000).round(2)
|
321
|
+
data['graph_details_avg'][i + 1] = (($results_scenarios[$list_of_tests[i]].inject{ |sum, el| sum + el }.to_f / $results_scenarios[$list_of_tests[i]].size) / 1000).round(2)
|
322
|
+
|
323
|
+
else
|
324
|
+
|
325
|
+
data['graph_details_min'][i + 1] = 0
|
326
|
+
data['graph_details_max'][i + 1] = 0
|
327
|
+
data['graph_details_avg'][i + 1] = 0
|
328
|
+
|
329
|
+
end
|
330
|
+
|
331
|
+
end
|
332
|
+
|
333
|
+
|
334
|
+
# Print the output as a json string
|
335
|
+
return data.to_json
|
336
|
+
end
|
337
|
+
|
338
|
+
# Get a localhost url defined (main page)
|
339
|
+
$sinatra_instance.get '/' do
|
340
|
+
|
341
|
+
erb :'index.html'
|
342
|
+
|
343
|
+
end
|
344
|
+
|
345
|
+
# run sinatra on the default url/port
|
346
|
+
$sinatra_instance.run!
|
347
|
+
|
348
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
|
3
|
+
<html>
|
4
|
+
<head>
|
5
|
+
|
6
|
+
<title>Performance Test</title>
|
7
|
+
|
8
|
+
<!--[if lt IE 9]><script language="javascript" type="text/javascript" src="excanvas.js"></script><![endif]-->
|
9
|
+
<script language="javascript" type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
10
|
+
<script language="javascript" type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jqPlot/1.0.8/jquery.jqplot.min.js"></script>
|
11
|
+
<link rel="stylesheet" type="text/css" href="http://cdnjs.cloudflare.com/ajax/libs/jqPlot/1.0.8/jquery.jqplot.min.css" />
|
12
|
+
<link rel="stylesheet" type="text/css" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
|
13
|
+
</head>
|
14
|
+
<body>
|
15
|
+
<div id="chartdiv" style="height:400px;width:800px; "></div>
|
16
|
+
|
17
|
+
</body>
|
18
|
+
|
19
|
+
<script class="code" type="text/javascript">
|
20
|
+
<%= @logfile %>
|
21
|
+
|
22
|
+
|
23
|
+
seriesColorsMaster = [ "#4bb2c5", "#c5b47f", "#EAA228", "#579575", "#839557", "#958c12",
|
24
|
+
"#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc"]
|
25
|
+
|
26
|
+
graph_ymax = 0
|
27
|
+
graph_y2max = 0
|
28
|
+
graph_xmax = 0
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
</script>
|
38
|
+
|
39
|
+
<br>
|
40
|
+
<b>Information:</b>
|
41
|
+
<div class="bs-example">
|
42
|
+
<table class="table">
|
43
|
+
<thead>
|
44
|
+
<tr>
|
45
|
+
<th>Colour</th>
|
46
|
+
<th>Name</th>
|
47
|
+
<th>Min</th>
|
48
|
+
<th>Avg</th>
|
49
|
+
<th>Max</th>
|
50
|
+
</tr>
|
51
|
+
</thead>
|
52
|
+
<tbody class="tablebody">
|
53
|
+
<tr>
|
54
|
+
<td id="row1"></td>
|
55
|
+
<td>Vusers</td>
|
56
|
+
<td></td>
|
57
|
+
<td></td>
|
58
|
+
<td></td>
|
59
|
+
</tr>
|
60
|
+
</tbody>
|
61
|
+
</table>
|
62
|
+
</div>
|
63
|
+
|
64
|
+
<br>
|
65
|
+
<b>Errors:</b>
|
66
|
+
<div class="bs-example">
|
67
|
+
<table class="table">
|
68
|
+
<thead>
|
69
|
+
<tr>
|
70
|
+
<th>Script</th>
|
71
|
+
<th>Instance</th>
|
72
|
+
<th>Error</th>
|
73
|
+
</tr>
|
74
|
+
</thead>
|
75
|
+
<tbody class="errors">
|
76
|
+
<tr>
|
77
|
+
<td></td>
|
78
|
+
<td></td>
|
79
|
+
<td></td>
|
80
|
+
</tr>
|
81
|
+
</tbody>
|
82
|
+
</table>
|
83
|
+
</div>
|
84
|
+
|
85
|
+
<script class="code" type="text/javascript">
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
function renderGraph() {
|
91
|
+
if (typeof plot1 !== 'undefined') {
|
92
|
+
plot1.destroy();
|
93
|
+
}
|
94
|
+
plot1 = $.jqplot('chartdiv', [graph_data1, graph_data2, graph_data3, graph_data4, graph_data5, graph_data6, graph_data7, graph_data8, graph_data9, graph_data10],
|
95
|
+
{ title:'Performance Test',
|
96
|
+
seriesColors: seriesColorsMaster,
|
97
|
+
axes:{yaxis:{label: 'VUsers', min:0, max:graph_ymax},
|
98
|
+
y2axis: {label: 'Response', min:0, max:graph_y2max},
|
99
|
+
xaxis:{min:0, max:graph_xmax, numberTicks: 10}
|
100
|
+
},
|
101
|
+
series: [
|
102
|
+
{ yaxis: "yaxis" },
|
103
|
+
{ yaxis: "y2axis" }
|
104
|
+
]
|
105
|
+
|
106
|
+
|
107
|
+
});
|
108
|
+
|
109
|
+
}
|
110
|
+
|
111
|
+
|
112
|
+
function get_graph_data() {
|
113
|
+
|
114
|
+
|
115
|
+
$.getJSON( "/data", function( json ) {
|
116
|
+
|
117
|
+
graph_ymax = json.graph_ymax;
|
118
|
+
graph_y2max = json.graph_y2max;
|
119
|
+
graph_xmax = json.graph_xmax;
|
120
|
+
|
121
|
+
graph_data1 = [];
|
122
|
+
graph_data2 = [];
|
123
|
+
graph_data3 = [];
|
124
|
+
graph_data4 = [];
|
125
|
+
graph_data5 = [];
|
126
|
+
graph_data6 = [];
|
127
|
+
graph_data7 = [];
|
128
|
+
graph_data8 = [];
|
129
|
+
graph_data9 = [];
|
130
|
+
graph_data10 = [];
|
131
|
+
|
132
|
+
graph_data1 = json.graph_data[0];
|
133
|
+
graph_data2 = json.graph_data[1];
|
134
|
+
graph_data3 = json.graph_data[2];
|
135
|
+
graph_data4 = json.graph_data[3];
|
136
|
+
graph_data5 = json.graph_data[4];
|
137
|
+
graph_data6 = json.graph_data[5];
|
138
|
+
graph_data7 = json.graph_data[6];
|
139
|
+
graph_data8 = json.graph_data[7];
|
140
|
+
graph_data9 = json.graph_data[8];
|
141
|
+
graph_data10 = json.graph_data[9];
|
142
|
+
|
143
|
+
|
144
|
+
graph_details_name = [];
|
145
|
+
graph_details_min = [];
|
146
|
+
graph_details_max = [];
|
147
|
+
graph_details_avg = [];
|
148
|
+
|
149
|
+
graph_details_name = json.graph_details_name;
|
150
|
+
graph_details_min = json.graph_details_min;
|
151
|
+
graph_details_max = json.graph_details_max;
|
152
|
+
graph_details_avg = json.graph_details_avg;
|
153
|
+
|
154
|
+
renderGraph()
|
155
|
+
|
156
|
+
$( ".tablebody" ).html('')
|
157
|
+
|
158
|
+
for (var i = 0; i < graph_details_name.length; i++) {
|
159
|
+
//alert(graph_details[i]);
|
160
|
+
//Do something
|
161
|
+
|
162
|
+
$( ".tablebody" ).append( '<tr><td id="row' + (i + 1) + '"></td><td>' + graph_details_name[i] + '</td><td>' + graph_details_min[i] + '</td><td>' + graph_details_avg[i] + '</td><td>' + graph_details_max[i] + '</td></tr>');
|
163
|
+
}
|
164
|
+
|
165
|
+
$('#row1').css('background',seriesColorsMaster[0]);
|
166
|
+
$('#row2').css('background',seriesColorsMaster[1]);
|
167
|
+
$('#row3').css('background',seriesColorsMaster[2]);
|
168
|
+
$('#row4').css('background',seriesColorsMaster[3]);
|
169
|
+
$('#row5').css('background',seriesColorsMaster[4]);
|
170
|
+
$('#row6').css('background',seriesColorsMaster[5]);
|
171
|
+
$('#row7').css('background',seriesColorsMaster[6]);
|
172
|
+
$('#row8').css('background',seriesColorsMaster[7]);
|
173
|
+
$('#row9').css('background',seriesColorsMaster[8]);
|
174
|
+
$('#row10').css('background',seriesColorsMaster[9]);
|
175
|
+
|
176
|
+
|
177
|
+
for (var i2 = 0; i2 < json.error_log.length; i2++) {
|
178
|
+
//alert(graph_details[i]);
|
179
|
+
//Do something
|
180
|
+
|
181
|
+
$( ".errors" ).append( '<tr><td>' + json.error_log[i2].error_script + '</td><td>' + json.error_log[i2].error_iteration + '</td><td>' + json.error_log[i2].error_message + '</td></tr>');
|
182
|
+
}
|
183
|
+
|
184
|
+
|
185
|
+
|
186
|
+
});
|
187
|
+
|
188
|
+
}
|
189
|
+
|
190
|
+
get_graph_data();
|
191
|
+
|
192
|
+
window.setInterval(function(){
|
193
|
+
|
194
|
+
get_graph_data();
|
195
|
+
|
196
|
+
|
197
|
+
}, 2000);
|
198
|
+
|
199
|
+
|
200
|
+
|
201
|
+
|
202
|
+
</script>
|
203
|
+
|
204
|
+
</div>
|
205
|
+
</html>
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cucumber-performance
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Moore
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cucumber
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.3.15
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.3.15
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sinatra
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.4.5
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.4.5
|
41
|
+
description: This gem adds function libraries for performance testing and the steps
|
42
|
+
to support the run
|
43
|
+
email: mooreandrew@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- lib/cucumber-performance.rb
|
49
|
+
- lib/cucumber-performance/cucumber-steps.rb
|
50
|
+
- lib/cucumber-performance/functions.rb
|
51
|
+
- lib/cucumber-performance/views/index.html.erb
|
52
|
+
homepage: https://github.com/mooreandrew/cucumber-performance
|
53
|
+
licenses:
|
54
|
+
- MIT
|
55
|
+
metadata: {}
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirements: []
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 2.0.14
|
73
|
+
signing_key:
|
74
|
+
specification_version: 4
|
75
|
+
summary: Hola!
|
76
|
+
test_files: []
|