robotframework-robotlog2rqm 1.4.0__tar.gz → 1.4.2__tar.gz
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.
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/PKG-INFO +13 -20
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/CRQM.py +135 -44
- robotframework-robotlog2rqm-1.4.2/RobotLog2RQM/RobotLog2RQM.pdf +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/robotlog2rqm.py +149 -21
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/version.py +2 -3
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/robotframework_robotlog2rqm.egg-info/PKG-INFO +13 -20
- robotframework-robotlog2rqm-1.4.0/RobotLog2RQM/RobotLog2RQM.pdf +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/LICENSE +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/README.rst +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/RQM_templates/buildrecord.xml +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/RQM_templates/configuration.xml +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/RQM_templates/executionresult.xml +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/RQM_templates/executionworkitem.xml +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/RQM_templates/suiteexecutionrecord.xml +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/RQM_templates/testcase.xml +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/RQM_templates/testsuite.xml +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/RQM_templates/testsuitelog.xml +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/__init__.py +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/__main__.py +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/robotframework_robotlog2rqm.egg-info/SOURCES.txt +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/robotframework_robotlog2rqm.egg-info/dependency_links.txt +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/robotframework_robotlog2rqm.egg-info/entry_points.txt +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/robotframework_robotlog2rqm.egg-info/requires.txt +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/robotframework_robotlog2rqm.egg-info/top_level.txt +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/setup.cfg +0 -0
- {robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: robotframework-robotlog2rqm
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.2
|
|
4
4
|
Summary: Imports robot result(s) to IBM Rational Quality Manager (RQM)
|
|
5
5
|
Home-page: https://github.com/test-fullautomation/robotframework-robotlog2rqm
|
|
6
6
|
Author: Tran Duy Ngoan
|
|
@@ -17,8 +17,7 @@ Requires-Python: >=3.0
|
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
|
19
19
|
|
|
20
|
-
RobotLog2RQM Description
|
|
21
|
-
========================
|
|
20
|
+
# RobotLog2RQM Description
|
|
22
21
|
|
|
23
22
|
The Python package **RobotLog2RQM** provides ability to import [Robot
|
|
24
23
|
Framework test
|
|
@@ -38,14 +37,13 @@ Manager](https://www.ibm.com/support/knowledgecenter/SSYMRC_6.0.2/com.ibm.ration
|
|
|
38
37
|
**RobotLog2RQM** tool is operating system independent and only works
|
|
39
38
|
with Python 3.
|
|
40
39
|
|
|
41
|
-
How to install
|
|
42
|
-
--------------
|
|
40
|
+
## How to install
|
|
43
41
|
|
|
44
42
|
**RobotLog2RQM** can be installed in two different ways.
|
|
45
43
|
|
|
46
44
|
1. Installation via PyPi (recommended for users)
|
|
47
45
|
|
|
48
|
-
```
|
|
46
|
+
```
|
|
49
47
|
pip install RobotLog2RQM
|
|
50
48
|
```
|
|
51
49
|
|
|
@@ -57,7 +55,7 @@ How to install
|
|
|
57
55
|
- Clone the **robotframework-robotlog2rqm** repository to your
|
|
58
56
|
machine.
|
|
59
57
|
|
|
60
|
-
```
|
|
58
|
+
```
|
|
61
59
|
git clone https://github.com/test-fullautomation/robotframework-robotlog2rqm.git
|
|
62
60
|
```
|
|
63
61
|
|
|
@@ -72,7 +70,7 @@ How to install
|
|
|
72
70
|
packages you can find in the file `requirements.txt` in the
|
|
73
71
|
repository root folder. Use pip to install them:
|
|
74
72
|
|
|
75
|
-
```
|
|
73
|
+
```
|
|
76
74
|
pip install -r ./requirements.txt
|
|
77
75
|
```
|
|
78
76
|
|
|
@@ -91,7 +89,7 @@ How to install
|
|
|
91
89
|
to find **LaTeX**. This is defined in the **GenPackageDoc**
|
|
92
90
|
configuration file
|
|
93
91
|
|
|
94
|
-
```
|
|
92
|
+
```
|
|
95
93
|
packagedoc\packagedoc_config.json
|
|
96
94
|
```
|
|
97
95
|
|
|
@@ -103,7 +101,7 @@ How to install
|
|
|
103
101
|
|
|
104
102
|
- Use the following command to install **RobotLog2RQM**:
|
|
105
103
|
|
|
106
|
-
```
|
|
104
|
+
```
|
|
107
105
|
python setup.py install
|
|
108
106
|
```
|
|
109
107
|
|
|
@@ -114,8 +112,7 @@ be available (under *Scripts* folder of Python on Windows and
|
|
|
114
112
|
In case above location is added to **PATH** environment variable then
|
|
115
113
|
you can run it directly as operation system\'s command.
|
|
116
114
|
|
|
117
|
-
How to use
|
|
118
|
-
----------
|
|
115
|
+
## How to use
|
|
119
116
|
|
|
120
117
|
**RobotLog2RQM** tool requires the Robot Framework `output.xml` result
|
|
121
118
|
file(s) which will be imported, RQM information(e.g. host url, project,
|
|
@@ -219,8 +216,7 @@ cases and their results are reflected on RQM, please refer to
|
|
|
219
216
|
[RobotLog2RQM tool's
|
|
220
217
|
Documentation](https://github.com/test-fullautomation/robotframework-robotlog2rqm/blob/develop/RobotLog2RQM/RobotLog2RQM.pdf).
|
|
221
218
|
|
|
222
|
-
Feedback
|
|
223
|
-
--------
|
|
219
|
+
## Feedback
|
|
224
220
|
|
|
225
221
|
To give us a feedback, you can send an email to [Thomas
|
|
226
222
|
Pollerspöck](mailto:Thomas.Pollerspoeck@de.bosch.com).
|
|
@@ -228,15 +224,13 @@ Pollerspöck](mailto:Thomas.Pollerspoeck@de.bosch.com).
|
|
|
228
224
|
In case you want to report a bug or request any interesting feature,
|
|
229
225
|
please don\'t hesitate to raise a ticket.
|
|
230
226
|
|
|
231
|
-
Maintainers
|
|
232
|
-
-----------
|
|
227
|
+
## Maintainers
|
|
233
228
|
|
|
234
229
|
[Thomas Pollerspöck](mailto:Thomas.Pollerspoeck@de.bosch.com)
|
|
235
230
|
|
|
236
231
|
[Tran Duy Ngoan](mailto:Ngoan.TranDuy@vn.bosch.com)
|
|
237
232
|
|
|
238
|
-
Contributors
|
|
239
|
-
------------
|
|
233
|
+
## Contributors
|
|
240
234
|
|
|
241
235
|
[Nguyen Huynh Tri Cuong](mailto:Cuong.NguyenHuynhTri@vn.bosch.com)
|
|
242
236
|
|
|
@@ -246,8 +240,7 @@ Contributors
|
|
|
246
240
|
|
|
247
241
|
[Holger Queckenstedt](mailto:Holger.Queckenstedt@de.bosch.com)
|
|
248
242
|
|
|
249
|
-
License
|
|
250
|
-
-------
|
|
243
|
+
## License
|
|
251
244
|
|
|
252
245
|
Copyright 2020-2024 Robert Bosch GmbH
|
|
253
246
|
|
{robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/CRQM.py
RENAMED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
#
|
|
16
16
|
# File: CRQM.py
|
|
17
17
|
#
|
|
18
|
-
#
|
|
18
|
+
# Initially created by Tran Duy Ngoan(RBVH/ECM11) / January 2021
|
|
19
19
|
#
|
|
20
20
|
# This is CRQMClient class which is used to interact with RQM via RQM REST APIs
|
|
21
21
|
#
|
|
@@ -78,6 +78,14 @@ Parse xml object from file.
|
|
|
78
78
|
exit(1)
|
|
79
79
|
return oTree
|
|
80
80
|
|
|
81
|
+
class Identifier:
|
|
82
|
+
"""
|
|
83
|
+
Identifier class used to identify RQM resource with name and id
|
|
84
|
+
"""
|
|
85
|
+
def __init__(self, name='', id=None):
|
|
86
|
+
self.name = name
|
|
87
|
+
self.id = id
|
|
88
|
+
|
|
81
89
|
#
|
|
82
90
|
# IBM Rational Quality Manager
|
|
83
91
|
#
|
|
@@ -87,7 +95,7 @@ class CRQMClient():
|
|
|
87
95
|
CRQMClient class uses RQM REST APIs to get, create and update resources
|
|
88
96
|
(testplan, testcase, test result, ...) on RQM - Rational Quality Manager
|
|
89
97
|
|
|
90
|
-
|
|
98
|
+
Resource type mapping:
|
|
91
99
|
|
|
92
100
|
* buildrecord: Build Record
|
|
93
101
|
* configuration: Test Environment
|
|
@@ -131,6 +139,17 @@ Resoure type mapping:
|
|
|
131
139
|
'ns21' : "http://www.w3.org/1999/XSL/Transform"
|
|
132
140
|
}
|
|
133
141
|
|
|
142
|
+
# define the convention for naming new RQM resource
|
|
143
|
+
SUPPORTED_PLACEHOLDER = ["testplan", "build", "environment", "testsuite", "testcase"]
|
|
144
|
+
NAMING_CONVENTION = {
|
|
145
|
+
"testcase" : "{testcase}",
|
|
146
|
+
"tcer" : "TCER: {testcase}",
|
|
147
|
+
"testresult" : "Execution result: {testcase}",
|
|
148
|
+
"testsuite" : "{testsuite}",
|
|
149
|
+
"tser" : "TSER: {testsuite}",
|
|
150
|
+
"suiteresult" : "Testsuite result: {testsuite}"
|
|
151
|
+
}
|
|
152
|
+
|
|
134
153
|
def __init__(self, user, password, project, host):
|
|
135
154
|
"""
|
|
136
155
|
Constructor of class ``CRQMClient``.
|
|
@@ -175,7 +194,7 @@ Constructor of class ``CRQMClient``.
|
|
|
175
194
|
'OSLC-Core-Version' : '2.0'
|
|
176
195
|
}
|
|
177
196
|
|
|
178
|
-
# Templates location which is
|
|
197
|
+
# Templates location which is used for importing
|
|
179
198
|
self.templatesDir = os.path.join(os.path.dirname(__file__),'RQM_templates')
|
|
180
199
|
|
|
181
200
|
# Data for mapping and linking
|
|
@@ -190,17 +209,17 @@ Constructor of class ``CRQMClient``.
|
|
|
190
209
|
self.lEndTimes = list()
|
|
191
210
|
|
|
192
211
|
# RQM configuration info
|
|
193
|
-
self.testplan = None
|
|
194
|
-
self.build = None
|
|
195
|
-
self.configuration = None
|
|
196
212
|
self.createmissing = None
|
|
197
213
|
self.updatetestcase= None
|
|
198
|
-
self.
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
self.stream =
|
|
203
|
-
self.baseline =
|
|
214
|
+
self.testplan = Identifier()
|
|
215
|
+
self.build = Identifier()
|
|
216
|
+
self.configuration = Identifier()
|
|
217
|
+
self.testsuite = Identifier()
|
|
218
|
+
self.stream = Identifier()
|
|
219
|
+
self.baseline = Identifier()
|
|
220
|
+
|
|
221
|
+
# Naming convention
|
|
222
|
+
self.naming_convention = None
|
|
204
223
|
|
|
205
224
|
def login(self):
|
|
206
225
|
"""
|
|
@@ -290,8 +309,8 @@ Disconnect from RQM.
|
|
|
290
309
|
self.session.close()
|
|
291
310
|
|
|
292
311
|
def config(self, plan_id, build_name=None, config_name=None,
|
|
293
|
-
createmissing=False, updatetestcase=False, suite_id=None,
|
|
294
|
-
stream=None, baseline=None):
|
|
312
|
+
createmissing=False, updatetestcase=False, suite_id=None,
|
|
313
|
+
stream=None, baseline=None, naming_convention=None):
|
|
295
314
|
"""
|
|
296
315
|
Configure RQMClient with testplan ID, build, configuration, createmissing, ...
|
|
297
316
|
|
|
@@ -344,11 +363,15 @@ Configure RQMClient with testplan ID, build, configuration, createmissing, ...
|
|
|
344
363
|
(*no returns*)
|
|
345
364
|
"""
|
|
346
365
|
try:
|
|
366
|
+
self.naming_convention = self.NAMING_CONVENTION
|
|
367
|
+
if naming_convention:
|
|
368
|
+
self.naming_convention.update(naming_convention)
|
|
369
|
+
|
|
347
370
|
self.createmissing = createmissing
|
|
348
371
|
self.updatetestcase = updatetestcase
|
|
349
|
-
self.testplan = plan_id
|
|
350
|
-
self.testsuite
|
|
351
|
-
|
|
372
|
+
self.testplan.id = plan_id
|
|
373
|
+
self.testsuite.id = suite_id
|
|
374
|
+
|
|
352
375
|
# Add Configuration-Context header information due to given stream or baseline
|
|
353
376
|
if stream:
|
|
354
377
|
res = self.getAllByResource('stream')
|
|
@@ -357,12 +380,13 @@ Configure RQMClient with testplan ID, build, configuration, createmissing, ...
|
|
|
357
380
|
bFoundStream = False
|
|
358
381
|
for stream_id, stream_name in dStreams.items():
|
|
359
382
|
if stream_name == stream:
|
|
360
|
-
self.stream = stream_id
|
|
383
|
+
self.stream.id = stream_id
|
|
384
|
+
self.stream.name = stream_name
|
|
361
385
|
bFoundStream = True
|
|
362
386
|
self.headers['Configuration-Context'] = stream_id
|
|
363
387
|
self.session.headers = self.headers
|
|
364
388
|
break
|
|
365
|
-
|
|
389
|
+
|
|
366
390
|
if not bFoundStream:
|
|
367
391
|
raise Exception(f"Cannot found given stream '{stream}'")
|
|
368
392
|
else:
|
|
@@ -374,12 +398,13 @@ Configure RQMClient with testplan ID, build, configuration, createmissing, ...
|
|
|
374
398
|
bFoundBaseline = False
|
|
375
399
|
for baseline_id, baseline_name in dBaselines.items():
|
|
376
400
|
if baseline_name == baseline:
|
|
377
|
-
self.baseline = baseline_id
|
|
401
|
+
self.baseline.id = baseline_id
|
|
402
|
+
self.baseline.name = baseline_name
|
|
378
403
|
bFoundBaseline = True
|
|
379
404
|
self.headers['Configuration-Context'] = baseline_id
|
|
380
405
|
self.session.headers = self.headers
|
|
381
406
|
break
|
|
382
|
-
|
|
407
|
+
|
|
383
408
|
if not bFoundBaseline:
|
|
384
409
|
raise Exception(f"Cannot found given baseline '{baseline}'")
|
|
385
410
|
else:
|
|
@@ -390,6 +415,9 @@ Configure RQMClient with testplan ID, build, configuration, createmissing, ...
|
|
|
390
415
|
if res_plan.status_code != 200:
|
|
391
416
|
raise Exception('Testplan with ID %s is not existing!'%str(plan_id))
|
|
392
417
|
|
|
418
|
+
oTestplan = get_xml_tree(BytesIO(str(res_plan.text).encode()), bdtd_validation=False)
|
|
419
|
+
self.testplan.name = oTestplan.find('ns4:title', oTestplan.getroot().nsmap).text
|
|
420
|
+
|
|
393
421
|
# Verify and create build version if required
|
|
394
422
|
if build_name != None:
|
|
395
423
|
if build_name == '':
|
|
@@ -397,7 +425,8 @@ Configure RQMClient with testplan ID, build, configuration, createmissing, ...
|
|
|
397
425
|
self.getAllBuildRecords()
|
|
398
426
|
res_build = self.createBuildRecord(build_name)
|
|
399
427
|
if res_build['success'] or res_build['status_code'] == "303":
|
|
400
|
-
self.build = res_build['id']
|
|
428
|
+
self.build.id = res_build['id']
|
|
429
|
+
self.build.name = build_name
|
|
401
430
|
else:
|
|
402
431
|
raise Exception("Cannot create build '%s': %s"%
|
|
403
432
|
(build_name, res_build['message']))
|
|
@@ -409,7 +438,8 @@ Configure RQMClient with testplan ID, build, configuration, createmissing, ...
|
|
|
409
438
|
self.getAllConfigurations()
|
|
410
439
|
res_conf = self.createConfiguration(config_name)
|
|
411
440
|
if res_conf['success'] or res_conf['status_code'] == "303":
|
|
412
|
-
self.configuration = res_conf['id']
|
|
441
|
+
self.configuration.id = res_conf['id']
|
|
442
|
+
self.configuration.name = config_name
|
|
413
443
|
else:
|
|
414
444
|
raise Exception("Cannot create configuration '%s': %s"%
|
|
415
445
|
(config_name, res_conf['message']))
|
|
@@ -420,11 +450,11 @@ Configure RQMClient with testplan ID, build, configuration, createmissing, ...
|
|
|
420
450
|
if res_suite.status_code != 200:
|
|
421
451
|
raise Exception('Testsuite with ID %s is not existing!'%str(suite_id))
|
|
422
452
|
oTestsuite = get_xml_tree(BytesIO(str(res_suite.text).encode()), bdtd_validation=False)
|
|
423
|
-
self.testsuite
|
|
453
|
+
self.testsuite.name = oTestsuite.find('ns4:title', oTestsuite.getroot().nsmap).text
|
|
424
454
|
|
|
425
455
|
# get all team-areas for testcase template
|
|
426
456
|
self.getAllTeamAreas()
|
|
427
|
-
|
|
457
|
+
|
|
428
458
|
|
|
429
459
|
except Exception as error:
|
|
430
460
|
raise Exception('Configure RQMClient failed: %s'%error)
|
|
@@ -454,7 +484,7 @@ Return interaction URL of provided userID
|
|
|
454
484
|
|
|
455
485
|
def integrationURL(self, resourceType, id=None, forceinternalID=False):
|
|
456
486
|
"""
|
|
457
|
-
Return interaction URL of provided
|
|
487
|
+
Return interaction URL of provided resource and ID.
|
|
458
488
|
The provided ID can be internalID (contains only digits) or externalID.
|
|
459
489
|
|
|
460
490
|
**Arguments:**
|
|
@@ -486,7 +516,7 @@ The provided ID can be internalID (contains only digits) or externalID.
|
|
|
486
516
|
|
|
487
517
|
/ *Type*: str /
|
|
488
518
|
|
|
489
|
-
The interaction URL of provided
|
|
519
|
+
The interaction URL of provided resource and ID.
|
|
490
520
|
"""
|
|
491
521
|
integrationURL = self.host + "/qm/service/com.ibm.rqm.integration.service.IIntegrationService/resources/" + \
|
|
492
522
|
self.projectID + '/' + resourceType
|
|
@@ -538,7 +568,7 @@ Note:
|
|
|
538
568
|
raise Exception("Cannot get ID from response. Reason: %s"%str(error))
|
|
539
569
|
return resultId
|
|
540
570
|
|
|
541
|
-
def webIDfromGeneratedID(self,
|
|
571
|
+
def webIDfromGeneratedID(self, resourceType, generateID):
|
|
542
572
|
"""
|
|
543
573
|
Return web ID (ns2:webId) from generate ID by get resource data from RQM.
|
|
544
574
|
|
|
@@ -549,7 +579,7 @@ Note:
|
|
|
549
579
|
|
|
550
580
|
**Arguments:**
|
|
551
581
|
|
|
552
|
-
* ``
|
|
582
|
+
* ``resourceType``
|
|
553
583
|
|
|
554
584
|
/ *Condition*: required / *Type*: str /
|
|
555
585
|
|
|
@@ -583,8 +613,8 @@ Note:
|
|
|
583
613
|
'testscript',
|
|
584
614
|
'testsuite',
|
|
585
615
|
'testsuitelog']
|
|
586
|
-
if
|
|
587
|
-
resResource = self.getResourceByID(
|
|
616
|
+
if resourceType in lSupportedResources:
|
|
617
|
+
resResource = self.getResourceByID(resourceType, generateID)
|
|
588
618
|
if resResource.status_code == 200:
|
|
589
619
|
oResource = get_xml_tree(BytesIO(str(resResource.text).encode()),
|
|
590
620
|
bdtd_validation=False)
|
|
@@ -595,6 +625,61 @@ Note:
|
|
|
595
625
|
raise Exception("Cannot get web ID of generated testcase!")
|
|
596
626
|
return webID
|
|
597
627
|
|
|
628
|
+
def __genResourceName(self, resource, name):
|
|
629
|
+
"""
|
|
630
|
+
Return the name for given resource bases on the naming convention
|
|
631
|
+
|
|
632
|
+
**Arguments:**
|
|
633
|
+
|
|
634
|
+
* ``resource``
|
|
635
|
+
|
|
636
|
+
/ *Condition*: required / *Type*: str /
|
|
637
|
+
|
|
638
|
+
The RQM resource type.
|
|
639
|
+
|
|
640
|
+
* ``name``
|
|
641
|
+
|
|
642
|
+
/ *Condition*: required / *Type*: str /
|
|
643
|
+
|
|
644
|
+
Relevant resource name.
|
|
645
|
+
|
|
646
|
+
**Returns:**
|
|
647
|
+
|
|
648
|
+
* ``resourceName``
|
|
649
|
+
|
|
650
|
+
/ *Type*: str /
|
|
651
|
+
|
|
652
|
+
Resource name after replacing bases on naming convention.
|
|
653
|
+
"""
|
|
654
|
+
dPlaceHolders = {
|
|
655
|
+
"{testplan}": self.testplan.name
|
|
656
|
+
}
|
|
657
|
+
testcaseRelevant = ["testcase", "tcer", "testresult"]
|
|
658
|
+
testsuiteRelevant = ["testsuite", "tser", "suiteresult"]
|
|
659
|
+
|
|
660
|
+
# Define scope of place holders
|
|
661
|
+
if resource in testcaseRelevant:
|
|
662
|
+
dPlaceHolders.update({
|
|
663
|
+
"{build}": self.build.name,
|
|
664
|
+
"{environment}": self.configuration.name,
|
|
665
|
+
"{testsuite}": self.testsuite.name,
|
|
666
|
+
"{testcase}": name
|
|
667
|
+
})
|
|
668
|
+
elif resource in testsuiteRelevant:
|
|
669
|
+
dPlaceHolders.update({
|
|
670
|
+
"{build}": self.build.name,
|
|
671
|
+
"{environment}": self.configuration.name,
|
|
672
|
+
"{testsuite}": name,
|
|
673
|
+
})
|
|
674
|
+
|
|
675
|
+
try:
|
|
676
|
+
resourceName = self.naming_convention[resource]
|
|
677
|
+
for placeHolder, val in dPlaceHolders.items():
|
|
678
|
+
resourceName = resourceName.replace(placeHolder, val)
|
|
679
|
+
return resourceName
|
|
680
|
+
except:
|
|
681
|
+
raise Exception(f"Failed to generate name for {resource} '{name}'")
|
|
682
|
+
|
|
598
683
|
#
|
|
599
684
|
# Methods to get resources
|
|
600
685
|
#
|
|
@@ -605,7 +690,7 @@ Return data of provided resource and ID by GET method
|
|
|
605
690
|
|
|
606
691
|
**Arguments:**
|
|
607
692
|
|
|
608
|
-
* ``
|
|
693
|
+
* ``resourceType``
|
|
609
694
|
|
|
610
695
|
/ *Condition*: required / *Type*: str /
|
|
611
696
|
|
|
@@ -635,7 +720,7 @@ Return all entries (in all pages) of provided resource by GET method.
|
|
|
635
720
|
|
|
636
721
|
**Arguments:**
|
|
637
722
|
|
|
638
|
-
* ``
|
|
723
|
+
* ``resourceType``
|
|
639
724
|
|
|
640
725
|
/ *Condition*: required / *Type*: str /
|
|
641
726
|
|
|
@@ -897,7 +982,7 @@ Return testcase template from provided information.
|
|
|
897
982
|
root = oTree.getroot()
|
|
898
983
|
nsmap = root.nsmap
|
|
899
984
|
# prepare required data for template
|
|
900
|
-
testcaseTittle = testcaseName
|
|
985
|
+
testcaseTittle = self.__genResourceName('testcase', testcaseName)
|
|
901
986
|
|
|
902
987
|
# find nodes to change data
|
|
903
988
|
oTittle = oTree.find(f'{{{self.NAMESPACES["ns3"]}}}title')
|
|
@@ -1010,7 +1095,8 @@ Return testcase execution record template from provided information.
|
|
|
1010
1095
|
root = oTree.getroot()
|
|
1011
1096
|
nsmap = root.nsmap
|
|
1012
1097
|
# prepare required data for template
|
|
1013
|
-
TCERTittle = '
|
|
1098
|
+
TCERTittle = self.__genResourceName('tcer', testcaseName)
|
|
1099
|
+
|
|
1014
1100
|
|
|
1015
1101
|
# Check tcid is internalid or externalid
|
|
1016
1102
|
testcaseURL = self.integrationURL('testcase', testcaseID)
|
|
@@ -1156,7 +1242,7 @@ Return testcase execution result template from provided information.
|
|
|
1156
1242
|
nsmap = root.nsmap
|
|
1157
1243
|
# prepare required data for template
|
|
1158
1244
|
prefixState = 'com.ibm.rqm.execution.common.state.'
|
|
1159
|
-
resultTittle = '
|
|
1245
|
+
resultTittle = self.__genResourceName('testresult', testcaseName)
|
|
1160
1246
|
testcaseURL = self.integrationURL('testcase', testcaseID)
|
|
1161
1247
|
testplanURL = self.integrationURL('testplan', testplanID)
|
|
1162
1248
|
TCERURL = self.integrationURL('executionworkitem', TCERID)
|
|
@@ -1339,7 +1425,7 @@ Return testsuite execution record (TSER) template from provided configuration na
|
|
|
1339
1425
|
oTree = get_xml_tree(sTemplatePath, bdtd_validation=False)
|
|
1340
1426
|
root = oTree.getroot()
|
|
1341
1427
|
# prepare required data for template
|
|
1342
|
-
TSERTittle = '
|
|
1428
|
+
TSERTittle = self.__genResourceName('tser', testsuiteName)
|
|
1343
1429
|
testsuiteURL = self.integrationURL('testsuite', testsuiteID)
|
|
1344
1430
|
testplanURL = self.integrationURL('testplan', testplanID)
|
|
1345
1431
|
testerURL = self.userURL(self.userID)
|
|
@@ -1376,7 +1462,7 @@ Return testsuite execution record (TSER) template from provided configuration na
|
|
|
1376
1462
|
|
|
1377
1463
|
def createTestsuiteResultTemplate(self, testsuiteID, testsuiteName, TSERID,
|
|
1378
1464
|
lTCER, lTCResults, resultState, startTime='',
|
|
1379
|
-
endTime='', duration='', sOwnerID=''):
|
|
1465
|
+
endTime='', duration='', sOwnerID='', buildrecordID=''):
|
|
1380
1466
|
"""
|
|
1381
1467
|
Return testsuite execution result template from provided configuration name.
|
|
1382
1468
|
|
|
@@ -1450,7 +1536,7 @@ Return testsuite execution result template from provided configuration name.
|
|
|
1450
1536
|
prefixState = 'com.ibm.rqm.execution.common.state.'
|
|
1451
1537
|
|
|
1452
1538
|
# prepare required data for template
|
|
1453
|
-
resultTittle = '
|
|
1539
|
+
resultTittle = self.__genResourceName('suiteresult', testsuiteName)
|
|
1454
1540
|
testsuiteURL = self.integrationURL('testsuite', testsuiteID)
|
|
1455
1541
|
TSERURL = self.integrationURL('suiteexecutionrecord', TSERID)
|
|
1456
1542
|
testerURL = self.userURL(self.userID)
|
|
@@ -1495,7 +1581,7 @@ Return testsuite execution result template from provided configuration name.
|
|
|
1495
1581
|
oState.text = prefixState + 'inconclusive'
|
|
1496
1582
|
if resultState.lower() in self.RESULT_STATES:
|
|
1497
1583
|
oState.text = prefixState +resultState.lower()
|
|
1498
|
-
|
|
1584
|
+
|
|
1499
1585
|
for idx, sTCER in enumerate(lTCER):
|
|
1500
1586
|
sTCERURL = self.integrationURL('executionworkitem', sTCER)
|
|
1501
1587
|
oSuiteElem = etree.Element('{http://jazz.net/xmlns/alm/qm/v0.1/tsl/v0.1/}suiteelement', nsmap=nsmap)
|
|
@@ -1513,6 +1599,12 @@ Return testsuite execution result template from provided configuration name.
|
|
|
1513
1599
|
oExecutionResult.set('href', sTCResultURL)
|
|
1514
1600
|
root.append(oExecutionResult)
|
|
1515
1601
|
|
|
1602
|
+
if buildrecordID:
|
|
1603
|
+
oBuildRecord = etree.Element('{http://jazz.net/xmlns/alm/qm/v0.1/}buildrecord', nsmap=nsmap)
|
|
1604
|
+
buildrecordURL = self.integrationURL('buildrecord', buildrecordID)
|
|
1605
|
+
oBuildRecord.set('href', buildrecordURL)
|
|
1606
|
+
root.append(oBuildRecord)
|
|
1607
|
+
|
|
1516
1608
|
# return xml template as string
|
|
1517
1609
|
sTSResultxml = etree.tostring(oTree)
|
|
1518
1610
|
return sTSResultxml
|
|
@@ -1576,7 +1668,7 @@ Return testcase template from provided information.
|
|
|
1576
1668
|
oOwner = oTree.find('ns6:owner', nsmap)
|
|
1577
1669
|
|
|
1578
1670
|
# change nodes's data
|
|
1579
|
-
oTittle.text = testsuiteName
|
|
1671
|
+
oTittle.text = self.__genResourceName('testsuite', testsuiteName)
|
|
1580
1672
|
oDescription.text = sDescription
|
|
1581
1673
|
|
|
1582
1674
|
# Incase not specify owner in template or input data, set it as provided user in cli
|
|
@@ -1774,7 +1866,6 @@ Create new configuration - test environment.
|
|
|
1774
1866
|
"""
|
|
1775
1867
|
returnObj = {'success' : False, 'id': None, 'message': '', 'status_code': ''}
|
|
1776
1868
|
# check existing build record in this executioon
|
|
1777
|
-
sConfID = ''
|
|
1778
1869
|
if (sConfigurationName not in self.dConfiguation.values()) or forceCreate:
|
|
1779
1870
|
sConfTemplate = self.createConfigurationTemplate(sConfigurationName)
|
|
1780
1871
|
returnObj = self.createResource('configuration', sConfTemplate)
|
|
@@ -1977,7 +2068,7 @@ Add testsuite ID to provided testplan ID
|
|
|
1977
2068
|
|
|
1978
2069
|
Testsuite to be linked with given testplan.
|
|
1979
2070
|
|
|
1980
|
-
If not provide, `testsuite
|
|
2071
|
+
If not provide, `testsuite.id` value will be used as id of testsuite.
|
|
1981
2072
|
|
|
1982
2073
|
**Returns:**
|
|
1983
2074
|
|
|
@@ -1999,7 +2090,7 @@ Add testsuite ID to provided testplan ID
|
|
|
1999
2090
|
"""
|
|
2000
2091
|
returnObj = {'success' : False, 'message': ''}
|
|
2001
2092
|
if testsuiteID == None:
|
|
2002
|
-
testsuiteID = self.testsuite
|
|
2093
|
+
testsuiteID = self.testsuite.id
|
|
2003
2094
|
if testsuiteID:
|
|
2004
2095
|
resTestplanData = self.getResourceByID('testplan', testplanID)
|
|
2005
2096
|
oTree = get_xml_tree(BytesIO(str(resTestplanData.text).encode()),bdtd_validation=False)
|
|
Binary file
|
{robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/robotlog2rqm.py
RENAMED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
#
|
|
28
28
|
# ******************************************************************************
|
|
29
29
|
|
|
30
|
+
import json
|
|
30
31
|
import re
|
|
31
32
|
import argparse
|
|
32
33
|
import os
|
|
@@ -64,6 +65,15 @@ DEFAULT_METADATA = {
|
|
|
64
65
|
"team-area" : "",
|
|
65
66
|
}
|
|
66
67
|
|
|
68
|
+
NAMING_CONVENTION_SCHEMA = {
|
|
69
|
+
"testcase" : str,
|
|
70
|
+
"tcer" : str,
|
|
71
|
+
"testresult" : str,
|
|
72
|
+
"testsuite" : str,
|
|
73
|
+
"tser" : str,
|
|
74
|
+
"suiteresult" : str
|
|
75
|
+
}
|
|
76
|
+
|
|
67
77
|
#
|
|
68
78
|
# Logger class
|
|
69
79
|
#
|
|
@@ -281,6 +291,108 @@ Convert time string to datetime.
|
|
|
281
291
|
dt=datetime.datetime(tp[0],tp[1],tp[2],tp[3],tp[4],tp[5],tp[6])
|
|
282
292
|
return dt
|
|
283
293
|
|
|
294
|
+
def process_config_file(path_file):
|
|
295
|
+
"""
|
|
296
|
+
Parse and validate content of configuration file
|
|
297
|
+
|
|
298
|
+
**Arguments:**
|
|
299
|
+
|
|
300
|
+
* ``path_file``
|
|
301
|
+
|
|
302
|
+
/ *Condition*: required / *Type*: str /
|
|
303
|
+
|
|
304
|
+
Path to the configuration json file.
|
|
305
|
+
|
|
306
|
+
**Returns:**
|
|
307
|
+
|
|
308
|
+
* ``dConfig``
|
|
309
|
+
|
|
310
|
+
/ *Type*: dict /
|
|
311
|
+
|
|
312
|
+
Content of json file.
|
|
313
|
+
"""
|
|
314
|
+
with open(path_file, encoding='utf-8') as f:
|
|
315
|
+
try:
|
|
316
|
+
dConfig = json.load(f)
|
|
317
|
+
except Exception as reason:
|
|
318
|
+
Logger.log_error(f"Cannot parse the json file '{path_file}'. Reason: {reason}",
|
|
319
|
+
fatal_error=True)
|
|
320
|
+
|
|
321
|
+
if not is_valid_config(dConfig, bExitOnFail=False):
|
|
322
|
+
Logger.log_error(f"Error in naming configuration file '{path_file}'.",
|
|
323
|
+
fatal_error=True)
|
|
324
|
+
return dConfig
|
|
325
|
+
|
|
326
|
+
def is_valid_config(dConfig, dSchema=NAMING_CONVENTION_SCHEMA, bExitOnFail=True):
|
|
327
|
+
"""
|
|
328
|
+
Validate the json configuration base on given schema.
|
|
329
|
+
|
|
330
|
+
Default schema supports below information:
|
|
331
|
+
|
|
332
|
+
.. code:: python
|
|
333
|
+
|
|
334
|
+
NAMING_CONVENTION_SCHEMA = {
|
|
335
|
+
"testcase" : str,
|
|
336
|
+
"tcer" : str,
|
|
337
|
+
"testresult" : str,
|
|
338
|
+
"testsuite" : str,
|
|
339
|
+
"tser" : str,
|
|
340
|
+
"suiteresult" : str
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
**Arguments:**
|
|
344
|
+
|
|
345
|
+
* ``dConfig``
|
|
346
|
+
|
|
347
|
+
/ *Condition*: required / *Type*: dict /
|
|
348
|
+
|
|
349
|
+
Json configuration object to be verified.
|
|
350
|
+
|
|
351
|
+
* ``dSchema``
|
|
352
|
+
|
|
353
|
+
/ *Condition*: optional / *Type*: dict / *Default*: CONFIG_SCHEMA /
|
|
354
|
+
|
|
355
|
+
Schema for the validation.
|
|
356
|
+
|
|
357
|
+
* ``bExitOnFail``
|
|
358
|
+
|
|
359
|
+
/ *Condition*: optional / *Type*: bool / *Default*: True /
|
|
360
|
+
|
|
361
|
+
If True, exit tool in case the validation is fail.
|
|
362
|
+
|
|
363
|
+
**Returns:**
|
|
364
|
+
|
|
365
|
+
* ``bValid``
|
|
366
|
+
|
|
367
|
+
/ *Type*: bool /
|
|
368
|
+
|
|
369
|
+
True if the given json configuration data is valid.
|
|
370
|
+
"""
|
|
371
|
+
bValid = True
|
|
372
|
+
for key in dConfig:
|
|
373
|
+
if key in dSchema.keys():
|
|
374
|
+
if type(dConfig[key]) != dSchema[key]:
|
|
375
|
+
bValid = False
|
|
376
|
+
Logger.log_error(f"Value of '{key}' has wrong type '{type(dConfig[key])}' in configuration json file.",
|
|
377
|
+
fatal_error=bExitOnFail)
|
|
378
|
+
break
|
|
379
|
+
|
|
380
|
+
# TESTCASE_NAME is not available for non-testcase relevant resources
|
|
381
|
+
# TESTSUITE_NAME is not available for `buildrecord` and `configuration` resources
|
|
382
|
+
# Warning user for using wrong place holders
|
|
383
|
+
oMatch = re.search(".*\{(.*)\}.*", dConfig[key])
|
|
384
|
+
if oMatch:
|
|
385
|
+
if oMatch.group(1) not in CRQMClient.SUPPORTED_PLACEHOLDER:
|
|
386
|
+
Logger.log_warning(f"Place holder '{{{oMatch.group(1)}}}' is not supported, it will not be replaced when generating {key} resource")
|
|
387
|
+
|
|
388
|
+
else:
|
|
389
|
+
bValid = False
|
|
390
|
+
Logger.log_error(f"resource '{key}' is not supported in naming conventions json file.",
|
|
391
|
+
fatal_error=bExitOnFail)
|
|
392
|
+
break
|
|
393
|
+
|
|
394
|
+
return bValid
|
|
395
|
+
|
|
284
396
|
def __process_commandline():
|
|
285
397
|
"""
|
|
286
398
|
Process provided argument(s) from command line.
|
|
@@ -296,6 +408,8 @@ Avalable arguments in command line:
|
|
|
296
408
|
- `--testsuite` : RQM testsuite ID. If value is 'new', then create a new testsuite for this execution.
|
|
297
409
|
- `--recursive` : if True, then the path is searched recursively for log files to be imported.
|
|
298
410
|
- `--createmissing` : if True, then all testcases without tcid are created when importing.
|
|
411
|
+
- `--updatetestcase` : if set, then testcase information on RQM will be updated bases on robot testfile.
|
|
412
|
+
- `--naming_config` : configuration json file for naming conventions when creating RQM resources.
|
|
299
413
|
- `--dryrun` : if True, then verify all input arguments (includes RQM authentication) and show what would be done.
|
|
300
414
|
- `--stream` : project stream. Note, requires Configuration Management (CM) to be enabled for the project area.
|
|
301
415
|
- `--baseline` : project baseline. Note, requires Configuration Management (CM), or Baselines Only to be enabled for the project area.
|
|
@@ -327,7 +441,7 @@ Avalable arguments in command line:
|
|
|
327
441
|
cmdParser.add_argument('password', type=str, help='password for RQM login.')
|
|
328
442
|
cmdParser.add_argument('testplan', type=str,
|
|
329
443
|
help='testplan ID for this execution.')
|
|
330
|
-
cmdParser.add_argument('--testsuite', type=str,
|
|
444
|
+
cmdParser.add_argument('--testsuite', type=str,
|
|
331
445
|
help="testsuite ID for this execution. If 'new', then create a new testsuite for this execution.")
|
|
332
446
|
cmdParser.add_argument('--recursive',action="store_true",
|
|
333
447
|
help='if set, then the path is searched recursively for log files to be imported.')
|
|
@@ -335,6 +449,8 @@ Avalable arguments in command line:
|
|
|
335
449
|
help='if set, then all testcases without tcid are created when importing.')
|
|
336
450
|
cmdParser.add_argument('--updatetestcase', action="store_true",
|
|
337
451
|
help='if set, then testcase information on RQM will be updated bases on robot testfile.')
|
|
452
|
+
cmdParser.add_argument('--naming_config', type=str,
|
|
453
|
+
help='configuration json file for naming conventions when creating RQM resources.')
|
|
338
454
|
cmdParser.add_argument('--dryrun',action="store_true",
|
|
339
455
|
help='if set, then verify all input arguments (includes RQM authentication) and show what would be done.')
|
|
340
456
|
cmdParser.add_argument('--stream', type=str,
|
|
@@ -507,9 +623,9 @@ Process robot test for importing to RQM.
|
|
|
507
623
|
_tc_cmpt = metadata_info['component']
|
|
508
624
|
_tc_team = metadata_info['team-area']
|
|
509
625
|
# from RQMClient
|
|
510
|
-
_tc_testplan_id = RQMClient.testplan
|
|
511
|
-
_tc_config_id = RQMClient.configuration
|
|
512
|
-
_tc_build_id = RQMClient.build
|
|
626
|
+
_tc_testplan_id = RQMClient.testplan.id
|
|
627
|
+
_tc_config_id = RQMClient.configuration.id
|
|
628
|
+
_tc_build_id = RQMClient.build.id
|
|
513
629
|
_tc_createmissing = RQMClient.createmissing
|
|
514
630
|
_tc_update = RQMClient.updatetestcase
|
|
515
631
|
# from robot result object
|
|
@@ -628,7 +744,7 @@ Process robot test for importing to RQM.
|
|
|
628
744
|
# Append lTestcaseIDs (for linking testplan/testsuite)
|
|
629
745
|
if _tc_id not in RQMClient.lTestcaseIDs:
|
|
630
746
|
RQMClient.lTestcaseIDs.append(_tc_id)
|
|
631
|
-
|
|
747
|
+
|
|
632
748
|
# Collect starttime and endtime for testsuite log creation
|
|
633
749
|
RQMClient.lStartTimes.append(_tc_start_time)
|
|
634
750
|
RQMClient.lEndTimes.append(_tc_end_time)
|
|
@@ -663,6 +779,7 @@ Flow to import Robot results to RQM:
|
|
|
663
779
|
* `recursive` : if True, then the path is searched recursively for log files to be imported.
|
|
664
780
|
* `createmissing` : if True, then all testcases without tcid are created when importing.
|
|
665
781
|
* `updatetestcase` : if True, then testcases information on RQM will be updated bases on robot testfile.
|
|
782
|
+
* `naming_config` : configuration json file for naming conventions when creating RQM resources.
|
|
666
783
|
* `dryrun` : if True, then verify all input arguments (includes RQM authentication) and show what would be done.
|
|
667
784
|
* `stream` : project stream. Note, requires Configuration Management (CM) to be enabled for the project area.
|
|
668
785
|
* `baseline` : project baseline. Note, requires Configuration Management (CM), or Baselines Only to be enabled for the project area.
|
|
@@ -710,6 +827,15 @@ Flow to import Robot results to RQM:
|
|
|
710
827
|
result = ExecutionResult(*sources)
|
|
711
828
|
result.configure()
|
|
712
829
|
|
|
830
|
+
# verify given configuration file
|
|
831
|
+
dNamingConvention = None
|
|
832
|
+
if args.naming_config != None:
|
|
833
|
+
if os.path.isfile(args.naming_config):
|
|
834
|
+
dNamingConvention = process_config_file(args.naming_config)
|
|
835
|
+
else:
|
|
836
|
+
Logger.log_error(f"The given naming configuration file is not existing: '{args.naming_config}'",
|
|
837
|
+
fatal_error=True)
|
|
838
|
+
|
|
713
839
|
# 3. Login Rational Quality Management (RQM)
|
|
714
840
|
RQMClient = CRQMClient(args.user, args.password, args.project, args.host)
|
|
715
841
|
try:
|
|
@@ -718,7 +844,7 @@ Flow to import Robot results to RQM:
|
|
|
718
844
|
Logger.log()
|
|
719
845
|
Logger.log(f"Login RQM as user '{args.user}' successfully!")
|
|
720
846
|
else:
|
|
721
|
-
Logger.log_error("Could not login to RQM: '
|
|
847
|
+
Logger.log_error("Could not login to RQM: 'Unknown reason'.")
|
|
722
848
|
except Exception as reason:
|
|
723
849
|
Logger.log_error(f"Could not login to RQM: '{str(reason)}'.")
|
|
724
850
|
|
|
@@ -734,8 +860,9 @@ Flow to import Robot results to RQM:
|
|
|
734
860
|
metadata_info['version_sw'] = None
|
|
735
861
|
metadata_info['project'] = None
|
|
736
862
|
RQMClient.config(args.testplan, metadata_info['version_sw'],
|
|
737
|
-
metadata_info['project'], args.createmissing, args.updatetestcase,
|
|
738
|
-
args.testsuite, stream=args.stream, baseline=args.baseline
|
|
863
|
+
metadata_info['project'], args.createmissing, args.updatetestcase,
|
|
864
|
+
args.testsuite, stream=args.stream, baseline=args.baseline,
|
|
865
|
+
naming_convention=dNamingConvention)
|
|
739
866
|
|
|
740
867
|
if args.testsuite == "new":
|
|
741
868
|
# Create new testsuite
|
|
@@ -749,18 +876,18 @@ Flow to import Robot results to RQM:
|
|
|
749
876
|
if res_testsuite['success']:
|
|
750
877
|
_ts_id = res_testsuite['id']
|
|
751
878
|
Logger.log(f"Create testsuite '{result.suite.name}' with ID '{_ts_id}' successfully!")
|
|
752
|
-
RQMClient.testsuite
|
|
753
|
-
RQMClient.testsuite
|
|
879
|
+
RQMClient.testsuite.id = _ts_id
|
|
880
|
+
RQMClient.testsuite.name = result.suite.name
|
|
754
881
|
else:
|
|
755
882
|
Logger.log_error(f"Create testsuite '{result.suite.name}' failed. Reason: {res_testsuite['message']}", fatal_error=True)
|
|
756
883
|
|
|
757
884
|
# Process suite for importing
|
|
758
885
|
process_suite(RQMClient, result.suite)
|
|
759
886
|
|
|
760
|
-
if RQMClient.testsuite
|
|
887
|
+
if RQMClient.testsuite.id:
|
|
761
888
|
if not args.dryrun:
|
|
762
889
|
# Create testsuite execution record if requires
|
|
763
|
-
testsuite_record_data = RQMClient.createTSERTemplate(RQMClient.testsuite
|
|
890
|
+
testsuite_record_data = RQMClient.createTSERTemplate(RQMClient.testsuite.id, RQMClient.testsuite.name, args.testplan, RQMClient.configuration.id)
|
|
764
891
|
res_TSER = RQMClient.createResource('suiteexecutionrecord', testsuite_record_data)
|
|
765
892
|
sTSERID = res_TSER['id']
|
|
766
893
|
Logger.log()
|
|
@@ -769,20 +896,21 @@ Flow to import Robot results to RQM:
|
|
|
769
896
|
elif (res_TSER['status_code'] == 303 or res_TSER['status_code'] == 200) and res_TSER['id'] != '':
|
|
770
897
|
### incase executionworkitem is existing, cannot create new one
|
|
771
898
|
### Use the existing ID for new result
|
|
772
|
-
Logger.log_warning(f"TSER for testsuite {RQMClient.testsuite
|
|
899
|
+
Logger.log_warning(f"TSER for testsuite {RQMClient.testsuite.id} is existing.\nAdd this execution result to existing TSER id: {sTSERID}")
|
|
773
900
|
else:
|
|
774
901
|
Logger.log_error(f"Create TSER failed, {res_TSER['message']}")
|
|
775
902
|
|
|
776
903
|
# Create new testsuite result and link all TCERs
|
|
777
|
-
testsuite_result_data = RQMClient.createTestsuiteResultTemplate(RQMClient.testsuite
|
|
778
|
-
RQMClient.testsuite
|
|
904
|
+
testsuite_result_data = RQMClient.createTestsuiteResultTemplate(RQMClient.testsuite.id,
|
|
905
|
+
RQMClient.testsuite.name,
|
|
779
906
|
sTSERID,
|
|
780
907
|
RQMClient.lTCERIDs,
|
|
781
908
|
RQMClient.lTCResultIDs,
|
|
782
|
-
DRESULT_MAPPING[result.suite.status]
|
|
909
|
+
DRESULT_MAPPING[result.suite.status],
|
|
910
|
+
buildrecordID=RQMClient.build.id
|
|
783
911
|
)
|
|
784
912
|
res_TSLog = RQMClient.createResource('testsuitelog', testsuite_result_data)
|
|
785
|
-
sSuiteResultID = res_TSLog['id']
|
|
913
|
+
sSuiteResultID = res_TSLog['id']
|
|
786
914
|
if res_TSLog['success']:
|
|
787
915
|
Logger.log(f"Created testsuite result with id {sSuiteResultID} successfully.", indent=2)
|
|
788
916
|
else:
|
|
@@ -793,15 +921,15 @@ Flow to import Robot results to RQM:
|
|
|
793
921
|
|
|
794
922
|
# Link all imported testcase ID(s) with testsuite
|
|
795
923
|
try:
|
|
796
|
-
RQMClient.linkListTestcase2Testsuite(RQMClient.testsuite
|
|
797
|
-
Logger.log(f"Link all imported test cases with testsuite {RQMClient.testsuite
|
|
924
|
+
RQMClient.linkListTestcase2Testsuite(RQMClient.testsuite.id)
|
|
925
|
+
Logger.log(f"Link all imported test cases with testsuite {RQMClient.testsuite.id} successfully.")
|
|
798
926
|
except Exception as reason:
|
|
799
927
|
Logger.log_error(f"Link all imported test cases with testsuite failed.\nReason: {reason}", fatal_error=True)
|
|
800
928
|
|
|
801
929
|
# Add testsuite to given testplan
|
|
802
930
|
try:
|
|
803
931
|
RQMClient.addTestsuite2Testplan(args.testplan)
|
|
804
|
-
Logger.log(f"Add testsuite {RQMClient.testsuite
|
|
932
|
+
Logger.log(f"Add testsuite {RQMClient.testsuite.id} to testplan {args.testplan} successfully.")
|
|
805
933
|
except Exception as reason:
|
|
806
934
|
Logger.log_error(f"Add testsuite to testplan failed.\nReason: {reason}", fatal_error=True)
|
|
807
935
|
|
|
@@ -812,7 +940,7 @@ Flow to import Robot results to RQM:
|
|
|
812
940
|
Logger.log(f"Link all imported test cases with testplan {args.testplan} successfully.")
|
|
813
941
|
except Exception as reason:
|
|
814
942
|
Logger.log_error(f"Link all imported test cases with testplan failed.\nReason: {reason}", fatal_error=True)
|
|
815
|
-
|
|
943
|
+
|
|
816
944
|
# Update testcase(s) with generated ID(s)
|
|
817
945
|
# Under developing
|
|
818
946
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: robotframework-robotlog2rqm
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.2
|
|
4
4
|
Summary: Imports robot result(s) to IBM Rational Quality Manager (RQM)
|
|
5
5
|
Home-page: https://github.com/test-fullautomation/robotframework-robotlog2rqm
|
|
6
6
|
Author: Tran Duy Ngoan
|
|
@@ -17,8 +17,7 @@ Requires-Python: >=3.0
|
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
|
19
19
|
|
|
20
|
-
RobotLog2RQM Description
|
|
21
|
-
========================
|
|
20
|
+
# RobotLog2RQM Description
|
|
22
21
|
|
|
23
22
|
The Python package **RobotLog2RQM** provides ability to import [Robot
|
|
24
23
|
Framework test
|
|
@@ -38,14 +37,13 @@ Manager](https://www.ibm.com/support/knowledgecenter/SSYMRC_6.0.2/com.ibm.ration
|
|
|
38
37
|
**RobotLog2RQM** tool is operating system independent and only works
|
|
39
38
|
with Python 3.
|
|
40
39
|
|
|
41
|
-
How to install
|
|
42
|
-
--------------
|
|
40
|
+
## How to install
|
|
43
41
|
|
|
44
42
|
**RobotLog2RQM** can be installed in two different ways.
|
|
45
43
|
|
|
46
44
|
1. Installation via PyPi (recommended for users)
|
|
47
45
|
|
|
48
|
-
```
|
|
46
|
+
```
|
|
49
47
|
pip install RobotLog2RQM
|
|
50
48
|
```
|
|
51
49
|
|
|
@@ -57,7 +55,7 @@ How to install
|
|
|
57
55
|
- Clone the **robotframework-robotlog2rqm** repository to your
|
|
58
56
|
machine.
|
|
59
57
|
|
|
60
|
-
```
|
|
58
|
+
```
|
|
61
59
|
git clone https://github.com/test-fullautomation/robotframework-robotlog2rqm.git
|
|
62
60
|
```
|
|
63
61
|
|
|
@@ -72,7 +70,7 @@ How to install
|
|
|
72
70
|
packages you can find in the file `requirements.txt` in the
|
|
73
71
|
repository root folder. Use pip to install them:
|
|
74
72
|
|
|
75
|
-
```
|
|
73
|
+
```
|
|
76
74
|
pip install -r ./requirements.txt
|
|
77
75
|
```
|
|
78
76
|
|
|
@@ -91,7 +89,7 @@ How to install
|
|
|
91
89
|
to find **LaTeX**. This is defined in the **GenPackageDoc**
|
|
92
90
|
configuration file
|
|
93
91
|
|
|
94
|
-
```
|
|
92
|
+
```
|
|
95
93
|
packagedoc\packagedoc_config.json
|
|
96
94
|
```
|
|
97
95
|
|
|
@@ -103,7 +101,7 @@ How to install
|
|
|
103
101
|
|
|
104
102
|
- Use the following command to install **RobotLog2RQM**:
|
|
105
103
|
|
|
106
|
-
```
|
|
104
|
+
```
|
|
107
105
|
python setup.py install
|
|
108
106
|
```
|
|
109
107
|
|
|
@@ -114,8 +112,7 @@ be available (under *Scripts* folder of Python on Windows and
|
|
|
114
112
|
In case above location is added to **PATH** environment variable then
|
|
115
113
|
you can run it directly as operation system\'s command.
|
|
116
114
|
|
|
117
|
-
How to use
|
|
118
|
-
----------
|
|
115
|
+
## How to use
|
|
119
116
|
|
|
120
117
|
**RobotLog2RQM** tool requires the Robot Framework `output.xml` result
|
|
121
118
|
file(s) which will be imported, RQM information(e.g. host url, project,
|
|
@@ -219,8 +216,7 @@ cases and their results are reflected on RQM, please refer to
|
|
|
219
216
|
[RobotLog2RQM tool's
|
|
220
217
|
Documentation](https://github.com/test-fullautomation/robotframework-robotlog2rqm/blob/develop/RobotLog2RQM/RobotLog2RQM.pdf).
|
|
221
218
|
|
|
222
|
-
Feedback
|
|
223
|
-
--------
|
|
219
|
+
## Feedback
|
|
224
220
|
|
|
225
221
|
To give us a feedback, you can send an email to [Thomas
|
|
226
222
|
Pollerspöck](mailto:Thomas.Pollerspoeck@de.bosch.com).
|
|
@@ -228,15 +224,13 @@ Pollerspöck](mailto:Thomas.Pollerspoeck@de.bosch.com).
|
|
|
228
224
|
In case you want to report a bug or request any interesting feature,
|
|
229
225
|
please don\'t hesitate to raise a ticket.
|
|
230
226
|
|
|
231
|
-
Maintainers
|
|
232
|
-
-----------
|
|
227
|
+
## Maintainers
|
|
233
228
|
|
|
234
229
|
[Thomas Pollerspöck](mailto:Thomas.Pollerspoeck@de.bosch.com)
|
|
235
230
|
|
|
236
231
|
[Tran Duy Ngoan](mailto:Ngoan.TranDuy@vn.bosch.com)
|
|
237
232
|
|
|
238
|
-
Contributors
|
|
239
|
-
------------
|
|
233
|
+
## Contributors
|
|
240
234
|
|
|
241
235
|
[Nguyen Huynh Tri Cuong](mailto:Cuong.NguyenHuynhTri@vn.bosch.com)
|
|
242
236
|
|
|
@@ -246,8 +240,7 @@ Contributors
|
|
|
246
240
|
|
|
247
241
|
[Holger Queckenstedt](mailto:Holger.Queckenstedt@de.bosch.com)
|
|
248
242
|
|
|
249
|
-
License
|
|
250
|
-
-------
|
|
243
|
+
## License
|
|
251
244
|
|
|
252
245
|
Copyright 2020-2024 Robert Bosch GmbH
|
|
253
246
|
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/__init__.py
RENAMED
|
File without changes
|
{robotframework-robotlog2rqm-1.4.0 → robotframework-robotlog2rqm-1.4.2}/RobotLog2RQM/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|