6
6
@author: kereval.com
7
7
Initialy based on the James Stock testlink-api-python-client R7.
8
8
9
- Updated by Kereval to support testCase Reporting and File attachment to test execution
10
-
9
+ Update by pade to provide a user friendly library, with more robustness and error management
11
10
"""
12
11
import xmlrpclib
12
+ import sys
13
+
14
+ class TestLinkAPIClient :
15
+
16
+ __VERSION__ = "0.3"
13
17
14
- class TestlinkAPIClient :
15
-
16
18
def __init__ (self , server_url , devKey ):
17
19
self .server = xmlrpclib .Server (server_url )
18
20
self .devKey = devKey
@@ -139,14 +141,52 @@ def getTestCaseCustomFieldDesignValue(self, testcaseexternalid, version,
139
141
'details' : str (details )}
140
142
return self .server .tl .getTestCaseCustomFieldDesignValue (argsAPI )
141
143
142
- def getTestCaseIDByName (self , testCaseName ):
143
- """ getTestCaseIDByName :
144
- Find a test case by its name
145
- """
144
+ def __getTestCaseIDByName (self , testCaseName , testSuiteName = None , testProjectName = None ):
145
+ """ __getTestCaseIDByName :
146
+ Internal function
147
+ Find a test case by its name
148
+ testSuiteName and testProjectName are optionals arguments
149
+ This function return a list of tests cases
150
+ """
146
151
argsAPI = {'devKey' : self .devKey ,
147
152
'testcasename' :str (testCaseName )}
148
- return self .server .tl .getTestCaseIDByName (argsAPI )
153
+
154
+ if testSuiteName is not None :
155
+ argsAPI .update ({'testsuitename' :str (testSuiteName )})
156
+
157
+ if testProjectName is not None :
158
+ argsAPI .update ({'testprojectname' :str (testProjectName )})
159
+
160
+ # Server return can be a list or a dictionnary !
161
+ # This function always return a list
162
+ ret_srv = self .server .tl .getTestCaseIDByName (argsAPI )
163
+ if type (ret_srv ) == dict :
164
+ retval = []
165
+ for value in ret_srv .values ():
166
+ retval .append (value )
167
+ return retval
168
+ else :
169
+ return ret_srv
170
+
171
+
172
+ def getTestCaseIDByName (self , testCaseName , testSuiteName , testProjectName ):
173
+ """ getTestCaseIDByName :
174
+ Find a test case by its name, by its suite and its project
175
+ Suite name must not be duplicate, so only one test case must be found
176
+ Return (id, None) if success
177
+ or (-1, "error message") in case of error
178
+ """
179
+ results = self .__getTestCaseIDByName (testCaseName , testSuiteName , testProjectName )
180
+ if results [0 ].has_key ("message" ):
181
+ return (- 1 , results [0 ]["message" ])
182
+ elif len (results ) > 1 :
183
+ return (- 1 , "(getTestCaseIDByName) - Several case test found. Suite name must not be duplicate for the same project" )
184
+ else :
185
+ if results [0 ]["name" ] == testCaseName :
186
+ return (results [0 ]["id" ], None )
187
+ return (- 1 , "(getTestCaseIDByName) - Internal server error. Return value is not expected one!" )
149
188
189
+
150
190
def getTestCasesForTestPlan (self , * args ):
151
191
""" getTestCasesForTestPlan :
152
192
List test cases linked to a test plan
@@ -329,12 +369,12 @@ def createTestCase(self, *args):
329
369
self .stepsList = []
330
370
return ret
331
371
332
- def reportTCResult (self , testcaseid , testplanid , buildid , status , notes ):
372
+ def __reportTCResult (self , testcaseid , testplanid , buildname , status , notes ):
333
373
"""
334
374
Report execution result
335
375
testcaseid: internal testlink id of the test case
336
376
testplanid: testplan associated with the test case
337
- buildid : build version of the test case
377
+ buildname : build name of the test case
338
378
status: test verdict ('p': pass,'f': fail,'b': blocked)
339
379
340
380
Return : [{'status': True, 'operation': 'reportTCResult', 'message': 'Success!', 'overwrite': False, 'id': '37'}]
@@ -343,11 +383,31 @@ def reportTCResult(self, testcaseid, testplanid, buildid, status, notes ):
343
383
argsAPI = {'devKey' : self .devKey ,
344
384
'testcaseid' : testcaseid ,
345
385
'testplanid' : testplanid ,
346
- 'buildid' : buildid ,
386
+ 'buildname' : buildname ,
347
387
'status' : status ,
348
388
'notes' : notes
349
389
}
350
390
return self .server .tl .reportTCResult (argsAPI )
391
+
392
+ def reportResult (self , testCaseName , testSuiteName , testProjectName ):
393
+ pass
394
+
395
+ def setReportCtx (self , testProjectName , testPlanName , buildName ):
396
+ """
397
+ Set project name test plan name and build name for reportResult function
398
+ """
399
+ project = getTestProjectByName (testProjectName )
400
+ if project [0 ].has_key ("message" ):
401
+ sys .exit (project [0 ]["message" ])
402
+
403
+ # Check if project is active
404
+ if project [0 ]['active' ] != '1' :
405
+ sys .exit ("(getTestProjectByName) - Test project (name:%s) is not active" % testProjectName )
406
+
407
+ # Store project id
408
+ self .projectId = project [0 ]['id' ]
409
+ #TODO: à finir
410
+
351
411
352
412
def uploadExecutionAttachment (self ,attachmentfile ,executionid ,title ,description ):
353
413
"""
@@ -486,35 +546,45 @@ def initStep(self, actions, expected_results, execution_type):
486
546
Initializes the list which stores the Steps of a Test Case to create
487
547
"""
488
548
self .stepsList = []
489
- list = {}
490
- list ['step_number' ] = '1'
491
- list ['actions' ] = actions
492
- list ['expected_results' ] = expected_results
493
- list ['execution_type' ] = str (execution_type )
494
- self .stepsList .append (list )
549
+ lst = {}
550
+ lst ['step_number' ] = '1'
551
+ lst ['actions' ] = actions
552
+ lst ['expected_results' ] = expected_results
553
+ lst ['execution_type' ] = str (execution_type )
554
+ self .stepsList .append (lst )
495
555
return True
496
556
497
557
def appendStep (self , actions , expected_results , execution_type ):
498
558
""" appendStep :
499
559
Appends a step to the steps list
500
560
"""
501
- list = {}
502
- list ['step_number' ] = str (len (self .stepsList )+ 1 )
503
- list ['actions' ] = actions
504
- list ['expected_results' ] = expected_results
505
- list ['execution_type' ] = str (execution_type )
506
- self .stepsList .append (list )
561
+ lst = {}
562
+ lst ['step_number' ] = str (len (self .stepsList )+ 1 )
563
+ lst ['actions' ] = actions
564
+ lst ['expected_results' ] = expected_results
565
+ lst ['execution_type' ] = str (execution_type )
566
+ self .stepsList .append (lst )
507
567
return True
508
568
509
569
def getProjectIDByName (self , projectName ):
510
- projects = self .server .tl .getProjects ({'devKey' : self .devKey })
511
- for project in projects :
512
- if (project ['name' ] == projectName ):
513
- result = project ['id' ]
514
- else :
515
- result = - 1
516
- return result
517
-
570
+ projects = self .server .tl .getProjects ({'devKey' : self .devKey })
571
+ for project in projects :
572
+ if (project ['name' ] == projectName ):
573
+ result = project ['id' ]
574
+ else :
575
+ result = - 1
576
+ return result
577
+
578
+ def __str__ (self ):
579
+ message = """
580
+ TestLinkAPIClient - version %s
581
+ @author: Olivier Renault ([email protected] )
582
+ @author: kereval.com
583
+ @author: Patrick Dassier
584
+
585
+ """
586
+ return message % self .__VERSION__
587
+
518
588
if __name__ == "__main__" :
519
589
myTestLinkServer = "http://YOURSERVER/testlink/lib/api/xmlrpc.php" #change
520
590
myDevKey = "" # Put here your devKey
@@ -530,3 +600,4 @@ def getProjectIDByName(self, projectName):
530
600
print ""
531
601
else :
532
602
print "Incorrect DevKey."
603
+
0 commit comments