cucumber-performance 0.0.1
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: 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: []
|