qTestScenarioRuby 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: cc6e9dfd1295fe83365f0b536090eb6d4e31a38b
4
+ data.tar.gz: 3e9153475ba0e4582ebb70d687f077d7365898b5
5
+ SHA512:
6
+ metadata.gz: a42ed9e488d80870624113340c604b425d7239030680249f106ccffe7d8e7478ac05bb9c7feff1447f4fca625c76d2a478d1f61ee723f6192478123c8d8ac0fa
7
+ data.tar.gz: d0f64e914993f1b78e335d143e464d04baf4ea6e8eca556e76af78eefa52036a13f5a8146123094cbf1064e1e2250557c3a48e6f0e84a12afaadfa0aa0e08b67
@@ -0,0 +1,33 @@
1
+ module QspecResult
2
+ PASSED = 'PASSED'
3
+ UNCOMPLETED = 'UNCOMPLETED'
4
+ FAILED = 'FAILED'
5
+ SKIP = 'SKIP'
6
+ end
7
+
8
+ class Constants
9
+
10
+ def self.getMappingFileName
11
+ '.qtestscenario'
12
+ end
13
+
14
+ def self.getCreateExecutionUri
15
+ '/qspec/api/execution'
16
+ end
17
+
18
+ def self.getFeatureFilesUri
19
+ '/qspec/api/feature-file'
20
+ end
21
+
22
+ def self.getSubmitFeatureTestLogUri
23
+ '/qspec/api/feature/%s/test-log'
24
+ end
25
+
26
+ def self.getUpdateExecutionUri
27
+ '/qspec/api/execution/%s'
28
+ end
29
+
30
+ def self.getConfigFile
31
+ 'config/config.yml'
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+
2
+ class Time
3
+ def to_ms
4
+ (self.to_f * 1000.0).to_i
5
+ end
6
+ end
7
+
8
+ class ExecutionLog
9
+ attr_accessor :executionId, :startDate, :endDate, :host
10
+
11
+ def initialize
12
+ @host = Socket.gethostname
13
+ @startDate = Time.now.to_ms
14
+ end
15
+
16
+ def self.from_json data
17
+ executionLog = ExecutionLog.new
18
+ executionLog.executionId = data['execution_id']
19
+ executionLog.startDate = data['start_date']
20
+ executionLog.endDate = data['end_date']
21
+ executionLog.host = data['host']
22
+ executionLog
23
+ end
24
+
25
+ def to_json(options={})
26
+ {'execution_id' => @executionId, 'start_date' => @startDate, 'end_date' => @endDate, 'host' => @host}.to_json
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ class FeatureLog
2
+ attr_accessor :featureId, :result, :startDate, :endDate, :executionId, :scenarioLogs, :versionId,
3
+ :totalScenariosNumber, :currentScenariosNumber, :resultSet
4
+
5
+ def initialize
6
+ @currentScenariosNumber = 0
7
+ @scenarioLogs = []
8
+ @resultSet = []
9
+ end
10
+
11
+ def to_json(options={})
12
+ {'feature_id' => @featureId, 'result' => @result, 'start_date' => @startDate, 'end_date' => @endDate, 'execution_id' => @executionId,
13
+ 'scenario_logs' => @scenarioLogs, 'versionId' => @versionId}.to_json
14
+ end
15
+
16
+ def addScenarioResult result
17
+ @resultSet.push result
18
+ @currentScenariosNumber += 1
19
+ end
20
+
21
+ def addScenarioLog scenarioLog
22
+ @scenarioLogs.push scenarioLog
23
+ end
24
+
25
+ def done?
26
+ @currentScenariosNumber.eql? totalScenariosNumber
27
+ end
28
+
29
+ end
@@ -0,0 +1,16 @@
1
+ class ScenarioLog
2
+ attr_accessor :featureId, :featureName, :execution_method, :result, :startDate, :endDate,
3
+ :executionLog, :scenarioId, :host, :scenarioName, :outLineResult
4
+
5
+ def initialize
6
+ @execution_method = "AUTOMATE"
7
+ @outLineResult = []
8
+ end
9
+
10
+ def to_json(options={})
11
+ {'feature_id' => @featureId, 'feature_name' => @featureName, 'execution_method' => @execution_method,
12
+ 'result' => @result, 'start_date' => @startDate, 'end_date' => @endDate, 'execute_log' => @executionLog,
13
+ 'scenario_id' => @scenarioId, 'host' => @host}.to_json
14
+ end
15
+
16
+ end
@@ -0,0 +1,263 @@
1
+ require_relative '../lib/qspec_feature/feature_meta'
2
+ require_relative '../lib/qspec_feature/qspec_feature'
3
+ require_relative '../lib/utils/q_test_scenario_utils'
4
+ require_relative '../lib/logs/feature_log'
5
+ require_relative '../lib/logs/scenario_log'
6
+ require_relative 'configuration/constants'
7
+ require 'fileutils'
8
+
9
+ module QTestScenario
10
+ $outline_pattern = '%s, %s (#%s)'
11
+ $hook_version = '1.2'
12
+
13
+ class QTestScenarioPlugin
14
+
15
+ attr_accessor :server, :api_key, :destination_dir, :jql, :keys, :support_folder, :project_path
16
+
17
+ def initialize(args)
18
+ args.each do |k, v|
19
+ instance_variable_set("@#{k}", v) unless v.nil?
20
+ end
21
+ if @server.nil? or @api_key.nil? or @destination_dir.nil?
22
+ puts '--------------------------------------------------------------'
23
+ puts 'Must set at least Jira host URI (server), api key (api_key) and destination folder (destination_dir) for feature files'
24
+ puts '--------------------------------------------------------------'
25
+ exit 1
26
+ end
27
+ if @jql.nil? and @keys.nil?
28
+ puts '--------------------------------------------------------------'
29
+ puts 'Must set at least jql or issue key to select feature files'
30
+ puts '--------------------------------------------------------------'
31
+ exit 1
32
+ end
33
+
34
+ @setup_is_done = false
35
+ generate_hooks
36
+ end
37
+
38
+ def prepare_test
39
+ FileUtils.rm_rf(@destination_dir)
40
+ begin
41
+ FileUtils.mkdir(@destination_dir)
42
+ rescue
43
+ # retry if we encounter PermissionDenied exception
44
+ FileUtils.mkdir(@destination_dir)
45
+ end
46
+
47
+ response = QTestScenarioUtils.get_feature_files(@keys, @jql, @server, @api_key)
48
+ if response.code === 200
49
+ features = JSON.parse(response.body)
50
+ feature_mapper = Hash.new
51
+
52
+ features.each { |feature|
53
+ qspec_feature = QspecFeature.from_json feature
54
+
55
+ # Write qspec_feature to file
56
+ write_to_file(@destination_dir, qspec_feature.fileName, qspec_feature.content)
57
+
58
+ feature_meta = FeatureMeta.new(qspec_feature.id, qspec_feature.name, qspec_feature.scenarios, qspec_feature.versionId)
59
+ feature_mapper[qspec_feature.name] = feature_meta.to_json
60
+ }
61
+
62
+ # Write qspecFeature mapping to file
63
+ write_to_file(@destination_dir, Constants.getMappingFileName, feature_mapper.to_json)
64
+ end
65
+ end
66
+
67
+ def write_to_file (destination_dir, file_name, content)
68
+ path = destination_dir + file_name
69
+ File.open(path, 'wb') do |f|
70
+ f.puts content
71
+ end
72
+ end
73
+
74
+ def get_scenario_log (scenariosLog, featureMeta, scenario)
75
+ scenariosLog.each { |scenarioLog|
76
+ scenarioId = featureMeta.scenarios[scenario.name]
77
+ if scenarioLog.scenarioId.eql? scenarioId
78
+ return scenarioLog
79
+ end
80
+ }
81
+ return nil
82
+ end
83
+
84
+ def before_scenario (scenario)
85
+
86
+ if (!@setup_is_done)
87
+ @setup_is_done = true
88
+ @feature_mappings_map = QTestScenarioUtils.load_feature_mapping_file(@destination_dir)
89
+ @execution = QTestScenarioUtils.create_execution(@server, @api_key)
90
+ @feature_logs_map = Hash.new
91
+ @scenario_id_to_outline_number = Hash.new
92
+ @current_outline_count = 0
93
+ end
94
+
95
+ feature_meta = @feature_mappings_map[scenario.feature.name]
96
+ feature_log = @feature_logs_map[feature_meta.id]
97
+ if feature_log.nil?
98
+ # new feature if not exists
99
+ feature_log = FeatureLog.new
100
+ feature_log.totalScenariosNumber = feature_meta.scenarios.length
101
+ feature_log.featureId = feature_meta.id
102
+ feature_log.versionId = feature_meta.versionId
103
+ feature_log.executionId = @execution.executionId
104
+ feature_log.startDate = Time.now.to_ms
105
+ feature_log.totalScenariosNumber = feature_meta.scenarios.length
106
+ @feature_logs_map[feature_meta.id] = feature_log
107
+
108
+ # build outline count for scenarios
109
+ scenario.feature.feature_elements.each { |child|
110
+ if ('Scenario Outline'.eql? child.keyword) || ('scenario outline'.eql? child.keyword)
111
+ outline_example_count = 0
112
+ scenarioId = feature_meta.scenarios[child.name]
113
+ child.examples_tables.each { |table|
114
+ outline_example_count += table.example_rows.length
115
+ table.example_rows.each { |row|
116
+ outLineName = $outline_pattern % [child.name, table.name, row.number]
117
+ feature_meta.scenarios[outLineName] = scenarioId
118
+ }
119
+ }
120
+ @scenario_id_to_outline_number[scenarioId] = outline_example_count
121
+ end
122
+ }
123
+ end
124
+ # get the scenario log, in case Scenario Outline, we will get the same scenarioLog
125
+ scenario_log = get_scenario_log(feature_log.scenarioLogs, feature_meta, scenario)
126
+ scenario_id = feature_meta.scenarios[scenario.name]
127
+
128
+ if scenario_log.nil?
129
+ scenario_log = ScenarioLog.new
130
+ scenario_log.featureId = feature_meta.id
131
+ scenario_log.featureName = feature_meta.name
132
+ scenario_log.startDate = Time.now.to_ms
133
+ scenario_log.host = Socket.gethostname
134
+ scenario_log.scenarioName = scenario.name
135
+ scenario_log.scenarioId = scenario_id
136
+ feature_log.addScenarioLog(scenario_log)
137
+ end
138
+ end
139
+
140
+ def calculate_result (results)
141
+ if results.include? QspecResult::FAILED
142
+ result = QspecResult::FAILED
143
+ elsif results.include? QspecResult::UNCOMPLETED
144
+ result = QspecResult::UNCOMPLETED
145
+ else
146
+ result = QspecResult::PASSED
147
+ end
148
+ result
149
+ end
150
+
151
+ def after_scenario (scenario)
152
+ feature_meta = @feature_mappings_map[scenario.feature.name]
153
+ feature_log = @feature_logs_map[feature_meta.id]
154
+ scenario_log = get_scenario_log(feature_log.scenarioLogs, feature_meta, scenario)
155
+
156
+ if !scenario_log.nil?
157
+ scenario_log.endDate = Time.now.to_ms
158
+ result = ''
159
+ if scenario.failed?
160
+ scenario_log.executionLog = scenario.exception
161
+ result = QspecResult::FAILED
162
+ else
163
+ if 'passed'.eql? scenario.status.to_s
164
+ result = QspecResult::PASSED
165
+ else
166
+ result = QspecResult::UNCOMPLETED
167
+ end
168
+ end
169
+
170
+ if !scenario.outline?
171
+ # not scenario outline: update result to scenarioLog
172
+ scenario_log.result = result
173
+ feature_log.addScenarioResult(scenario_log.result)
174
+ else
175
+ # scenario outline: doesn't calculate scenario, defer it until all outline has been executed
176
+ scenario_log.outLineResult.push(result)
177
+ @current_outline_count += 1
178
+
179
+ if @current_outline_count.eql? @scenario_id_to_outline_number[scenario_log.scenarioId]
180
+ # put the outline result to scenario log
181
+ scenario_log.result = calculate_result(scenario_log.outLineResult)
182
+ feature_log.addScenarioResult(scenario_log.result)
183
+ @current_outline_count = 0
184
+ end
185
+ end
186
+ end
187
+
188
+ if feature_log.done?
189
+ # all scenarios have been executed, updates the qspecFeature log and sends it to scenario server
190
+ feature_log.result = calculate_result(feature_log.resultSet)
191
+ feature_log.endDate = Time.now.to_ms
192
+
193
+ QTestScenarioUtils.submit_feature_test_log(feature_log, @server, @api_key)
194
+ end
195
+ end
196
+
197
+ def at_exit
198
+ @execution.endDate = Time.now.to_ms
199
+ QTestScenarioUtils.update_execution(@execution, @server, @api_key)
200
+ end
201
+
202
+ def generate_hooks? (version_file_path, hook_file_path)
203
+ generate_hook = false
204
+ begin
205
+ File.open(version_file_path, 'r') do |f|
206
+ versionUsed = f.gets
207
+ if !$hook_version.eql? versionUsed
208
+ File.delete(hook_file_path)
209
+ generate_hook = true
210
+ end
211
+ end
212
+ rescue
213
+ # hook_version does not exist, then generate hook
214
+ generate_hook = true
215
+ end
216
+ generate_hook
217
+ end
218
+
219
+ def generate_hooks
220
+ support_folder_path = @project_path + '/' + @support_folder + '/hook/'
221
+ if !File.directory? (support_folder_path)
222
+ FileUtils.mkdir(support_folder_path)
223
+ end
224
+
225
+ version_file_path = support_folder_path + 'hook_version'
226
+ hook_file_path = support_folder_path + 'hooks.rb'
227
+ generate_hook = generate_hooks?(version_file_path, hook_file_path)
228
+
229
+ if (generate_hook)
230
+ File.open(version_file_path, 'wb') do |f|
231
+ f << $hook_version
232
+ end
233
+
234
+ File.open(hook_file_path, 'wb') do |f|
235
+ f.puts 'require \'qTestScenarioRuby\''
236
+ f.puts ''
237
+ f.puts '$plugin = QTestScenario::QTestScenarioPlugin.new({'
238
+ f.puts ' \'server\' => ENV[\'server\'],'
239
+ f.puts ' \'api_key\' => ENV[\'api_key\'],'
240
+ f.puts ' \'destination_dir\' => ENV[\'destination_dir\'],'
241
+ f.puts ' \'jql\' => ENV[\'jql\'],'
242
+ f.puts ' \'support_folder\' => ENV[\'support_folder\'],'
243
+ f.puts ' \'project_path\' => Dir.pwd'
244
+ f.puts ' })'
245
+ f.puts ''
246
+ f.puts 'Before do |scenario|'
247
+ f.puts ' $plugin.before_scenario scenario'
248
+ f.puts 'end'
249
+ f.puts ''
250
+ f.puts 'After do |scenario|'
251
+ f.puts ' $plugin.after_scenario scenario'
252
+ f.puts 'end'
253
+ f.puts ''
254
+ f.puts 'at_exit do'
255
+ f.puts ' $plugin.at_exit'
256
+ f.puts 'end'
257
+ end
258
+ end
259
+ end
260
+ end
261
+ end
262
+
263
+
@@ -0,0 +1,18 @@
1
+ class FeatureMeta
2
+ attr_accessor :id, :name, :scenarios, :versionId
3
+
4
+ def initialize(id, name, scenarios, versionId)
5
+ @id = id
6
+ @name = name
7
+ @scenarios = scenarios
8
+ @versionId = versionId
9
+ end
10
+
11
+ def to_json(options={})
12
+ {'id' => @id, 'name' => @name, 'scenarios' => @scenarios, 'versionId' => @versionId}
13
+ end
14
+
15
+ def self.from_json data
16
+ self.new data['id'], data['name'], data['scenarios'], data['versionId']
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ class QspecFeature
2
+ attr_accessor :id, :fileName, :name, :content, :versionId, :scenarios
3
+
4
+ def initialize(id, name, content, versionId, fileName, scenarios)
5
+ @id = id
6
+ @name = name
7
+ @content = content
8
+ @versionId = versionId
9
+ @fileName = fileName
10
+ @scenarios = scenarios
11
+ end
12
+
13
+ def self.from_json data
14
+ QspecFeature.new data['id'], data['name'], data['content'], data['versionId'], data['fileName'], data['scenarios']
15
+ end
16
+ end
@@ -0,0 +1,61 @@
1
+ require 'rest-client'
2
+ require 'fileutils'
3
+ require_relative '../../lib/logs/execution_log'
4
+ require_relative '../../lib/qspec_feature/feature_meta'
5
+ require_relative '../../lib/configuration/constants'
6
+
7
+ module QTestScenario
8
+
9
+ class QTestScenarioUtils
10
+
11
+ def self.get_feature_files(keys, jql, server, apiKey)
12
+ params = '?keys=' + keys if (!keys.nil? && !keys.empty?)
13
+ params = '?jql=' + CGI::escape(jql) if (!jql.nil? && !jql.empty?)
14
+
15
+ resource = RestClient::Resource.new(server + Constants.getFeatureFilesUri + params)
16
+ response = resource.get( :Authorization => apiKey )
17
+ end
18
+
19
+ def self.create_execution(server, api_key)
20
+ execution = ExecutionLog.new
21
+ response = RestClient.post(
22
+ server + Constants.getCreateExecutionUri,
23
+ execution.to_json,
24
+ { :Authorization => api_key, :content_type => 'application/json' }
25
+ )
26
+ result = JSON.parse response
27
+ ExecutionLog.from_json(result)
28
+ end
29
+
30
+ def self.update_execution (execution, server, api_key)
31
+ uri = Constants.getUpdateExecutionUri % [execution.executionId]
32
+ RestClient.put(
33
+ server + uri,
34
+ execution.to_json,
35
+ { :Authorization => api_key, :content_type => 'application/json' }
36
+ )
37
+ end
38
+
39
+ def self.load_feature_mapping_file(destination_dir)
40
+ feature_mappings_map = Hash.new
41
+ File.open(destination_dir + Constants.getMappingFileName, 'r') do |f|
42
+ feature_mappings = JSON.parse f.read
43
+ feature_mappings.each { |feature_name, feature_meta_json|
44
+ feature_meta = FeatureMeta.from_json feature_meta_json
45
+ feature_mappings_map[feature_name] = feature_meta
46
+ }
47
+ end
48
+ feature_mappings_map
49
+ end
50
+
51
+ def self.submit_feature_test_log (feature_test_log, server, api_key)
52
+
53
+ uri = Constants.getSubmitFeatureTestLogUri % [feature_test_log.featureId]
54
+ response = RestClient.post(
55
+ server + uri,
56
+ feature_test_log.to_json,
57
+ { :Authorization => api_key, :content_type => 'application/json' }
58
+ )
59
+ end
60
+ end
61
+ end
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qTestScenarioRuby
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Thuan Tran
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-05-30 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A Ruby plugin of qTest Scenario
14
+ email: thuantran@qasymphony.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/configuration/constants.rb
20
+ - lib/logs/execution_log.rb
21
+ - lib/logs/feature_log.rb
22
+ - lib/logs/scenario_log.rb
23
+ - lib/qspec_feature/feature_meta.rb
24
+ - lib/qspec_feature/qspec_feature.rb
25
+ - lib/qTestScenarioRuby.rb
26
+ - lib/utils/q_test_scenario_utils.rb
27
+ homepage: https://www.qasymphony.com/testing-platform/qtest-scenario/
28
+ licenses:
29
+ - MIT
30
+ metadata: {}
31
+ post_install_message:
32
+ rdoc_options: []
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ requirements: []
46
+ rubyforge_project:
47
+ rubygems_version: 2.0.14.1
48
+ signing_key:
49
+ specification_version: 4
50
+ summary: qTest Scenario Ruby plugin!
51
+ test_files: []