tms-cli 0.0.pre.beta
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 +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
|