robotframework-robotlog2rqm 1.2.3__tar.gz → 1.4.0__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.2.3 → robotframework-robotlog2rqm-1.4.0}/PKG-INFO +29 -22
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/README.rst +28 -21
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/RobotLog2RQM/CRQM.py +198 -4
- robotframework-robotlog2rqm-1.4.0/RobotLog2RQM/RQM_templates/testsuite.xml +27 -0
- robotframework-robotlog2rqm-1.4.0/RobotLog2RQM/RobotLog2RQM.pdf +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/RobotLog2RQM/robotlog2rqm.py +149 -29
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/RobotLog2RQM/version.py +2 -2
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/robotframework_robotlog2rqm.egg-info/PKG-INFO +29 -22
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/robotframework_robotlog2rqm.egg-info/SOURCES.txt +1 -0
- robotframework-robotlog2rqm-1.2.3/RobotLog2RQM/RobotLog2RQM.pdf +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/LICENSE +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/RobotLog2RQM/RQM_templates/buildrecord.xml +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/RobotLog2RQM/RQM_templates/configuration.xml +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/RobotLog2RQM/RQM_templates/executionresult.xml +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/RobotLog2RQM/RQM_templates/executionworkitem.xml +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/RobotLog2RQM/RQM_templates/suiteexecutionrecord.xml +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/RobotLog2RQM/RQM_templates/testcase.xml +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/RobotLog2RQM/RQM_templates/testsuitelog.xml +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/RobotLog2RQM/__init__.py +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/RobotLog2RQM/__main__.py +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/robotframework_robotlog2rqm.egg-info/dependency_links.txt +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/robotframework_robotlog2rqm.egg-info/entry_points.txt +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/robotframework_robotlog2rqm.egg-info/requires.txt +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/robotframework_robotlog2rqm.egg-info/top_level.txt +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/setup.cfg +0 -0
- {robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: robotframework-robotlog2rqm
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
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
|
|
@@ -128,33 +128,40 @@ Use below command to get tools\'s usage:
|
|
|
128
128
|
|
|
129
129
|
The usage should be showed as below:
|
|
130
130
|
|
|
131
|
-
usage: RobotLog2RQM (RobotXMLResult to RQM importer) [-h] [-v] [--recursive]
|
|
132
|
-
|
|
133
|
-
|
|
131
|
+
usage: RobotLog2RQM (RobotXMLResult to RQM importer) [-h] [-v] [--testsuite TESTSUITE] [--recursive]
|
|
132
|
+
[--createmissing] [--updatetestcase] [--dryrun] [--stream STREAM] [--baseline BASELINE]
|
|
133
|
+
resultxmlfile host project user password testplan
|
|
134
134
|
|
|
135
|
-
RobotLog2RQM imports XML result files (default: output.xml) generated by the
|
|
135
|
+
RobotLog2RQM imports XML result files (default: output.xml) generated by the
|
|
136
136
|
Robot Framework into an IBM Rational Quality Manager.
|
|
137
137
|
|
|
138
138
|
positional arguments:
|
|
139
|
-
resultxmlfile
|
|
140
|
-
|
|
141
|
-
host
|
|
142
|
-
project
|
|
143
|
-
user
|
|
144
|
-
password
|
|
145
|
-
testplan
|
|
139
|
+
resultxmlfile absolute or relative path to the xml result file
|
|
140
|
+
or directory of result files to be imported.
|
|
141
|
+
host RQM host url.
|
|
142
|
+
project project on RQM.
|
|
143
|
+
user user for RQM login.
|
|
144
|
+
password password for RQM login.
|
|
145
|
+
testplan testplan ID for this execution.
|
|
146
146
|
|
|
147
147
|
optional arguments:
|
|
148
|
-
-h, --help
|
|
149
|
-
-v, --version
|
|
150
|
-
--
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
148
|
+
-h, --help show this help message and exit
|
|
149
|
+
-v, --version Version of the RobotLog2RQM importer.
|
|
150
|
+
--testsuite TESTSUITE
|
|
151
|
+
testsuite ID for this execution. If 'new', then create a new
|
|
152
|
+
testsuite for this execution.
|
|
153
|
+
--recursive if set, then the path is searched recursively for
|
|
154
|
+
log files to be imported.
|
|
155
|
+
--createmissing if set, then all testcases without tcid are created
|
|
156
|
+
when importing.
|
|
157
|
+
--updatetestcase if set, then testcase information on RQM will be updated
|
|
158
|
+
bases on robot testfile.
|
|
159
|
+
--dryrun if set, then verify all input arguments
|
|
160
|
+
(includes RQM authentication) and show what would be done.
|
|
161
|
+
--stream STREAM project stream. Note, requires Configuration Management (CM)
|
|
162
|
+
to be enabled for the project area.
|
|
163
|
+
--baseline BASELINE project baseline. Note, requires Configuration Management (CM),
|
|
164
|
+
or Baselines Only to be enabled for the project area.
|
|
158
165
|
|
|
159
166
|
The below command is simple usage witth all required arguments to import
|
|
160
167
|
Robot Framework results into RQM:
|
|
@@ -112,33 +112,40 @@ The usage should be showed as below:
|
|
|
112
112
|
|
|
113
113
|
::
|
|
114
114
|
|
|
115
|
-
usage: RobotLog2RQM (RobotXMLResult to RQM importer) [-h] [-v] [--recursive]
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
usage: RobotLog2RQM (RobotXMLResult to RQM importer) [-h] [-v] [--testsuite TESTSUITE] [--recursive]
|
|
116
|
+
[--createmissing] [--updatetestcase] [--dryrun] [--stream STREAM] [--baseline BASELINE]
|
|
117
|
+
resultxmlfile host project user password testplan
|
|
118
118
|
|
|
119
|
-
RobotLog2RQM imports XML result files (default: output.xml) generated by the
|
|
119
|
+
RobotLog2RQM imports XML result files (default: output.xml) generated by the
|
|
120
120
|
Robot Framework into an IBM Rational Quality Manager.
|
|
121
121
|
|
|
122
122
|
positional arguments:
|
|
123
|
-
resultxmlfile
|
|
124
|
-
|
|
125
|
-
host
|
|
126
|
-
project
|
|
127
|
-
user
|
|
128
|
-
password
|
|
129
|
-
testplan
|
|
123
|
+
resultxmlfile absolute or relative path to the xml result file
|
|
124
|
+
or directory of result files to be imported.
|
|
125
|
+
host RQM host url.
|
|
126
|
+
project project on RQM.
|
|
127
|
+
user user for RQM login.
|
|
128
|
+
password password for RQM login.
|
|
129
|
+
testplan testplan ID for this execution.
|
|
130
130
|
|
|
131
131
|
optional arguments:
|
|
132
|
-
-h, --help
|
|
133
|
-
-v, --version
|
|
134
|
-
--
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
132
|
+
-h, --help show this help message and exit
|
|
133
|
+
-v, --version Version of the RobotLog2RQM importer.
|
|
134
|
+
--testsuite TESTSUITE
|
|
135
|
+
testsuite ID for this execution. If 'new', then create a new
|
|
136
|
+
testsuite for this execution.
|
|
137
|
+
--recursive if set, then the path is searched recursively for
|
|
138
|
+
log files to be imported.
|
|
139
|
+
--createmissing if set, then all testcases without tcid are created
|
|
140
|
+
when importing.
|
|
141
|
+
--updatetestcase if set, then testcase information on RQM will be updated
|
|
142
|
+
bases on robot testfile.
|
|
143
|
+
--dryrun if set, then verify all input arguments
|
|
144
|
+
(includes RQM authentication) and show what would be done.
|
|
145
|
+
--stream STREAM project stream. Note, requires Configuration Management (CM)
|
|
146
|
+
to be enabled for the project area.
|
|
147
|
+
--baseline BASELINE project baseline. Note, requires Configuration Management (CM),
|
|
148
|
+
or Baselines Only to be enabled for the project area.
|
|
142
149
|
|
|
143
150
|
|
|
144
151
|
The below command is simple usage witth all required arguments to import
|
{robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/RobotLog2RQM/CRQM.py
RENAMED
|
@@ -195,7 +195,12 @@ Constructor of class ``CRQMClient``.
|
|
|
195
195
|
self.configuration = None
|
|
196
196
|
self.createmissing = None
|
|
197
197
|
self.updatetestcase= None
|
|
198
|
-
self.testsuite =
|
|
198
|
+
self.testsuite = {
|
|
199
|
+
"id": None,
|
|
200
|
+
"name": None
|
|
201
|
+
}
|
|
202
|
+
self.stream = None
|
|
203
|
+
self.baseline = None
|
|
199
204
|
|
|
200
205
|
def login(self):
|
|
201
206
|
"""
|
|
@@ -285,7 +290,8 @@ Disconnect from RQM.
|
|
|
285
290
|
self.session.close()
|
|
286
291
|
|
|
287
292
|
def config(self, plan_id, build_name=None, config_name=None,
|
|
288
|
-
createmissing=False, updatetestcase=False,suite_id=None
|
|
293
|
+
createmissing=False, updatetestcase=False, suite_id=None,
|
|
294
|
+
stream=None, baseline=None):
|
|
289
295
|
"""
|
|
290
296
|
Configure RQMClient with testplan ID, build, configuration, createmissing, ...
|
|
291
297
|
|
|
@@ -340,8 +346,45 @@ Configure RQMClient with testplan ID, build, configuration, createmissing, ...
|
|
|
340
346
|
try:
|
|
341
347
|
self.createmissing = createmissing
|
|
342
348
|
self.updatetestcase = updatetestcase
|
|
343
|
-
self.testsuite = suite_id
|
|
344
349
|
self.testplan = plan_id
|
|
350
|
+
self.testsuite['id'] = suite_id
|
|
351
|
+
|
|
352
|
+
# Add Configuration-Context header information due to given stream or baseline
|
|
353
|
+
if stream:
|
|
354
|
+
res = self.getAllByResource('stream')
|
|
355
|
+
if res['success']:
|
|
356
|
+
dStreams = res['data']
|
|
357
|
+
bFoundStream = False
|
|
358
|
+
for stream_id, stream_name in dStreams.items():
|
|
359
|
+
if stream_name == stream:
|
|
360
|
+
self.stream = stream_id
|
|
361
|
+
bFoundStream = True
|
|
362
|
+
self.headers['Configuration-Context'] = stream_id
|
|
363
|
+
self.session.headers = self.headers
|
|
364
|
+
break
|
|
365
|
+
|
|
366
|
+
if not bFoundStream:
|
|
367
|
+
raise Exception(f"Cannot found given stream '{stream}'")
|
|
368
|
+
else:
|
|
369
|
+
raise Exception("Get all streams failed. Reason: %s"%res['message'])
|
|
370
|
+
elif baseline:
|
|
371
|
+
res = self.getAllByResource('baseline')
|
|
372
|
+
if res['success']:
|
|
373
|
+
dBaselines = res['data']
|
|
374
|
+
bFoundBaseline = False
|
|
375
|
+
for baseline_id, baseline_name in dBaselines.items():
|
|
376
|
+
if baseline_name == baseline:
|
|
377
|
+
self.baseline = baseline_id
|
|
378
|
+
bFoundBaseline = True
|
|
379
|
+
self.headers['Configuration-Context'] = baseline_id
|
|
380
|
+
self.session.headers = self.headers
|
|
381
|
+
break
|
|
382
|
+
|
|
383
|
+
if not bFoundBaseline:
|
|
384
|
+
raise Exception(f"Cannot found given baseline '{baseline}'")
|
|
385
|
+
else:
|
|
386
|
+
raise Exception("Get all baselines failed. Reason: %s"%res['message'])
|
|
387
|
+
|
|
345
388
|
# Verify testplan ID
|
|
346
389
|
res_plan = self.getResourceByID('testplan', plan_id)
|
|
347
390
|
if res_plan.status_code != 200:
|
|
@@ -371,8 +414,17 @@ Configure RQMClient with testplan ID, build, configuration, createmissing, ...
|
|
|
371
414
|
raise Exception("Cannot create configuration '%s': %s"%
|
|
372
415
|
(config_name, res_conf['message']))
|
|
373
416
|
|
|
417
|
+
# Verify testsuite if given
|
|
418
|
+
if (suite_id != None) and (suite_id != "new"):
|
|
419
|
+
res_suite = self.getResourceByID('testsuite', suite_id)
|
|
420
|
+
if res_suite.status_code != 200:
|
|
421
|
+
raise Exception('Testsuite with ID %s is not existing!'%str(suite_id))
|
|
422
|
+
oTestsuite = get_xml_tree(BytesIO(str(res_suite.text).encode()), bdtd_validation=False)
|
|
423
|
+
self.testsuite['name'] = oTestsuite.find('ns4:title', oTestsuite.getroot().nsmap).text
|
|
424
|
+
|
|
374
425
|
# get all team-areas for testcase template
|
|
375
426
|
self.getAllTeamAreas()
|
|
427
|
+
|
|
376
428
|
|
|
377
429
|
except Exception as error:
|
|
378
430
|
raise Exception('Configure RQMClient failed: %s'%error)
|
|
@@ -1323,7 +1375,7 @@ Return testsuite execution record (TSER) template from provided configuration na
|
|
|
1323
1375
|
return sTSxml
|
|
1324
1376
|
|
|
1325
1377
|
def createTestsuiteResultTemplate(self, testsuiteID, testsuiteName, TSERID,
|
|
1326
|
-
lTCER, lTCResults, startTime='',
|
|
1378
|
+
lTCER, lTCResults, resultState, startTime='',
|
|
1327
1379
|
endTime='', duration='', sOwnerID=''):
|
|
1328
1380
|
"""
|
|
1329
1381
|
Return testsuite execution result template from provided configuration name.
|
|
@@ -1395,6 +1447,7 @@ Return testsuite execution result template from provided configuration name.
|
|
|
1395
1447
|
sTSResultxml = ''
|
|
1396
1448
|
sTemplatePath = os.path.join(self.templatesDir, 'testsuitelog.xml')
|
|
1397
1449
|
oTree = get_xml_tree(sTemplatePath, bdtd_validation=False)
|
|
1450
|
+
prefixState = 'com.ibm.rqm.execution.common.state.'
|
|
1398
1451
|
|
|
1399
1452
|
# prepare required data for template
|
|
1400
1453
|
resultTittle = 'Testsuite result: ' + testsuiteName
|
|
@@ -1438,6 +1491,11 @@ Return testsuite execution result template from provided configuration name.
|
|
|
1438
1491
|
oStarttime.text = str(startTime).replace(' ', 'T')
|
|
1439
1492
|
oEndtime.text = str(endTime).replace(' ', 'T')
|
|
1440
1493
|
oTotalRunTime.text = str(duration)
|
|
1494
|
+
# set default RQM state as inconclusive
|
|
1495
|
+
oState.text = prefixState + 'inconclusive'
|
|
1496
|
+
if resultState.lower() in self.RESULT_STATES:
|
|
1497
|
+
oState.text = prefixState +resultState.lower()
|
|
1498
|
+
|
|
1441
1499
|
for idx, sTCER in enumerate(lTCER):
|
|
1442
1500
|
sTCERURL = self.integrationURL('executionworkitem', sTCER)
|
|
1443
1501
|
oSuiteElem = etree.Element('{http://jazz.net/xmlns/alm/qm/v0.1/tsl/v0.1/}suiteelement', nsmap=nsmap)
|
|
@@ -1459,6 +1517,79 @@ Return testsuite execution result template from provided configuration name.
|
|
|
1459
1517
|
sTSResultxml = etree.tostring(oTree)
|
|
1460
1518
|
return sTSResultxml
|
|
1461
1519
|
|
|
1520
|
+
def createTestsuiteTemplate(self, testsuiteName, sDescription='', sOwnerID='', sTStemplate=None):
|
|
1521
|
+
"""
|
|
1522
|
+
Return testcase template from provided information.
|
|
1523
|
+
|
|
1524
|
+
**Arguments:**
|
|
1525
|
+
|
|
1526
|
+
* ``testsuiteName``
|
|
1527
|
+
|
|
1528
|
+
/ *Condition*: required / *Type*: str /
|
|
1529
|
+
|
|
1530
|
+
Testsuite name.
|
|
1531
|
+
|
|
1532
|
+
* ``sDescription``
|
|
1533
|
+
|
|
1534
|
+
/ *Condition*: optional / *Type*: str / *Default*: '' /
|
|
1535
|
+
|
|
1536
|
+
Testsuite description.
|
|
1537
|
+
|
|
1538
|
+
* ``sOwnerID``
|
|
1539
|
+
|
|
1540
|
+
/ *Condition*: optional / *Type*: str / *Default*: '' /
|
|
1541
|
+
|
|
1542
|
+
User ID of testsuite owner.
|
|
1543
|
+
|
|
1544
|
+
* ``sTStemplate``
|
|
1545
|
+
|
|
1546
|
+
/ *Condition*: optional / *Type*: str / *Default*: None /
|
|
1547
|
+
|
|
1548
|
+
Existing testsuite template as xml string.
|
|
1549
|
+
|
|
1550
|
+
If not provided, template file under `RQM_templates` is used as default.
|
|
1551
|
+
|
|
1552
|
+
**Returns:**
|
|
1553
|
+
|
|
1554
|
+
* ``sTSxml``
|
|
1555
|
+
|
|
1556
|
+
/ *Type*: str /
|
|
1557
|
+
|
|
1558
|
+
The xml testsuite template as string.
|
|
1559
|
+
"""
|
|
1560
|
+
sTSxml = ''
|
|
1561
|
+
if not sTStemplate:
|
|
1562
|
+
sTemplatePath = os.path.join(self.templatesDir ,'testsuite.xml')
|
|
1563
|
+
oTree = get_xml_tree(sTemplatePath, bdtd_validation=False)
|
|
1564
|
+
else:
|
|
1565
|
+
oTree = get_xml_tree(BytesIO(sTStemplate.encode()),bdtd_validation=False)
|
|
1566
|
+
|
|
1567
|
+
root = oTree.getroot()
|
|
1568
|
+
nsmap = root.nsmap
|
|
1569
|
+
|
|
1570
|
+
# prepare required data for template
|
|
1571
|
+
testerURL = self.userURL(self.userID)
|
|
1572
|
+
|
|
1573
|
+
# find nodes to change data
|
|
1574
|
+
oTittle = oTree.find('ns4:title', nsmap)
|
|
1575
|
+
oDescription = oTree.find('ns4:description', nsmap)
|
|
1576
|
+
oOwner = oTree.find('ns6:owner', nsmap)
|
|
1577
|
+
|
|
1578
|
+
# change nodes's data
|
|
1579
|
+
oTittle.text = testsuiteName
|
|
1580
|
+
oDescription.text = sDescription
|
|
1581
|
+
|
|
1582
|
+
# Incase not specify owner in template or input data, set it as provided user in cli
|
|
1583
|
+
if sOwnerID:
|
|
1584
|
+
oOwner.text = sOwnerID
|
|
1585
|
+
oOwner.attrib['{%s}resource' % nsmap['ns1']] = self.userURL(sOwnerID)
|
|
1586
|
+
elif not oOwner.text:
|
|
1587
|
+
oOwner.text = self.userID
|
|
1588
|
+
oOwner.attrib['{%s}resource' % nsmap['ns1']] = testerURL
|
|
1589
|
+
|
|
1590
|
+
# return xml template as string
|
|
1591
|
+
sTSxml = etree.tostring(oTree)
|
|
1592
|
+
return sTSxml
|
|
1462
1593
|
#
|
|
1463
1594
|
# Methods to create RQM resources
|
|
1464
1595
|
#
|
|
@@ -1827,3 +1958,66 @@ Link list of test cases to provided testsuite ID
|
|
|
1827
1958
|
else:
|
|
1828
1959
|
returnObj['message'] = "No testcase for linking."
|
|
1829
1960
|
return returnObj
|
|
1961
|
+
|
|
1962
|
+
def addTestsuite2Testplan(self, testplanID, testsuiteID=None):
|
|
1963
|
+
"""
|
|
1964
|
+
Add testsuite ID to provided testplan ID
|
|
1965
|
+
|
|
1966
|
+
**Arguments:**
|
|
1967
|
+
|
|
1968
|
+
* ``testplanID``
|
|
1969
|
+
|
|
1970
|
+
/ *Condition*: required / *Type*: str /
|
|
1971
|
+
|
|
1972
|
+
Testplan ID to link given testsuite ID.
|
|
1973
|
+
|
|
1974
|
+
* ``testsuiteID``
|
|
1975
|
+
|
|
1976
|
+
/ *Condition*: optional / *Type*: str / *Default*: None /
|
|
1977
|
+
|
|
1978
|
+
Testsuite to be linked with given testplan.
|
|
1979
|
+
|
|
1980
|
+
If not provide, `testsuite['id']` value will be used as id of testsuite.
|
|
1981
|
+
|
|
1982
|
+
**Returns:**
|
|
1983
|
+
|
|
1984
|
+
* ``returnObj``
|
|
1985
|
+
|
|
1986
|
+
/ *Type*: dict /
|
|
1987
|
+
|
|
1988
|
+
Response dictionary which contains status and error message.
|
|
1989
|
+
|
|
1990
|
+
Example:
|
|
1991
|
+
|
|
1992
|
+
.. code:: python
|
|
1993
|
+
|
|
1994
|
+
{
|
|
1995
|
+
'success' : False,
|
|
1996
|
+
'message': ''
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
"""
|
|
2000
|
+
returnObj = {'success' : False, 'message': ''}
|
|
2001
|
+
if testsuiteID == None:
|
|
2002
|
+
testsuiteID = self.testsuite['id']
|
|
2003
|
+
if testsuiteID:
|
|
2004
|
+
resTestplanData = self.getResourceByID('testplan', testplanID)
|
|
2005
|
+
oTree = get_xml_tree(BytesIO(str(resTestplanData.text).encode()),bdtd_validation=False)
|
|
2006
|
+
# RQM XML response using namespace for nodes
|
|
2007
|
+
# use namespace mapping from root for access response XML
|
|
2008
|
+
root = oTree.getroot()
|
|
2009
|
+
|
|
2010
|
+
sTestsuiteURL = self.integrationURL('testsuite', testsuiteID)
|
|
2011
|
+
oTS = etree.Element('{http://jazz.net/xmlns/alm/qm/v0.1/}testsuite', nsmap=root.nsmap)
|
|
2012
|
+
oTS.set('href', sTestsuiteURL)
|
|
2013
|
+
root.append(oTS)
|
|
2014
|
+
|
|
2015
|
+
# Update test plan data with linked testsuite and PUT to RQM
|
|
2016
|
+
resUpdateTestplan = self.updateResourceByID('testplan', testplanID, etree.tostring(oTree))
|
|
2017
|
+
if resUpdateTestplan.status_code == 200:
|
|
2018
|
+
returnObj['success'] = True
|
|
2019
|
+
else:
|
|
2020
|
+
returnObj['message'] = str(resUpdateTestplan.reason)
|
|
2021
|
+
else:
|
|
2022
|
+
returnObj['message'] = "No testsuite for adding."
|
|
2023
|
+
return returnObj
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<ns2:testsuite xmlns:ns2="http://jazz.net/xmlns/alm/qm/v0.1/"
|
|
3
|
+
xmlns:ns1="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
4
|
+
xmlns:ns3="http://schema.ibm.com/vega/2008/"
|
|
5
|
+
xmlns:ns4="http://purl.org/dc/elements/1.1/"
|
|
6
|
+
xmlns:ns5="http://jazz.net/xmlns/prod/jazz/process/0.6/"
|
|
7
|
+
xmlns:ns6="http://jazz.net/xmlns/alm/v0.1/"
|
|
8
|
+
xmlns:ns7="http://purl.org/dc/terms/"
|
|
9
|
+
xmlns:ns8="http://jazz.net/xmlns/alm/qm/v0.1/testscript/v0.1/"
|
|
10
|
+
xmlns:ns9="http://jazz.net/xmlns/alm/qm/v0.1/executionworkitem/v0.1"
|
|
11
|
+
xmlns:ns10="http://open-services.net/ns/core#"
|
|
12
|
+
xmlns:ns11="http://open-services.net/ns/qm#"
|
|
13
|
+
xmlns:ns12="http://jazz.net/xmlns/prod/jazz/rqm/process/1.0/"
|
|
14
|
+
xmlns:ns13="http://www.w3.org/2002/07/owl#"
|
|
15
|
+
xmlns:ns14="http://jazz.net/xmlns/alm/qm/qmadapter/v0.1"
|
|
16
|
+
xmlns:ns15="http://jazz.net/xmlns/alm/qm/qmadapter/task/v0.1"
|
|
17
|
+
xmlns:ns16="http://jazz.net/xmlns/alm/qm/v0.1/executionresult/v0.1"
|
|
18
|
+
xmlns:ns17="http://jazz.net/xmlns/alm/qm/v0.1/catalog/v0.1"
|
|
19
|
+
xmlns:ns18="http://jazz.net/xmlns/alm/qm/v0.1/tsl/v0.1/"
|
|
20
|
+
xmlns:ns20="http://jazz.net/xmlns/alm/qm/styleinfo/v0.1/"
|
|
21
|
+
xmlns:ns21="http://www.w3.org/1999/XSL/Transform">
|
|
22
|
+
<ns4:title></ns4:title>
|
|
23
|
+
<ns4:description></ns4:description>
|
|
24
|
+
<ns4:creator></ns4:creator>
|
|
25
|
+
<ns6:owner></ns6:owner>
|
|
26
|
+
<ns2:testplan href=""/>
|
|
27
|
+
</ns2:testsuite>
|
|
Binary file
|
{robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/RobotLog2RQM/robotlog2rqm.py
RENAMED
|
@@ -41,7 +41,8 @@ from RobotLog2RQM.version import VERSION, VERSION_DATE
|
|
|
41
41
|
DRESULT_MAPPING = {
|
|
42
42
|
"PASS": "Passed",
|
|
43
43
|
"FAIL": "Failed",
|
|
44
|
-
"UNKNOWN": "Inconclusive"
|
|
44
|
+
"UNKNOWN": "Inconclusive",
|
|
45
|
+
"SKIP": "Blocked"
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
DEFAULT_METADATA = {
|
|
@@ -157,7 +158,7 @@ Write log message to console/file output.
|
|
|
157
158
|
return
|
|
158
159
|
|
|
159
160
|
@classmethod
|
|
160
|
-
def log_warning(cls, msg):
|
|
161
|
+
def log_warning(cls, msg, indent=0):
|
|
161
162
|
"""
|
|
162
163
|
Write warning message to console/file output.
|
|
163
164
|
|
|
@@ -169,14 +170,20 @@ Write warning message to console/file output.
|
|
|
169
170
|
|
|
170
171
|
Warning message which is written to output.
|
|
171
172
|
|
|
173
|
+
* ``indent``
|
|
174
|
+
|
|
175
|
+
/ *Condition*: optional / *Type*: int / *Default*: 0 /
|
|
176
|
+
|
|
177
|
+
Offset indent.
|
|
178
|
+
|
|
172
179
|
**Returns:**
|
|
173
180
|
|
|
174
181
|
(*no returns*)
|
|
175
182
|
"""
|
|
176
|
-
cls.log(cls.prefix_warn+str(msg), cls.color_warn)
|
|
183
|
+
cls.log(cls.prefix_warn+str(msg), cls.color_warn, indent)
|
|
177
184
|
|
|
178
185
|
@classmethod
|
|
179
|
-
def log_error(cls, msg, fatal_error=False):
|
|
186
|
+
def log_error(cls, msg, fatal_error=False, indent=0):
|
|
180
187
|
"""
|
|
181
188
|
Write error message to console/file output.
|
|
182
189
|
|
|
@@ -192,6 +199,12 @@ Write error message to console/file output.
|
|
|
192
199
|
|
|
193
200
|
If set, tool will terminate after logging error message.
|
|
194
201
|
|
|
202
|
+
* ``indent``
|
|
203
|
+
|
|
204
|
+
/ *Condition*: optional / *Type*: int / *Default*: 0 /
|
|
205
|
+
|
|
206
|
+
Offset indent.
|
|
207
|
+
|
|
195
208
|
**Returns:**
|
|
196
209
|
|
|
197
210
|
(*no returns*)
|
|
@@ -200,7 +213,7 @@ Write error message to console/file output.
|
|
|
200
213
|
if fatal_error:
|
|
201
214
|
prefix = cls.prefix_fatalerror
|
|
202
215
|
|
|
203
|
-
cls.log(prefix+str(msg), cls.color_error)
|
|
216
|
+
cls.log(prefix+str(msg), cls.color_error, indent)
|
|
204
217
|
if fatal_error:
|
|
205
218
|
cls.log(f"{sys.argv[0]} has been stopped!", cls.color_error)
|
|
206
219
|
exit(1)
|
|
@@ -280,9 +293,12 @@ Avalable arguments in command line:
|
|
|
280
293
|
- `user` : user for RQM login.
|
|
281
294
|
- `password` : user password for RQM login.
|
|
282
295
|
- `testplan` : RQM testplan ID.
|
|
296
|
+
- `--testsuite` : RQM testsuite ID. If value is 'new', then create a new testsuite for this execution.
|
|
283
297
|
- `--recursive` : if True, then the path is searched recursively for log files to be imported.
|
|
284
298
|
- `--createmissing` : if True, then all testcases without tcid are created when importing.
|
|
285
299
|
- `--dryrun` : if True, then verify all input arguments (includes RQM authentication) and show what would be done.
|
|
300
|
+
- `--stream` : project stream. Note, requires Configuration Management (CM) to be enabled for the project area.
|
|
301
|
+
- `--baseline` : project baseline. Note, requires Configuration Management (CM), or Baselines Only to be enabled for the project area.
|
|
286
302
|
|
|
287
303
|
**Arguments:**
|
|
288
304
|
|
|
@@ -311,6 +327,8 @@ Avalable arguments in command line:
|
|
|
311
327
|
cmdParser.add_argument('password', type=str, help='password for RQM login.')
|
|
312
328
|
cmdParser.add_argument('testplan', type=str,
|
|
313
329
|
help='testplan ID for this execution.')
|
|
330
|
+
cmdParser.add_argument('--testsuite', type=str,
|
|
331
|
+
help="testsuite ID for this execution. If 'new', then create a new testsuite for this execution.")
|
|
314
332
|
cmdParser.add_argument('--recursive',action="store_true",
|
|
315
333
|
help='if set, then the path is searched recursively for log files to be imported.')
|
|
316
334
|
cmdParser.add_argument('--createmissing', action="store_true",
|
|
@@ -319,6 +337,10 @@ Avalable arguments in command line:
|
|
|
319
337
|
help='if set, then testcase information on RQM will be updated bases on robot testfile.')
|
|
320
338
|
cmdParser.add_argument('--dryrun',action="store_true",
|
|
321
339
|
help='if set, then verify all input arguments (includes RQM authentication) and show what would be done.')
|
|
340
|
+
cmdParser.add_argument('--stream', type=str,
|
|
341
|
+
help='project stream. Note, requires Configuration Management (CM) to be enabled for the project area.')
|
|
342
|
+
cmdParser.add_argument('--baseline', type=str,
|
|
343
|
+
help='project baseline. Note, requires Configuration Management (CM), or Baselines Only to be enabled for the project area.')
|
|
322
344
|
|
|
323
345
|
return cmdParser.parse_args()
|
|
324
346
|
|
|
@@ -394,7 +416,7 @@ Extract metadata from suite result bases on DEFAULT_METADATA.
|
|
|
394
416
|
|
|
395
417
|
return dMetadata
|
|
396
418
|
|
|
397
|
-
def process_suite(RQMClient, suite):
|
|
419
|
+
def process_suite(RQMClient, suite, log_indent=0):
|
|
398
420
|
"""
|
|
399
421
|
Process robot suite for importing to RQM.
|
|
400
422
|
|
|
@@ -412,15 +434,21 @@ Process robot suite for importing to RQM.
|
|
|
412
434
|
|
|
413
435
|
Robot suite object.
|
|
414
436
|
|
|
437
|
+
* ``log_indent``
|
|
438
|
+
|
|
439
|
+
/ *Condition*: optional / *Type*: int / *Default*: 0 /
|
|
440
|
+
|
|
441
|
+
Indent for logging message.
|
|
442
|
+
|
|
415
443
|
**Returns:**
|
|
416
444
|
|
|
417
445
|
(*no returns*)
|
|
418
446
|
"""
|
|
419
447
|
if len(list(suite.suites)) > 0:
|
|
420
448
|
for subsuite in suite.suites:
|
|
421
|
-
process_suite(RQMClient, subsuite)
|
|
449
|
+
process_suite(RQMClient, subsuite, log_indent=log_indent+2)
|
|
422
450
|
else:
|
|
423
|
-
Logger.log(f"Process suite: {suite.name}")
|
|
451
|
+
Logger.log(f"Process suite: {suite.name}", indent=log_indent)
|
|
424
452
|
|
|
425
453
|
# update missing metadata from parent suite
|
|
426
454
|
if suite.parent and suite.parent.metadata:
|
|
@@ -430,9 +458,9 @@ Process robot suite for importing to RQM.
|
|
|
430
458
|
|
|
431
459
|
if len(list(suite.tests)) > 0:
|
|
432
460
|
for test in suite.tests:
|
|
433
|
-
process_test(RQMClient, test)
|
|
461
|
+
process_test(RQMClient, test, log_indent=log_indent+2)
|
|
434
462
|
|
|
435
|
-
def process_test(RQMClient, test):
|
|
463
|
+
def process_test(RQMClient, test, log_indent=0):
|
|
436
464
|
"""
|
|
437
465
|
Process robot test for importing to RQM.
|
|
438
466
|
|
|
@@ -450,11 +478,17 @@ Process robot test for importing to RQM.
|
|
|
450
478
|
|
|
451
479
|
Robot test object.
|
|
452
480
|
|
|
481
|
+
* ``log_indent``
|
|
482
|
+
|
|
483
|
+
/ *Condition*: optional / *Type*: int / *Default*: 0 /
|
|
484
|
+
|
|
485
|
+
Indent for logging message.
|
|
486
|
+
|
|
453
487
|
**Returns:**
|
|
454
488
|
|
|
455
489
|
(*no returns*)
|
|
456
490
|
"""
|
|
457
|
-
Logger.log(f"Process test: {test.name}")
|
|
491
|
+
Logger.log(f"Process test: {test.name}", indent=log_indent)
|
|
458
492
|
|
|
459
493
|
# Avoid create resources with dryrun
|
|
460
494
|
if Logger.dryrun:
|
|
@@ -484,7 +518,7 @@ Process robot test for importing to RQM.
|
|
|
484
518
|
try:
|
|
485
519
|
_tc_result = DRESULT_MAPPING[test.status]
|
|
486
520
|
except Exception:
|
|
487
|
-
Logger.log_error(f"Invalid Robotframework result state '{test.status}' of test '{_tc_name}'.")
|
|
521
|
+
Logger.log_error(f"Invalid Robotframework result state '{test.status}' of test '{_tc_name}'.", indent=log_indent)
|
|
488
522
|
return
|
|
489
523
|
_tc_message = test.message
|
|
490
524
|
_tc_start_time = convert_to_datetime(test.starttime)
|
|
@@ -508,19 +542,19 @@ Process robot test for importing to RQM.
|
|
|
508
542
|
res = RQMClient.createResource('testcase', oTCTemplate)
|
|
509
543
|
if res['success']:
|
|
510
544
|
_tc_id = res['id']
|
|
511
|
-
Logger.log(f"Create testcase '{_tc_name}' with ID '{_tc_id}' successfully!")
|
|
545
|
+
Logger.log(f"Create testcase '{_tc_name}' with ID '{_tc_id}' successfully!", indent=log_indent)
|
|
512
546
|
RQMClient.dMappingTCID[_tc_id] = _tc_name
|
|
513
547
|
else:
|
|
514
|
-
Logger.log_error(f"Create testcase '{_tc_name}' failed. Reason: {res['message']}")
|
|
548
|
+
Logger.log_error(f"Create testcase '{_tc_name}' failed. Reason: {res['message']}", indent=log_indent)
|
|
515
549
|
return
|
|
516
550
|
else:
|
|
517
|
-
Logger.log_error(f"There is no 'tcid' information for importing test '{_tc_name}'.")
|
|
551
|
+
Logger.log_error(f"There is no 'tcid' information for importing test '{_tc_name}'.", indent=log_indent)
|
|
518
552
|
return
|
|
519
553
|
else:
|
|
520
554
|
# If more than 1 tcid are defined in [Tags], the first one is used.
|
|
521
555
|
if len(lTCIDTags) > 1:
|
|
522
556
|
_tc_id = lTCIDTags[0]
|
|
523
|
-
Logger.log_warning(f"More than 1 'tcid-' tags in test '{_tc_name}', '{_tc_id}' is used.")
|
|
557
|
+
Logger.log_warning(f"More than 1 'tcid-' tags in test '{_tc_name}', '{_tc_id}' is used.", indent=log_indent)
|
|
524
558
|
|
|
525
559
|
# If --updatetestcase is set. Test case with provided tcid will be updated on RQM:
|
|
526
560
|
# Get existing resource of testcase from RQM.
|
|
@@ -537,9 +571,9 @@ Process robot test for importing to RQM.
|
|
|
537
571
|
_tc_link,
|
|
538
572
|
sTCtemplate=str(resTC.text))
|
|
539
573
|
RQMClient.updateResourceByID('testcase', _tc_id, oTCTemplate)
|
|
540
|
-
Logger.log(f"Update testcase '{_tc_name}' with ID '{_tc_id}' successfully!")
|
|
574
|
+
Logger.log(f"Update testcase '{_tc_name}' with ID '{_tc_id}' successfully!", indent=log_indent)
|
|
541
575
|
else:
|
|
542
|
-
Logger.log_error(f"Update testcase with ID '{_tc_id}' failed. Please check whether it is existing on RQM.")
|
|
576
|
+
Logger.log_error(f"Update testcase with ID '{_tc_id}' failed. Please check whether it is existing on RQM.", indent=log_indent)
|
|
543
577
|
return
|
|
544
578
|
|
|
545
579
|
# Create TCER:
|
|
@@ -554,11 +588,11 @@ Process robot test for importing to RQM.
|
|
|
554
588
|
res = RQMClient.createResource('executionworkitem', oTCERTemplate)
|
|
555
589
|
_tc_tcer_id = res['id']
|
|
556
590
|
if res['success']:
|
|
557
|
-
Logger.log(f"Created TCER with ID '{_tc_tcer_id}' successfully.")
|
|
591
|
+
Logger.log(f"Created TCER with ID '{_tc_tcer_id}' successfully.", indent=log_indent+2)
|
|
558
592
|
elif (res['status_code'] == 303 or res['status_code'] == 200) and res['id'] != '':
|
|
559
|
-
Logger.log_warning(f"TCER for testcase '{_tc_id}' and testplan '{_tc_testplan_id}' is existing with ID: '{_tc_tcer_id}'")
|
|
593
|
+
Logger.log_warning(f"TCER for testcase '{_tc_id}' and testplan '{_tc_testplan_id}' is existing with ID: '{_tc_tcer_id}'", indent=log_indent+2)
|
|
560
594
|
else:
|
|
561
|
-
Logger.log_error(f"Create TCER failed. Please check whether test case with ID '{_tc_id}' is existing on RQM or not. Reason: {res['message']}.")
|
|
595
|
+
Logger.log_error(f"Create TCER failed. Please check whether test case with ID '{_tc_id}' is existing on RQM or not. Reason: {res['message']}.", indent=log_indent+2)
|
|
562
596
|
return
|
|
563
597
|
|
|
564
598
|
if _tc_tcer_id not in RQMClient.lTCERIDs:
|
|
@@ -583,10 +617,10 @@ Process robot test for importing to RQM.
|
|
|
583
617
|
_tc_team)
|
|
584
618
|
res = RQMClient.createResource('executionresult', oTCResultTemplate)
|
|
585
619
|
if res['success']:
|
|
586
|
-
Logger.log(f"Create result for test '{_tc_name}' successfully!")
|
|
620
|
+
Logger.log(f"Create result for test '{_tc_name}' successfully!", indent=log_indent+4)
|
|
587
621
|
_tc_result_id = res['id']
|
|
588
622
|
else:
|
|
589
|
-
Logger.log_error(f"Create result for test '{_tc_name}' failed. Reason: {res['message']}.")
|
|
623
|
+
Logger.log_error(f"Create result for test '{_tc_name}' failed. Reason: {res['message']}.", indent=log_indent+4)
|
|
590
624
|
return
|
|
591
625
|
if _tc_result_id not in RQMClient.lTCResultIDs:
|
|
592
626
|
RQMClient.lTCResultIDs.append(_tc_result_id)
|
|
@@ -594,6 +628,10 @@ Process robot test for importing to RQM.
|
|
|
594
628
|
# Append lTestcaseIDs (for linking testplan/testsuite)
|
|
595
629
|
if _tc_id not in RQMClient.lTestcaseIDs:
|
|
596
630
|
RQMClient.lTestcaseIDs.append(_tc_id)
|
|
631
|
+
|
|
632
|
+
# Collect starttime and endtime for testsuite log creation
|
|
633
|
+
RQMClient.lStartTimes.append(_tc_start_time)
|
|
634
|
+
RQMClient.lEndTimes.append(_tc_end_time)
|
|
597
635
|
|
|
598
636
|
def RobotLog2RQM(args=None):
|
|
599
637
|
"""
|
|
@@ -621,11 +659,13 @@ Flow to import Robot results to RQM:
|
|
|
621
659
|
* `user` : user for RQM login.
|
|
622
660
|
* `password` : user password for RQM login.
|
|
623
661
|
* `testplan` : RQM testplan ID.
|
|
662
|
+
* `testsuite` : testsuite ID for this execution. If 'new', then create a new testsuite for this execution.
|
|
624
663
|
* `recursive` : if True, then the path is searched recursively for log files to be imported.
|
|
625
664
|
* `createmissing` : if True, then all testcases without tcid are created when importing.
|
|
626
665
|
* `updatetestcase` : if True, then testcases information on RQM will be updated bases on robot testfile.
|
|
627
666
|
* `dryrun` : if True, then verify all input arguments (includes RQM authentication) and show what would be done.
|
|
628
|
-
|
|
667
|
+
* `stream` : project stream. Note, requires Configuration Management (CM) to be enabled for the project area.
|
|
668
|
+
* `baseline` : project baseline. Note, requires Configuration Management (CM), or Baselines Only to be enabled for the project area.
|
|
629
669
|
**Returns:**
|
|
630
670
|
|
|
631
671
|
(*no returns*)
|
|
@@ -675,6 +715,7 @@ Flow to import Robot results to RQM:
|
|
|
675
715
|
try:
|
|
676
716
|
bSuccess = RQMClient.login()
|
|
677
717
|
if bSuccess:
|
|
718
|
+
Logger.log()
|
|
678
719
|
Logger.log(f"Login RQM as user '{args.user}' successfully!")
|
|
679
720
|
else:
|
|
680
721
|
Logger.log_error("Could not login to RQM: 'Unkown reason'.")
|
|
@@ -693,14 +734,85 @@ Flow to import Robot results to RQM:
|
|
|
693
734
|
metadata_info['version_sw'] = None
|
|
694
735
|
metadata_info['project'] = None
|
|
695
736
|
RQMClient.config(args.testplan, metadata_info['version_sw'],
|
|
696
|
-
metadata_info['project'], args.createmissing, args.updatetestcase
|
|
737
|
+
metadata_info['project'], args.createmissing, args.updatetestcase,
|
|
738
|
+
args.testsuite, stream=args.stream, baseline=args.baseline)
|
|
739
|
+
|
|
740
|
+
if args.testsuite == "new":
|
|
741
|
+
# Create new testsuite
|
|
742
|
+
if not args.dryrun:
|
|
743
|
+
testsuite_data = RQMClient.createTestsuiteTemplate(result.suite.name, result.suite.doc)
|
|
744
|
+
res_testsuite = RQMClient.createResource('testsuite', testsuite_data)
|
|
745
|
+
else:
|
|
746
|
+
# for dryrun
|
|
747
|
+
res_testsuite = {'success': True, 'id': 1111}
|
|
748
|
+
|
|
749
|
+
if res_testsuite['success']:
|
|
750
|
+
_ts_id = res_testsuite['id']
|
|
751
|
+
Logger.log(f"Create testsuite '{result.suite.name}' with ID '{_ts_id}' successfully!")
|
|
752
|
+
RQMClient.testsuite['id'] = _ts_id
|
|
753
|
+
RQMClient.testsuite['name'] = result.suite.name
|
|
754
|
+
else:
|
|
755
|
+
Logger.log_error(f"Create testsuite '{result.suite.name}' failed. Reason: {res_testsuite['message']}", fatal_error=True)
|
|
756
|
+
|
|
697
757
|
# Process suite for importing
|
|
698
758
|
process_suite(RQMClient, result.suite)
|
|
699
759
|
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
760
|
+
if RQMClient.testsuite['id']:
|
|
761
|
+
if not args.dryrun:
|
|
762
|
+
# Create testsuite execution record if requires
|
|
763
|
+
testsuite_record_data = RQMClient.createTSERTemplate(RQMClient.testsuite['id'], RQMClient.testsuite['name'], args.testplan, RQMClient.configuration)
|
|
764
|
+
res_TSER = RQMClient.createResource('suiteexecutionrecord', testsuite_record_data)
|
|
765
|
+
sTSERID = res_TSER['id']
|
|
766
|
+
Logger.log()
|
|
767
|
+
if res_TSER['success']:
|
|
768
|
+
Logger.log(f"Create TSER with id {sTSERID} successfully!")
|
|
769
|
+
elif (res_TSER['status_code'] == 303 or res_TSER['status_code'] == 200) and res_TSER['id'] != '':
|
|
770
|
+
### incase executionworkitem is existing, cannot create new one
|
|
771
|
+
### Use the existing ID for new result
|
|
772
|
+
Logger.log_warning(f"TSER for testsuite {RQMClient.testsuite['id']} is existing.\nAdd this execution result to existing TSER id: {sTSERID}")
|
|
773
|
+
else:
|
|
774
|
+
Logger.log_error(f"Create TSER failed, {res_TSER['message']}")
|
|
775
|
+
|
|
776
|
+
# Create new testsuite result and link all TCERs
|
|
777
|
+
testsuite_result_data = RQMClient.createTestsuiteResultTemplate(RQMClient.testsuite['id'],
|
|
778
|
+
RQMClient.testsuite['name'],
|
|
779
|
+
sTSERID,
|
|
780
|
+
RQMClient.lTCERIDs,
|
|
781
|
+
RQMClient.lTCResultIDs,
|
|
782
|
+
DRESULT_MAPPING[result.suite.status]
|
|
783
|
+
)
|
|
784
|
+
res_TSLog = RQMClient.createResource('testsuitelog', testsuite_result_data)
|
|
785
|
+
sSuiteResultID = res_TSLog['id']
|
|
786
|
+
if res_TSLog['success']:
|
|
787
|
+
Logger.log(f"Created testsuite result with id {sSuiteResultID} successfully.", indent=2)
|
|
788
|
+
else:
|
|
789
|
+
Logger.log_error(f"Create testsuite result failed, {res_TSLog['message']}", indent=2)
|
|
790
|
+
else:
|
|
791
|
+
Logger.log(f"Create TSER")
|
|
792
|
+
Logger.log(f"Created testsuite result")
|
|
793
|
+
|
|
794
|
+
# Link all imported testcase ID(s) with testsuite
|
|
795
|
+
try:
|
|
796
|
+
RQMClient.linkListTestcase2Testsuite(RQMClient.testsuite['id'])
|
|
797
|
+
Logger.log(f"Link all imported test cases with testsuite {RQMClient.testsuite['id']} successfully.")
|
|
798
|
+
except Exception as reason:
|
|
799
|
+
Logger.log_error(f"Link all imported test cases with testsuite failed.\nReason: {reason}", fatal_error=True)
|
|
800
|
+
|
|
801
|
+
# Add testsuite to given testplan
|
|
802
|
+
try:
|
|
803
|
+
RQMClient.addTestsuite2Testplan(args.testplan)
|
|
804
|
+
Logger.log(f"Add testsuite {RQMClient.testsuite['id']} to testplan {args.testplan} successfully.")
|
|
805
|
+
except Exception as reason:
|
|
806
|
+
Logger.log_error(f"Add testsuite to testplan failed.\nReason: {reason}", fatal_error=True)
|
|
703
807
|
|
|
808
|
+
else:
|
|
809
|
+
# Link all imported testcase ID(s) with testplan
|
|
810
|
+
try:
|
|
811
|
+
RQMClient.linkListTestcase2Testplan(args.testplan)
|
|
812
|
+
Logger.log(f"Link all imported test cases with testplan {args.testplan} successfully.")
|
|
813
|
+
except Exception as reason:
|
|
814
|
+
Logger.log_error(f"Link all imported test cases with testplan failed.\nReason: {reason}", fatal_error=True)
|
|
815
|
+
|
|
704
816
|
# Update testcase(s) with generated ID(s)
|
|
705
817
|
# Under developing
|
|
706
818
|
|
|
@@ -709,7 +821,15 @@ Flow to import Robot results to RQM:
|
|
|
709
821
|
|
|
710
822
|
# 5. Disconnect from RQM
|
|
711
823
|
RQMClient.disconnect()
|
|
712
|
-
|
|
824
|
+
|
|
825
|
+
testcnt_msg = f"All {len(RQMClient.lTestcaseIDs)}"
|
|
826
|
+
extended_msg = ""
|
|
827
|
+
if (len(RQMClient.lTestcaseIDs) > len(RQMClient.lTCResultIDs)):
|
|
828
|
+
testcnt_msg = f"{len(RQMClient.lTCResultIDs)} of {len(RQMClient.lTestcaseIDs)}"
|
|
829
|
+
extended_msg = f" {len(RQMClient.lTestcaseIDs)-len(RQMClient.lTCResultIDs)} test results are skipped because of errors."
|
|
830
|
+
|
|
831
|
+
Logger.log()
|
|
832
|
+
Logger.log(f"{testcnt_msg} test results are imported to RQM successfully.{extended_msg}")
|
|
713
833
|
|
|
714
834
|
if __name__=="__main__":
|
|
715
835
|
RobotLog2RQM()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: robotframework-robotlog2rqm
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
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
|
|
@@ -128,33 +128,40 @@ Use below command to get tools\'s usage:
|
|
|
128
128
|
|
|
129
129
|
The usage should be showed as below:
|
|
130
130
|
|
|
131
|
-
usage: RobotLog2RQM (RobotXMLResult to RQM importer) [-h] [-v] [--recursive]
|
|
132
|
-
|
|
133
|
-
|
|
131
|
+
usage: RobotLog2RQM (RobotXMLResult to RQM importer) [-h] [-v] [--testsuite TESTSUITE] [--recursive]
|
|
132
|
+
[--createmissing] [--updatetestcase] [--dryrun] [--stream STREAM] [--baseline BASELINE]
|
|
133
|
+
resultxmlfile host project user password testplan
|
|
134
134
|
|
|
135
|
-
RobotLog2RQM imports XML result files (default: output.xml) generated by the
|
|
135
|
+
RobotLog2RQM imports XML result files (default: output.xml) generated by the
|
|
136
136
|
Robot Framework into an IBM Rational Quality Manager.
|
|
137
137
|
|
|
138
138
|
positional arguments:
|
|
139
|
-
resultxmlfile
|
|
140
|
-
|
|
141
|
-
host
|
|
142
|
-
project
|
|
143
|
-
user
|
|
144
|
-
password
|
|
145
|
-
testplan
|
|
139
|
+
resultxmlfile absolute or relative path to the xml result file
|
|
140
|
+
or directory of result files to be imported.
|
|
141
|
+
host RQM host url.
|
|
142
|
+
project project on RQM.
|
|
143
|
+
user user for RQM login.
|
|
144
|
+
password password for RQM login.
|
|
145
|
+
testplan testplan ID for this execution.
|
|
146
146
|
|
|
147
147
|
optional arguments:
|
|
148
|
-
-h, --help
|
|
149
|
-
-v, --version
|
|
150
|
-
--
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
148
|
+
-h, --help show this help message and exit
|
|
149
|
+
-v, --version Version of the RobotLog2RQM importer.
|
|
150
|
+
--testsuite TESTSUITE
|
|
151
|
+
testsuite ID for this execution. If 'new', then create a new
|
|
152
|
+
testsuite for this execution.
|
|
153
|
+
--recursive if set, then the path is searched recursively for
|
|
154
|
+
log files to be imported.
|
|
155
|
+
--createmissing if set, then all testcases without tcid are created
|
|
156
|
+
when importing.
|
|
157
|
+
--updatetestcase if set, then testcase information on RQM will be updated
|
|
158
|
+
bases on robot testfile.
|
|
159
|
+
--dryrun if set, then verify all input arguments
|
|
160
|
+
(includes RQM authentication) and show what would be done.
|
|
161
|
+
--stream STREAM project stream. Note, requires Configuration Management (CM)
|
|
162
|
+
to be enabled for the project area.
|
|
163
|
+
--baseline BASELINE project baseline. Note, requires Configuration Management (CM),
|
|
164
|
+
or Baselines Only to be enabled for the project area.
|
|
158
165
|
|
|
159
166
|
The below command is simple usage witth all required arguments to import
|
|
160
167
|
Robot Framework results into RQM:
|
|
@@ -13,6 +13,7 @@ RobotLog2RQM/RQM_templates/executionresult.xml
|
|
|
13
13
|
RobotLog2RQM/RQM_templates/executionworkitem.xml
|
|
14
14
|
RobotLog2RQM/RQM_templates/suiteexecutionrecord.xml
|
|
15
15
|
RobotLog2RQM/RQM_templates/testcase.xml
|
|
16
|
+
RobotLog2RQM/RQM_templates/testsuite.xml
|
|
16
17
|
RobotLog2RQM/RQM_templates/testsuitelog.xml
|
|
17
18
|
robotframework_robotlog2rqm.egg-info/PKG-INFO
|
|
18
19
|
robotframework_robotlog2rqm.egg-info/SOURCES.txt
|
|
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
|
{robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/RobotLog2RQM/__init__.py
RENAMED
|
File without changes
|
{robotframework-robotlog2rqm-1.2.3 → robotframework-robotlog2rqm-1.4.0}/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
|