tms-cli 0.0.pre.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/tms +5 -0
- data/lib/.env +11 -0
- data/lib/cucumber.rb +369 -0
- data/lib/db/mysql.rb +107 -0
- data/lib/import/importcucumber.rb +123 -0
- data/lib/import/importfeature.rb +34 -0
- data/lib/import/importflutter.rb +40 -0
- data/lib/import/importgolang.rb +47 -0
- data/lib/import/importjest.rb +81 -0
- data/lib/import/importjunit.rb +76 -0
- data/lib/import/importrspec.rb +36 -0
- data/lib/jira/jira_api.rb +37 -0
- data/lib/jira/jira_issues.rb +48 -0
- data/lib/preprocessing.rb +334 -0
- data/lib/regression.rb +232 -0
- data/lib/testrail/attachment.rb +17 -0
- data/lib/testrail/cleanup.rb +64 -0
- data/lib/testrail/dataprep.rb +169 -0
- data/lib/testrail/log.rb +15 -0
- data/lib/testrail/milestone.rb +136 -0
- data/lib/testrail/projects.rb +39 -0
- data/lib/testrail/report.rb +61 -0
- data/lib/testrail/results.rb +20 -0
- data/lib/testrail/sections.rb +32 -0
- data/lib/testrail/testbdd.rb +72 -0
- data/lib/testrail/testcase.rb +196 -0
- data/lib/testrail/testplan.rb +93 -0
- data/lib/testrail/testrail.rb +136 -0
- data/lib/testrail/testrun.rb +184 -0
- data/lib/testrail/testsuite.rb +49 -0
- data/lib/tms.rb +337 -0
- data/util/script/generate-password.rb +47 -0
- data/util/script/generatereport.rb +90 -0
- data/util/script/mergerequest.rb +38 -0
- metadata +300 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 126ea4c79dfe3ba2f0577507e6710dd6a87b54931bd88503ff73f69d87bda43a
|
4
|
+
data.tar.gz: f05c3543997e9f3f9e1452d87e99c1a742abcb6bf2fd2ff5703e93bba947e6ca
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 99d223285e06a2ec541feed40f9b2462c332deedf529944708491736741a815e6b06306cff1f152c9c818b22b5020ee4b3e480a3c189759ba26e3b2ebe6bf3b9
|
7
|
+
data.tar.gz: cf16282634835829b2fdc037c1a0377f290ddf70cf9e5339af5d675dd180f2055b39ae72b76e17aa45bc5e65ffa2f261e021dc19838a2693ea0061569f9aca45
|
data/bin/tms
ADDED
data/lib/.env
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
TR_USERNAME=core.quality@bukalapak.com
|
2
|
+
TR_SECRET=coretebukalapak
|
3
|
+
TR_API_KEY=mrVfIsQkG0yhFChoR7j/9r+4GydgMykS7FplZ6/tiXieOIzBKGGRjeI=
|
4
|
+
DB_TR_PORT=3306
|
5
|
+
DB_TR_USERNAME=usr_testrail_rw
|
6
|
+
DB_TR=testrail
|
7
|
+
DB_TR_HOST=mysql-tools-prod-testrail-main.mysql.database.azure.com
|
8
|
+
DB_TR_PASSWORD=8Z9YJfsUGmSKOnshe6vO/A==
|
9
|
+
TR_BASEURL=https://testrail.prod.tools.buka20.com/
|
10
|
+
TR_PASSWORD=/rJHEOwcShrdUA==
|
11
|
+
BASTION_HOST=bastion.prod.tools.buka20.com
|
data/lib/cucumber.rb
ADDED
@@ -0,0 +1,369 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'testrail/testrail'
|
4
|
+
require_relative 'testrail/milestone'
|
5
|
+
require_relative 'testrail/testcase'
|
6
|
+
require_relative 'testrail/testrun'
|
7
|
+
require_relative 'testrail/dataprep'
|
8
|
+
require_relative 'testrail/testsuite'
|
9
|
+
require_relative 'testrail/testplan'
|
10
|
+
require_relative 'testrail/sections'
|
11
|
+
require_relative 'testrail/projects'
|
12
|
+
require_relative 'testrail/log'
|
13
|
+
require_relative 'testrail/testbdd'
|
14
|
+
|
15
|
+
|
16
|
+
module Tms
|
17
|
+
module Cucumber
|
18
|
+
module_function
|
19
|
+
|
20
|
+
include Dataprep
|
21
|
+
include Milestone
|
22
|
+
include Testcase
|
23
|
+
include Testrun
|
24
|
+
include Testsuite
|
25
|
+
include Testplan
|
26
|
+
include Sections
|
27
|
+
include Projects
|
28
|
+
include Log
|
29
|
+
include Testbdd
|
30
|
+
|
31
|
+
# Create test run cucumber test for micorservice project
|
32
|
+
# @param project name
|
33
|
+
# @param test type (suite)
|
34
|
+
# @param squad name
|
35
|
+
# @param custom label
|
36
|
+
# @param milestone name
|
37
|
+
def create_test_run_microservice(project_name, test_type, squad, label, milestone_name)
|
38
|
+
# getting project id
|
39
|
+
test_type = test_type
|
40
|
+
client = Dataprep.client_tr
|
41
|
+
tr_version = Dataprep.testrail_version(client, ENV['TR_BASEURL'])
|
42
|
+
|
43
|
+
project_id = search_project(client, project_name)
|
44
|
+
puts 'project_id found: ' + project_id.to_s if !project_id.nil?
|
45
|
+
|
46
|
+
milestone_id = Milestone.milestone_id(client, project_id, milestone_name, tr_version)
|
47
|
+
suite_id = search_suite(client, project_id, test_type)
|
48
|
+
case_ids = search_cases(client, project_id, suite_id, squad, label)
|
49
|
+
raise 'no cases found' if case_ids.empty?
|
50
|
+
|
51
|
+
test_run_name = "Test_Run_E2E_#{squad}_#{test_type}"
|
52
|
+
response = Testrun.testrun_id_by_milestone(client, project_id, milestone_id)
|
53
|
+
find_test_run = response.find { |run| run['name'] == test_run_name }
|
54
|
+
run_id = find_test_run&.fetch('id', nil)
|
55
|
+
test_run = run_id.nil? ? Testrun.create_testrun(client, project_id, suite_id, milestone_id, case_ids, test_run_name) : run_id
|
56
|
+
|
57
|
+
getter_testrail_clean_dependencies(test_type, milestone_id, test_run)
|
58
|
+
|
59
|
+
return test_run
|
60
|
+
end
|
61
|
+
|
62
|
+
# Create test run cucumber test for app project
|
63
|
+
# @param project name
|
64
|
+
# @param test type (suite)
|
65
|
+
# @param squad name
|
66
|
+
# @param custom label
|
67
|
+
def create_test_run_app(project_name, squad, env_name, test_type, label, pipeline_id, custom_section)
|
68
|
+
client = Dataprep.client_tr
|
69
|
+
puts project_name.split('_')[1]
|
70
|
+
project_id = app_project_id(project_name)
|
71
|
+
suite_id = search_suite(client, project_id, squad)
|
72
|
+
automation_section_ids = find_automation_section(client, project_id, suite_id, project_name.split('_')[1], env_name, custom_section)
|
73
|
+
case_ids = search_cases_by_section_ids(client, project_id, suite_id, automation_section_ids, label)
|
74
|
+
|
75
|
+
raise 'no cases found' if case_ids.empty?
|
76
|
+
|
77
|
+
test_run_name = "Test_Run_#{squad}_#{test_type}_#{env_name}_#{pipeline_id}"
|
78
|
+
response = Testrun.testrun_id_by_suite(client, project_id, milestone_id = '', suite_id)
|
79
|
+
find_test_run = response.find { |run| run['name'] == test_run_name }
|
80
|
+
run_id = find_test_run&.fetch('id', nil)
|
81
|
+
if run_id.nil?
|
82
|
+
puts "Creating #{test_run_name}..."
|
83
|
+
test_run = Testrun.create_testrun(client, project_id, suite_id, 0, case_ids, test_run_name)
|
84
|
+
else
|
85
|
+
puts "Updating #{test_run_name}..."
|
86
|
+
test_run = Testrun.update_testrun(client, run_id, milestone_id = '', case_ids)
|
87
|
+
end
|
88
|
+
|
89
|
+
getter_testrail_clean_dependencies(test_type, milestone_id = '', test_run)
|
90
|
+
|
91
|
+
return test_run
|
92
|
+
end
|
93
|
+
|
94
|
+
# Find sections of automation test
|
95
|
+
# @param client testrail
|
96
|
+
# @param project id
|
97
|
+
# @param suite id
|
98
|
+
# @param app name
|
99
|
+
# @param environment name
|
100
|
+
def find_automation_section(client, project_id, suite_id, app_name, env_name, custom_section)
|
101
|
+
sections = Sections.get_sections(client, project_id, suite_id)
|
102
|
+
app_section = sections['sections'].find { |section| section['name'].casecmp?(app_name) }
|
103
|
+
automation_section = sections['sections'].find{ |section|
|
104
|
+
section['name'].casecmp?('automation') && section['parent_id'].eql?(app_section['id'])
|
105
|
+
}
|
106
|
+
|
107
|
+
env_section = sections['sections'].find{ |section|
|
108
|
+
section['name'].casecmp?(env_name) && section['parent_id'].eql?(automation_section['id'])
|
109
|
+
}
|
110
|
+
parent_id = env_section['id']
|
111
|
+
|
112
|
+
# search for section directory hierarchy
|
113
|
+
target_section = {}
|
114
|
+
if !custom_section.eql? ""
|
115
|
+
sections_directory = custom_section.split('/')
|
116
|
+
sections_directory.each do | section_dir |
|
117
|
+
target_section = sections['sections'].find { |section|
|
118
|
+
section['name'].casecmp?(section_dir) && section['parent_id'].eql?(parent_id)
|
119
|
+
}
|
120
|
+
parent_id = target_section['id']
|
121
|
+
end
|
122
|
+
else
|
123
|
+
target_section = env_section
|
124
|
+
end
|
125
|
+
|
126
|
+
related_section_ids = find_related_sections(sections['sections'], target_section['id']) << target_section['id']
|
127
|
+
end
|
128
|
+
|
129
|
+
# Get project id
|
130
|
+
# @param client testrail
|
131
|
+
# @param project id
|
132
|
+
# @param suite id
|
133
|
+
# @param app name
|
134
|
+
# @param environment name
|
135
|
+
def app_project_id(app_name)
|
136
|
+
project = app_name.split("_")
|
137
|
+
platform = project[0]
|
138
|
+
project_ids = {
|
139
|
+
'android' => ENV['TR_ANDROID_PROJECT_ID'],
|
140
|
+
'ios' => ENV['TR_IOS_PROJECT_ID']
|
141
|
+
}
|
142
|
+
|
143
|
+
project_id = project_ids[platform] || (raise 'Incorrect app name!')
|
144
|
+
end
|
145
|
+
|
146
|
+
# Return all case ids from sections and filter with label
|
147
|
+
# @param client testrail
|
148
|
+
# @param project id
|
149
|
+
# @param suite id
|
150
|
+
# @param section_ids
|
151
|
+
# @param label
|
152
|
+
def search_cases_by_section_ids(client, project_id, suite_id, section_ids, label)
|
153
|
+
case_ids = []
|
154
|
+
puts label
|
155
|
+
|
156
|
+
section_ids.each do |id|
|
157
|
+
cases = Testcase.get_cases(client, project_id, suite_id, id)
|
158
|
+
|
159
|
+
# filter cases with label if any
|
160
|
+
filtered_cases =
|
161
|
+
if label.eql? ''
|
162
|
+
cases
|
163
|
+
else
|
164
|
+
cases.select { |case_data| case_data['custom_label_id']&.include?(label) }
|
165
|
+
end
|
166
|
+
|
167
|
+
case_ids.concat(filtered_cases.map { |case_data| case_data['id'] })
|
168
|
+
end
|
169
|
+
|
170
|
+
return case_ids
|
171
|
+
end
|
172
|
+
|
173
|
+
# Return project id of a project name
|
174
|
+
# @param client testrail
|
175
|
+
# @param project name
|
176
|
+
def search_project(client, project_name)
|
177
|
+
begin
|
178
|
+
projects = Projects.get_projects(client)
|
179
|
+
filtered_projects = projects.select { |project| project['name'].casecmp?(project_name) }
|
180
|
+
|
181
|
+
if filtered_projects.empty?
|
182
|
+
puts "#{project_name} is not available!"
|
183
|
+
else
|
184
|
+
return filtered_projects.first['id']
|
185
|
+
end
|
186
|
+
|
187
|
+
rescue StandardError => e
|
188
|
+
puts "An error occurred: #{e.message}"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# Return suite id of a test type
|
193
|
+
# @param client testrail
|
194
|
+
# @param project id
|
195
|
+
# @param suite name
|
196
|
+
def search_suite(client, project_id, suite_name)
|
197
|
+
begin
|
198
|
+
suites = Testsuite.suites(client, project_id)
|
199
|
+
filtered_suites = suites.select { |suite| suite['name'].casecmp?(suite_name) }
|
200
|
+
|
201
|
+
if filtered_suites.empty?
|
202
|
+
puts "#{suite_name} is not available!"
|
203
|
+
else
|
204
|
+
return filtered_suites.first['id']
|
205
|
+
end
|
206
|
+
|
207
|
+
rescue StandardError => e
|
208
|
+
puts "An error occurred: #{e.message}"
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# Return array of case id from a squad section
|
213
|
+
# @param client testrail
|
214
|
+
# @param project id
|
215
|
+
# @param suite id
|
216
|
+
# @param section_name
|
217
|
+
# @param custom label
|
218
|
+
def search_cases(client, project_id, suite_id, section_name, label)
|
219
|
+
sections = Sections.get_sections(client, project_id, suite_id)
|
220
|
+
squad_section = sections['sections'].find { |section| section['name'].casecmp?(section_name) }
|
221
|
+
raise "squad section #{section_name} not found" if squad_section.eql? nil
|
222
|
+
|
223
|
+
puts 'squad section: ' + squad_section['id'].to_s
|
224
|
+
# search sections related to the squad section
|
225
|
+
related_sections_ids = find_related_sections(sections['sections'], squad_section['id']) << squad_section['id']
|
226
|
+
puts 'sections related from squad: ' + related_sections_ids.to_s
|
227
|
+
|
228
|
+
case_ids = []
|
229
|
+
|
230
|
+
related_sections_ids.each do |id|
|
231
|
+
cases = Testcase.get_cases(client, project_id, suite_id, id)
|
232
|
+
filtered_cases = []
|
233
|
+
|
234
|
+
if label.split(',').size > 1
|
235
|
+
arr_cases = []
|
236
|
+
label.split(',').each do |i|
|
237
|
+
tmp_filtered_cases = cases.select { |case_data| case_data['custom_label_id']&.include?(i) }
|
238
|
+
arr_cases.concat(tmp_filtered_cases)
|
239
|
+
end
|
240
|
+
filtered_cases = arr_cases
|
241
|
+
else
|
242
|
+
filtered_cases = cases.select { |case_data| case_data['custom_label_id']&.include?(label) }
|
243
|
+
end
|
244
|
+
case_ids.concat(filtered_cases.map { |case_data| case_data['id']})
|
245
|
+
|
246
|
+
end
|
247
|
+
|
248
|
+
return case_ids
|
249
|
+
end
|
250
|
+
|
251
|
+
# Return array of section id related to a parent id
|
252
|
+
# @param array of sections
|
253
|
+
# @param parent id
|
254
|
+
def find_related_sections(sections, parent_id)
|
255
|
+
child_ids = sections
|
256
|
+
.select { |obj| obj['parent_id'] == parent_id }
|
257
|
+
.flat_map { |obj| [obj['id']] + find_related_sections(sections, obj['id']) }
|
258
|
+
|
259
|
+
child_ids
|
260
|
+
end
|
261
|
+
|
262
|
+
# Download series of bdd cases from a test run
|
263
|
+
# @aram test run id
|
264
|
+
def feature_download(run_id)
|
265
|
+
client = Dataprep.client_tr
|
266
|
+
puts 'Get test cases for test run id: ' + run_id.to_s
|
267
|
+
num_test = 0
|
268
|
+
# Create the folder if it doesn't exist
|
269
|
+
folder_path = FileUtils.mkdir_p('scenarios')
|
270
|
+
|
271
|
+
tests = Testrun.test_ids(client, run_id)
|
272
|
+
puts "Downloading #{tests.size} test cases..."
|
273
|
+
tests.each do |test|
|
274
|
+
puts "downloading #{test['title']} feature..."
|
275
|
+
response_data = Testbdd.get_bdd(client, test['case_id'])
|
276
|
+
|
277
|
+
# handle test case with scenario outline included
|
278
|
+
response_data = Testbdd.get_case(client, test['case_id']) if response_data.include? ('Scenario Outline')
|
279
|
+
|
280
|
+
# Append test id as a feature label
|
281
|
+
# Handle if a feature already have labels
|
282
|
+
if response_data[0] == "@"
|
283
|
+
response_data = "@TESTID_#{test['id']} " + response_data
|
284
|
+
else
|
285
|
+
response_data = "@TESTID_#{test['id']}\n " + response_data
|
286
|
+
end
|
287
|
+
|
288
|
+
# Writes the data to a feature file
|
289
|
+
Dataprep.create_file("#{test['case_id']}.feature", folder_path, response_data)
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
# Download series of bdd cases from a test case directly (without create test run) on microservice
|
294
|
+
# @param project_name
|
295
|
+
# @param suite_name
|
296
|
+
# @param section_name
|
297
|
+
# @param label
|
298
|
+
def micr_download_feature_only(project_name, suite_name, squad, label)
|
299
|
+
client = Dataprep.client_tr
|
300
|
+
|
301
|
+
project_id = search_project(client, project_name)
|
302
|
+
suite_id = search_suite(client, project_id, suite_name)
|
303
|
+
case_ids = search_cases(client, project_id, suite_id, squad, label)
|
304
|
+
raise 'no cases found' if case_ids.empty?
|
305
|
+
|
306
|
+
download_features_to_local(client, case_ids)
|
307
|
+
|
308
|
+
getter_testrail_clean_dependencies(suite_name, '', '')
|
309
|
+
end
|
310
|
+
|
311
|
+
# Download series of bdd cases from a test case directly (without create test run) on apps
|
312
|
+
# @param project_name
|
313
|
+
# @param suite_name
|
314
|
+
# @param section_name
|
315
|
+
# @param label
|
316
|
+
def app_download_feature_only(project_name, squad, env_name, test_type, label, custom_section)
|
317
|
+
client = Dataprep.client_tr
|
318
|
+
puts project_name.split('_')[1]
|
319
|
+
|
320
|
+
project_id = app_project_id(project_name)
|
321
|
+
suite_id = search_suite(client, project_id, squad)
|
322
|
+
automation_section_ids = find_automation_section(client, project_id, suite_id, project_name.split('_')[1], env_name, custom_section)
|
323
|
+
case_ids = search_cases_by_section_ids(client, project_id, suite_id, automation_section_ids, label)
|
324
|
+
raise 'no cases found' if case_ids.empty?
|
325
|
+
|
326
|
+
download_features_to_local(client, case_ids)
|
327
|
+
|
328
|
+
getter_testrail_clean_dependencies(test_type, '', '')
|
329
|
+
end
|
330
|
+
|
331
|
+
# Download test cases to local storaged
|
332
|
+
# @param case_ids
|
333
|
+
def download_features_to_local(client, case_ids)
|
334
|
+
# Create the folder if it doesn't exist
|
335
|
+
folder_path = FileUtils.mkdir_p('scenarios')
|
336
|
+
|
337
|
+
puts "Download #{case_ids.size} test cases"
|
338
|
+
puts "This test will not create Milestone and Test Runs on Testrail"
|
339
|
+
case_ids.each do |cases|
|
340
|
+
response_data = Testbdd.get_bdd(client, cases)
|
341
|
+
|
342
|
+
# handle test case with scenario outline included
|
343
|
+
response_data = Testbdd.get_case(client, cases) if response_data.include? ('Scenario Outline')
|
344
|
+
|
345
|
+
# Writes the data to a feature file
|
346
|
+
Dataprep.create_file("#{cases}.feature", folder_path, response_data)
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
def getter_testrail_clean_dependencies(test_type, milestone_id, run_id)
|
351
|
+
test_type_upper = test_type.upcase
|
352
|
+
test_type_final = test_type_upper.gsub(/\s*AUTOMATION\s*/, '')
|
353
|
+
puts "Test Type: #{test_type_final}"
|
354
|
+
# Define your environment variables as a hash
|
355
|
+
env_variables = {
|
356
|
+
"TESTRAIL_TEST_TYPE" => test_type_final,
|
357
|
+
"TESTRAIL_#{test_type_final}_MILESTONE_ID" => milestone_id,
|
358
|
+
"TESTRAIL_#{test_type_final}_RUN_ID" => run_id
|
359
|
+
}
|
360
|
+
|
361
|
+
begin
|
362
|
+
Dataprep.create_file_env("testrail-data-post-test", env_variables)
|
363
|
+
rescue => e
|
364
|
+
puts "Create env failed: #{e.message}"
|
365
|
+
exit 1
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
data/lib/db/mysql.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../util/script/generate-password'
|
4
|
+
require 'mysql2'
|
5
|
+
|
6
|
+
module Tms
|
7
|
+
module Database
|
8
|
+
module_function
|
9
|
+
|
10
|
+
include GeneratePassword
|
11
|
+
|
12
|
+
# This method will create client database
|
13
|
+
def connect_db
|
14
|
+
db_host = ENV['DB_TR_HOST']
|
15
|
+
db_port = ENV['DB_TR_PORT']
|
16
|
+
db_user = ENV['DB_TR_USERNAME']
|
17
|
+
db_pass = GeneratePassword.decrypt(ENV['DB_TR_PASSWORD'], ENV['TR_SECRET'])
|
18
|
+
db_name = ENV['DB_TR']
|
19
|
+
Mysql2::Client.new(:host => db_host, :port => db_port, :username => db_user, :password => db_pass, :database => db_name)
|
20
|
+
end
|
21
|
+
|
22
|
+
# This method will validate test runner on database
|
23
|
+
def runner_type(project_id, section_name)
|
24
|
+
test_runner = ''
|
25
|
+
connect_db.query("SELECT runner from runner_type where project_id=#{project_id} and test_type='#{section_name}'").each do |row|
|
26
|
+
test_runner = row['runner']
|
27
|
+
end
|
28
|
+
test_runner
|
29
|
+
end
|
30
|
+
|
31
|
+
# This method will insert test runner if not exist
|
32
|
+
def insert_runner_type(project_id, test_types_and_runner)
|
33
|
+
val = test_types_and_runner.split(',')
|
34
|
+
db_client = connect_db
|
35
|
+
response = db_client.query("SELECT * from runner_type where project_id=#{project_id} and test_type='#{val[0]}' and runner='#{val[1]}'")
|
36
|
+
if response.size.eql?(0)
|
37
|
+
db_client.query("INSERT INTO runner_type(project_id,test_type,runner) VALUE(#{project_id},'#{val[0]}','#{val[1]}');")
|
38
|
+
else
|
39
|
+
Log.info("Test type '#{val[0]}' with runner '#{val[1]}' already exist on project id '#{project_id}'")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# This method will generate config ssh and connect database from local via jump bastion
|
44
|
+
def jump_bastion(email_azure)
|
45
|
+
puts 'connect to vpn buka 2.0 ...'
|
46
|
+
mysql_prod_host = ENV['DB_TR_HOST']
|
47
|
+
mysql_prod_bastion = ENV['BASTION_HOST']
|
48
|
+
ENV.merge!('DB_TR_HOST' => '127.0.0.1')
|
49
|
+
ENV.merge!('DB_TR_PORT' => '3307')
|
50
|
+
|
51
|
+
`rm -rf ~/.ssh/id_rsa.pub-aadcert.pub && rm -rf azure-ssh-config`
|
52
|
+
`az ssh cert --public-key-file ~/.ssh/id_rsa.pub`
|
53
|
+
config = "
|
54
|
+
Host vault-core-dev
|
55
|
+
HostName bastion.dev.core.buka20.com
|
56
|
+
LocalForward 8200 vault.dev.core.buka20.com:8200
|
57
|
+
|
58
|
+
Host vault-core-stg
|
59
|
+
HostName bastion.stg.core.buka20.com
|
60
|
+
LocalForward 8200 vault.stg.core.buka20.com:8200
|
61
|
+
|
62
|
+
Host vault-core-prod
|
63
|
+
HostName bastion.prod.core.buka20.com
|
64
|
+
LocalForward 8200 vault.prod.core.buka20.com:8200
|
65
|
+
|
66
|
+
Host vault-o2o-dev
|
67
|
+
HostName bastion.dev.o2o.buka20.com
|
68
|
+
LocalForward 8200 vault.dev.o2o.buka20.com:8200
|
69
|
+
|
70
|
+
Host vault-o2o-stg
|
71
|
+
HostName bastion.stg.o2o.buka20.com
|
72
|
+
LocalForward 8200 vault.stg.o2o.buka20.com:8200
|
73
|
+
|
74
|
+
Host vault-o2o-prod
|
75
|
+
HostName bastion.prod.o2o.buka20.com
|
76
|
+
LocalForward 8200 vault.prod.o2o.buka20.com:8200
|
77
|
+
|
78
|
+
Host vault-tools-stg
|
79
|
+
HostName bastion.stg.tools.buka20.com
|
80
|
+
LocalForward 8200 vault.stg.tools.buka20.com:8200
|
81
|
+
|
82
|
+
Host vault-tools-prod
|
83
|
+
HostName bastion.prod.tools.buka20.com
|
84
|
+
LocalForward 8200 vault.prod.tools.buka20.com:8200
|
85
|
+
|
86
|
+
Host *
|
87
|
+
User #{email_azure}
|
88
|
+
CertificateFile ~/.ssh/id_rsa.pub-aadcert.pub
|
89
|
+
StrictHostKeyChecking no
|
90
|
+
UserKnownHostsFile /dev/null"
|
91
|
+
|
92
|
+
ssh_conf_file = File.new("azure_config", "w")
|
93
|
+
ssh_conf_file.puts(config)
|
94
|
+
ssh_conf_file.close
|
95
|
+
|
96
|
+
`ssh -F azure_config -NL 3307:#{mysql_prod_host}:3306 #{mysql_prod_bastion} & echo $! > ./pid.file & sleep 5`
|
97
|
+
end
|
98
|
+
|
99
|
+
# This method will stop jump bastion for disconnect database from local
|
100
|
+
def stop_jump_bastion
|
101
|
+
puts 'disconnect to vpn buka 2.0 ...'
|
102
|
+
pid = `cat pid.file`
|
103
|
+
`kill #{pid}`
|
104
|
+
`rm -rf pid.file`
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../testrail/testrail'
|
4
|
+
require_relative '../testrail/testcase'
|
5
|
+
|
6
|
+
module Tms
|
7
|
+
module Cucumber
|
8
|
+
module_function
|
9
|
+
|
10
|
+
include Testcase
|
11
|
+
|
12
|
+
# TODO: Will refer to import_data_bdd instead, after squad migrate test automation to Testrail completely
|
13
|
+
def import_data(client, project_id, suite_id, section_id, report_data_hash, tr_version)
|
14
|
+
# looping the feature
|
15
|
+
report_data_hash.map do |report_data_result|
|
16
|
+
# looping the test cases with get key elements
|
17
|
+
report_data_result['elements'].map do |test_result|
|
18
|
+
# looping the report when keyword is scenario and scenario outline
|
19
|
+
if(test_result['keyword'].downcase == 'scenario' || test_result['keyword'].downcase == 'scenario outline')
|
20
|
+
test_title = test_result['keyword'].downcase == 'scenario outline' ? test_result['id'] : test_result['name']
|
21
|
+
scenario = check_status_and_error_message(test_result['steps'], test_title)
|
22
|
+
test_status = scenario[0]['status']
|
23
|
+
|
24
|
+
# if status is "pending", should get status from object "after" instead
|
25
|
+
# since in cucumber report "pending" turn out as "failed" on summary result
|
26
|
+
if test_status == 'pending'
|
27
|
+
test_status = test_result['after'][0]['result']['status']
|
28
|
+
end
|
29
|
+
|
30
|
+
test_status_id = Testcase.get_status_id(test_status)
|
31
|
+
error_comment = scenario[0]['error_message']
|
32
|
+
refs = get_refs_id(test_result['tags']) || ''
|
33
|
+
|
34
|
+
Testcase.validate_testcase(client, section_id, test_title, test_status_id, refs, tr_version, error_comment)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def import_data_bdd(client, project_id, suite_id, section_id, report_data_hash, tr_version)
|
41
|
+
# looping the feature
|
42
|
+
report_data_hash.map do |report_data_result|
|
43
|
+
# looping the test cases with get key elements
|
44
|
+
report_data_result['elements'].map do |test_result|
|
45
|
+
# looping the report when keyword is scenario and scenario outline
|
46
|
+
if(test_result['keyword'].downcase == 'scenario' || test_result['keyword'].downcase == 'scenario outline')
|
47
|
+
test_title = test_result['keyword'].downcase == 'scenario outline' ? test_result['id'] : test_result['name']
|
48
|
+
scenario = check_status_and_error_message(test_result['steps'], test_title)
|
49
|
+
labels = test_result['tags'][0]['name']
|
50
|
+
test_status = scenario[0]['status']
|
51
|
+
|
52
|
+
test_status_id = Testcase.get_status_id(test_status)
|
53
|
+
error_comment = scenario[0]['error_message']
|
54
|
+
refs = get_refs_id(test_result['tags']) || ''
|
55
|
+
|
56
|
+
if labels.include?('@TESTID_')
|
57
|
+
test_id = labels.gsub('@TESTID_','')
|
58
|
+
Results.add_result(client, test_id, test_status_id, error_comment)
|
59
|
+
end
|
60
|
+
Testcase.validate_testcase_bdd(client, section_id, test_id, refs, tr_version)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def check_status_and_error_message(steps, test_title)
|
67
|
+
result_scenario = []
|
68
|
+
isSuccess = true
|
69
|
+
error_message = ''
|
70
|
+
test_result = {}
|
71
|
+
list_status = ['passed', 'skipped', 'failed', 'undefined', 'pending']
|
72
|
+
|
73
|
+
#looping each steps in scenario
|
74
|
+
steps.map do |scenario|
|
75
|
+
status = scenario['result']['status']
|
76
|
+
# check if status failed or skipped then save the status failed and pending and not continue the looping
|
77
|
+
# save the status and error message
|
78
|
+
# if failed then get the error message from json and if skipped then the error message will be empty
|
79
|
+
if list_status.include?(status)
|
80
|
+
if status.downcase == 'failed' || status.downcase == 'undefined' || status.downcase == 'skipped'
|
81
|
+
isSuccess = false
|
82
|
+
error_message = scenario['result']['error_message'] || ''
|
83
|
+
test_result['status']= 'failed'
|
84
|
+
test_result['error_message']= error_message
|
85
|
+
break
|
86
|
+
end
|
87
|
+
else
|
88
|
+
puts "invalid status is in test case with title = #{test_title}"
|
89
|
+
puts "status = #{status}"
|
90
|
+
isSuccess = false
|
91
|
+
test_result['status'] = 'invalid status'
|
92
|
+
test_result['error_message'] = error_message
|
93
|
+
break
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# after looping all the steps if there is no failed and skipeed then the status will be passed and error message will be empty
|
98
|
+
if isSuccess == true
|
99
|
+
test_result['status'] = 'passed'
|
100
|
+
test_result['error_message'] = error_message
|
101
|
+
end
|
102
|
+
|
103
|
+
return result_scenario.push(test_result)
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_refs_id(elements)
|
107
|
+
jira_id = ''
|
108
|
+
|
109
|
+
# looping the tag element and find prefix @TEST or @CUCUMBER
|
110
|
+
elements.map do |element|
|
111
|
+
tag = element['name']
|
112
|
+
if tag.include?("@TEST_") || tag.include?("@CUCUMBER_")
|
113
|
+
# split the tag name with _ and save the value on index 1 that have value of JIRA ID
|
114
|
+
array_jira_id = tag.split("_")
|
115
|
+
jira_id = array_jira_id[1]
|
116
|
+
break
|
117
|
+
end
|
118
|
+
end
|
119
|
+
return jira_id
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative '../testrail/testrail'
|
3
|
+
|
4
|
+
module Tms
|
5
|
+
module Feature
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def parsing_feature(file)
|
9
|
+
updated_bdd_scenario = ''
|
10
|
+
feature_file = File.read(file)
|
11
|
+
|
12
|
+
bdd_refs = feature_file.lines.first.scan(/@[\w-]+/).join(',').gsub('@','')
|
13
|
+
|
14
|
+
# Extract test title from local file
|
15
|
+
bdd_title = feature_file.match(/Feature:(.+)/)[1]
|
16
|
+
# Extract custom label and BDD scenario from local file
|
17
|
+
bdd_label = feature_file.match(/Feature:.+?\n\s*(.+?)\n/m)[1].scan(/@\S+/).join(' ')
|
18
|
+
bdd_scenario = bdd_label + "\n" + feature_file.match(/(?:Scenario Outline|Scenario):(.+?)(?=Scenario(?:Outline|:)|\z)/m)[0]
|
19
|
+
|
20
|
+
[bdd_refs, bdd_title, bdd_label, bdd_scenario]
|
21
|
+
end
|
22
|
+
|
23
|
+
def update_bdd(client, case_id, file)
|
24
|
+
bdd_refs, bdd_title, bdd_label, bdd_scenario = parsing_feature(file)
|
25
|
+
Testcase.update_case(client, case_id, bdd_refs, bdd_title, bdd_label, bdd_scenario)
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_case(client, section_id, file)
|
29
|
+
bdd_refs, bdd_title, bdd_label, bdd_scenario = parsing_feature(file)
|
30
|
+
Testcase.add_case(client, section_id, bdd_refs, bdd_title, bdd_label, bdd_scenario)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|