Skip to content

Commit bc9bcc2

Browse files
author
Luiko Czub
committed
integrate v0.5.0 listKeyword service methods #25
Merge branch 'master' into tl-future Conflicts: CHANGES.rst src/testlink/version.py
2 parents b8f4a66 + 1cfbe19 commit bc9bcc2

File tree

9 files changed

+229
-13
lines changed

9 files changed

+229
-13
lines changed

CHANGES.rst

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,37 @@ known TL DEV1.9.11 problems
2222
assignTestCaseExecutionTask does not assign user
2323

2424

25-
TestLink-API-Python-client UNDER DEVELOP v0.4.9
26-
-----------------------------------------------------------
25+
TestLink-API-Python-client release notes v0.5.0 (Jul. 2014)
26+
------------------------------------------------------------
27+
support for TestLink release 1.9.10
28+
29+
new service methods - list keywords #25
30+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31+
32+
new TestlinkAPIClient service methods, which returns keyword lists without
33+
internal details (like getTestCasesForTestSuite() does)
34+
35+
- listKeywordsForTC(internal_or_external_tc_id)
36+
- listKeywordsForTC(internal_ts_id)
37+
38+
Example::
39+
40+
>>> import testlink
41+
>>> tls = testlink.TestLinkHelper().connect(testlink.TestlinkAPIClient)
42+
>>> tc_kw = tls.listKeywordsForTC('NPROAPI-3')
43+
['KeyWord01', 'KeyWord03']
44+
>>> tc_kw = tls.listKeywordsForTC(5440)
45+
['KeyWord01', 'KeyWord03']
46+
>>> tc_kw = tls.listKeywordsForTC('5440')
47+
['KeyWord01', 'KeyWord03']
48+
>>> ts_kw = tls.listKeywordsForTS('5415')
49+
{'5440' : ['KeyWord01', 'KeyWord03'], '5445' : ['KeyWord03'], '5450' : []}
50+
51+
52+
Known limitations:
53+
54+
- it is not possible to ask for a special test case version, cause TL links
55+
keywords against a test case and not a test case version
2756

2857
implement 1.9.10 api change - getTestCasesForTestSuite #23
2958
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

doc/install.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ TestLink-API-Python-client Installation
44
Preconditions
55
-------------
66

7-
Currently the combinations Python 2.6.6/2.7.5 and TestLink 1.9.8/1.9.9 are tested.
7+
Currently the combinations Python 2.6.6/2.7.5 and TestLink 1.9.10 are tested.
88

99
- Other combination might work - feedback is welcome :-)
1010

doc/usage.rst

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,29 @@ alternative optional args, default reporter (user for devKey)
9999
>>> tls.reportTCResult(a_TestPlanID, 'b', testcaseexternalid=exTCID,
100100
buildid='a build name', platformname='a platform name')
101101

102+
List keywords
103+
-------------------
104+
105+
Using the api method - keywords for all test cases of one test suite
106+
107+
>>> import testlink
108+
>>> tls = testlink.TestLinkHelper().connect(testlink.TestlinkAPIClient)
109+
>>> ts_kw = tls.getTestCasesForTestSuite(SuiteID, False, 'full', getkeywords=True)
110+
111+
Using the api method - keywords for all test cases of a test suite and their
112+
sub suites
113+
114+
>>> ts_kw = tls.getTestCasesForTestSuite(SuiteID, True, 'full', getkeywords=True)
115+
116+
Using the service method - keyword list without internal details for one test case
117+
118+
>>> tc_kw = tls.listKeywordsForTC(5440)
119+
>>> tc_kw = tls.listKeywordsForTC('NPROAPI-3')
120+
121+
Using the service method - keyword lists without internal details for all test
122+
cases of one test suite
123+
124+
>>> ts_kw = tls.listKeywordsForTS('5415')
102125

103126
Run examples
104127
------------
@@ -118,7 +141,7 @@ parameter defined as environment variables [2]_: ::
118141
set TESTLINK_API_PYTHON_SERVER_URL=http://[YOURSERVER]/testlink/lib/api/xmlrpc/v1/xmlrpc.php
119142
set TESTLINK_API_PYTHON_DEVKEY=[Users devKey generated by TestLink]
120143
python example\TestLinkExampleGenericApi.py
121-
144+
122145
Run unittests
123146
-------------
124147

example/TestLinkExample.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,6 @@
653653
print "Number of TestCases (in TestSuites): %s " % myTestLink.countTestCasesTS()
654654
print "Number of TestCases (in TestPlans) : %s " % myTestLink.countTestCasesTP()
655655
print ""
656-
myTestLink.listProjects()
657656

658657
print
659658
print ""

example/TestLinkExampleCustomFields.py renamed to example/TestLinkExample_CF_KW.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,10 @@
141141
# list test cases with assigned keywords
142142
response = myTestLink.getTestCasesForTestSuite(newTestSuiteID_B, True,
143143
'full', getkeywords=True)
144-
print "getTestCasesForTestSuite", response
144+
print "getTestCasesForTestSuite (deep=True)", response
145+
response = myTestLink.getTestCasesForTestSuite(newTestSuiteID_B, False,
146+
'full', getkeywords=True)
147+
print "getTestCasesForTestSuite (deep=False)", response
145148

146149
# get informationen - TestCase_B
147150
response = myTestLink.getTestCaseIDByName(NEWTESTCASE_B, testprojectname=NEWPROJECT)
@@ -151,6 +154,12 @@
151154
newTestCase_B = myTestLink.getTestCase(testcaseid=newTestCaseID_B)[0]
152155
print "getTestCase", newTestCase_B
153156

157+
# return keyword list for TestCase_B
158+
response = myTestLink.listKeywordsForTC(newTestCaseID_B)
159+
print "listKeywordsForTC", response
160+
# return keyword lists for all test cases of test newTestSuite_B
161+
response = myTestLink.listKeywordsForTS(newTestSuiteID_B)
162+
print "listKeywordsForTS", response
154163

155164
# new execution result with custom field data
156165
# TC_B passed, explicit build and some notes , TC identified with internal id

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070

7171
setup(name='TestLink-API-Python-client',
7272
version=VERSION,
73-
description='Python XML-RPC client for TestLink',
73+
description='Python XML-RPC client for TestLink %s' % TL_RELEASE,
7474
long_description = DESCRIPTION,
7575
author='James Stock, Olivier Renault, Luiko Czub, TestLink-API-Python-client developers',
7676

src/testlink/testlinkapi.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,66 @@ def _copyTCbuildArgs(self, origArgItems, changedArgs, options):
293293

294294
return (posArgValues, newArgItems)
295295

296+
#
297+
# ADDITIONNAL FUNCTIONS- keywords
298+
#
299+
300+
def listKeywordsForTC(self, internal_or_external_tc_id):
301+
""" Returns list with keyword for a test case
302+
INTERNAL_OR_EXTERNAL_TC_ID defines
303+
- either the internal test case ID (8111 or '8111')
304+
- or the full external test case ID ('NPROAPI-2')
305+
306+
Attention:
307+
- the tcversion_id is not supported
308+
- it is not possible to ask for a special test case version, cause TL
309+
links keywords against a test case and not a test case version
310+
"""
311+
312+
a_tc_id = str(internal_or_external_tc_id)
313+
argsPositional = [a_tc_id]
314+
argsOptional = {}
315+
if '-' in a_tc_id:
316+
# full external ID like 'NPROAPI-2'
317+
argsPositional = [None]
318+
argsOptional = {'testcaseexternalid' : a_tc_id}
319+
a_tc = self.getTestCase(*argsPositional, **argsOptional)[0]
320+
a_ts_id = a_tc['testsuite_id']
321+
# attention!
322+
# don't use 'id', that is the tcversion_id
323+
# - table tcversions, field id
324+
# use testcase_id, that is id test case id without a version info
325+
# - table nodes_hierarchy, fied id (condition node_type_id == 3)
326+
a_tc_id = a_tc['testcase_id']
327+
all_tc_for_ts = self.getTestCasesForTestSuite(a_ts_id, False,
328+
'full', getkeywords=True)
329+
330+
keyword_details = {}
331+
332+
for a_ts_tc in all_tc_for_ts:
333+
if a_ts_tc['id'] == a_tc_id:
334+
keyword_details = a_ts_tc.get('keywords', {})
335+
336+
keywords = map((lambda x: x['keyword']), keyword_details.values())
337+
return keywords
338+
339+
def listKeywordsForTS(self, internal_ts_id):
340+
""" Returns dictionary with keyword lists for all test cases of
341+
test suite with id == INTERNAL_TS_ID
342+
"""
343+
344+
a_ts_id = str(internal_ts_id)
345+
all_tc_for_ts = self.getTestCasesForTestSuite(a_ts_id, False,
346+
'full', getkeywords=True)
347+
response = {}
348+
for a_ts_tc in all_tc_for_ts:
349+
tc_id = a_ts_tc['id']
350+
keyword_details = a_ts_tc.get('keywords', {})
351+
keywords = map((lambda x: x['keyword']), keyword_details.values())
352+
response[tc_id] = keywords
353+
354+
return response
355+
296356
#
297357
# ADDITIONNAL FUNCTIONS
298358
#

src/testlink/version.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,6 @@
1717
#
1818
# ------------------------------------------------------------------------
1919

20-
VERSION = '0.5.1-Alpha'
20+
VERSION = '0.5.1-dev25'
21+
TL_RELEASE = 'DEV 1.9.11'
22+

test/utest-offline/testlinkapi_offline_test.py

Lines changed: 99 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@
188188
{'step_number': '7', 'actions': 'action 7 createTestCaseSteps.create', 'execution_type': '2', 'active': '1', 'id': '8157', 'expected_results': 'create - cause step 7 not yet exist'},
189189
{'step_number': '8', 'actions': 'action 8 createTestCaseSteps.update', 'execution_type': '2', 'active': '1', 'id': '8158', 'expected_results': 'create - cause step 8 not yet exist'}],
190190
'author_id': '1'},
191-
{'node_order': '1', 'is_open': '1',
191+
{'node_order': '1', 'is_open': '1',
192192
'keywords': {'2': {'keyword_id': '2', 'notes': 'another key word', 'testcase_id': '8159', 'keyword': 'KeyWord02'}},
193193
'id': '8159', 'node_type_id': '3', 'layout': '1', 'tc_external_id': '3', 'parent_id': '8134', 'version': '1',
194194
'details': '<p>\n\tDetails of the Test Suite B</p>\n', 'estimated_exec_duration': '3.00', 'updater_id': '2', 'status': '1',
@@ -199,7 +199,7 @@
199199
'steps': [{'step_number': '1', 'actions': '<p>\n\tStep action 1 -b2</p>\n', 'execution_type': '2', 'active': '1', 'id': '8161', 'expected_results': '<p>\n\tStep result 1 - b2</p>\n'},
200200
{'step_number': '2', 'actions': '<p>\n\tStep action 2 -b2</p>\n', 'execution_type': '2', 'active': '1', 'id': '8162', 'expected_results': '<p>\n\tStep result 2 - b2</p>\n'}],
201201
'author_id': '2'},
202-
{'node_order': '2', 'is_open': '1',
202+
{'node_order': '2', 'is_open': '1',
203203
'id': '8169', 'node_type_id': '3', 'layout': '1', 'tc_external_id': '4', 'parent_id': '8134', 'version': '1',
204204
'details': '<p>\n\tDetails of the Test Suite B</p>\n', 'estimated_exec_duration': '3.00', 'updater_id': '2', 'status': '1',
205205
'importance': '3', 'modification_ts': '2014-07-02 21:02:23', 'execution_type': '1',
@@ -208,8 +208,44 @@
208208
'summary': '<p>\n\tThis is the summary of the Test Case B3</p>\n',
209209
'steps': [{'step_number': '1', 'actions': '<p>\n\tStep action 1 -b3</p>\n', 'execution_type': '2', 'active': '1', 'id': '8171', 'expected_results': '<p>\n\tStep result 1 - b3</p>\n'},
210210
{'step_number': '2', 'actions': '<p>\n\tStep action 2 -b3</p>\n', 'execution_type': '2', 'active': '1', 'id': '8172', 'expected_results': '<p>\n\tStep result 2 - b3</p>\n'}],
211-
'author_id': '2'}]
212-
}
211+
'author_id': '2'}],
212+
213+
'4711' : [{'node_order': '0', 'is_open': '1',
214+
'keywords': {'1': {'keyword_id': '1', 'notes': 'a key word', 'testcase_id': '8144', 'keyword': 'KeyWord01'},
215+
'3': {'keyword_id': '3', 'notes': 'a third key word', 'testcase_id': '8144', 'keyword': 'KeyWord03'}},
216+
'id': '8144', 'node_type_id': '3', 'layout': '1', 'tc_external_id': '2', 'parent_id': '8134', 'version': '1',
217+
'details': '<p>\n\tDetails of the Test Suite B</p>\n', 'estimated_exec_duration': '3.00', 'updater_id': '2', 'status': '1',
218+
'importance': '3', 'modification_ts': '2014-06-30 20:45:40', 'execution_type': '1',
219+
'preconditions': '<p>\n\tthese are the preconditions</p>\n', 'active': '1', 'creation_ts': '2014-06-28 22:06:17',
220+
'node_table': 'testcases', 'tcversion_id': '8145', 'name': 'TESTCASE_B',
221+
'summary': '<p>\n\tThis is the summary of the Test Case B</p>\n',
222+
'steps': [{'step_number': '1', 'actions': 'Step action 1 -b ', 'execution_type': '2', 'active': '1', 'id': '8151', 'expected_results': 'Step result 1 - b'}],
223+
'author_id': '1'} ],
224+
225+
'noKeywords' : [{'node_order': '0', 'is_open': '1',
226+
'id': '8144', 'node_type_id': '3', 'layout': '1', 'tc_external_id': '2', 'parent_id': '8134', 'version': '1',
227+
'details': '<p>\n\tDetails of the Test Suite B</p>\n', 'estimated_exec_duration': '3.00', 'updater_id': '2', 'status': '1',
228+
'importance': '3', 'modification_ts': '2014-06-30 20:45:40', 'execution_type': '1',
229+
'preconditions': '<p>\n\tthese are the preconditions</p>\n', 'active': '1', 'creation_ts': '2014-06-28 22:06:17',
230+
'node_table': 'testcases', 'tcversion_id': '8145', 'name': 'TESTCASE_B',
231+
'summary': '<p>\n\tThis is the summary of the Test Case B</p>\n',
232+
'steps': [{'step_number': '1', 'actions': 'Step action 1 -b ', 'execution_type': '2', 'active': '1', 'id': '8151', 'expected_results': 'Step result 1 - b'}],
233+
'author_id': '1'} ]
234+
235+
},
236+
'getTestCase' : {
237+
'8144' : [{'full_tc_external_id': 'NPROAPI-2', 'id': '8145', 'tc_external_id': '2', 'version': '1',
238+
'testsuite_id': 'deepFalse3', 'testcase_id': '8144', 'name': 'TESTCASE_B'}],
239+
'NPROAPI-2' : [{'full_tc_external_id': 'NPROAPI-2', 'id': '8145', 'tc_external_id': '2', 'version': '1',
240+
'testsuite_id': 'deepFalse3', 'testcase_id': '8144', 'name': 'TESTCASE_B'}],
241+
'8159' : [{'full_tc_external_id': 'NPROAPI-3', 'id': '8160', 'tc_external_id': '3', 'version': '1',
242+
'testsuite_id': 'deepFalse3', 'testcase_id': '8159', 'name': 'TESTCASE_B2'}],
243+
'NPROAPI-3' : [{'full_tc_external_id': 'NPROAPI-3', 'id': '8160', 'tc_external_id': '3', 'version': '1',
244+
'testsuite_id': 'deepFalse3', 'testcase_id': '8159', 'name': 'TESTCASE_B2'}],
245+
'8169' : [{'full_tc_external_id': 'NPROAPI-4', 'id': '8170', 'tc_external_id': '3', 'version': '1',
246+
'testsuite_id': 'deepFalse3', 'testcase_id': '8169', 'name': 'TESTCASE_B3'}],
247+
'NPROAPI-4' : [{'full_tc_external_id': 'NPROAPI-4', 'id': '8170', 'tc_external_id': '3', 'version': '1',
248+
'testsuite_id': 'deepFalse3', 'testcase_id': '8169', 'name': 'TESTCASE_B3'}] }
213249
}
214250

215251

@@ -245,7 +281,14 @@ def _callServer(self, methodAPI, argsAPI=None):
245281
elif methodAPI in ['getTestCaseIDByName']:
246282
response = data[argsAPI['testcasename']]
247283
elif methodAPI in ['getTestCase']:
248-
response = data['%(testcaseid)s-%(version)s' % argsAPI]
284+
datakey = argsAPI.get('testcaseid')
285+
if datakey:
286+
datakey = str(datakey)
287+
else:
288+
datakey = argsAPI.get('testcaseexternalid', '')
289+
if argsAPI.has_key('version'):
290+
datakey += '-%(version)s' % argsAPI
291+
response = data[datakey]
249292
elif methodAPI in ['getFullPath']:
250293
response = data[argsAPI['nodeid']]
251294
elif methodAPI in ['getTestProjectByName']:
@@ -472,6 +515,57 @@ def test_whatArgs_getTestCasesForTestSuite(self):
472515
argsDescription = self.api.whatArgs('getTestCasesForTestSuite')
473516
self.assertIn('getkeywords=<getkeywords>', argsDescription)
474517

518+
def test_listKeywordsForTC_FullExternalId(self):
519+
self.api.loadScenario(SCENARIO_KEYWORDS)
520+
response = self.api.listKeywordsForTC('NPROAPI-2')
521+
self.assertEqual(['KeyWord01', 'KeyWord03'], response)
522+
523+
def test_listKeywordsForTC_InternalId_Int(self):
524+
self.api.loadScenario(SCENARIO_KEYWORDS)
525+
response = self.api.listKeywordsForTC(8144)
526+
self.assertEqual(['KeyWord01', 'KeyWord03'], response)
527+
528+
def test_listKeywordsForTC_InternalId_String(self):
529+
self.api.loadScenario(SCENARIO_KEYWORDS)
530+
response = self.api.listKeywordsForTC('8144')
531+
self.assertEqual(['KeyWord01', 'KeyWord03'], response)
532+
533+
def test_listKeywordsForTC_One(self):
534+
self.api.loadScenario(SCENARIO_KEYWORDS)
535+
response = self.api.listKeywordsForTC('NPROAPI-3')
536+
self.assertEqual(['KeyWord02'], response)
537+
538+
def test_listKeywordsForTC_None(self):
539+
self.api.loadScenario(SCENARIO_KEYWORDS)
540+
response = self.api.listKeywordsForTC('NPROAPI-4')
541+
self.assertEqual([], response)
542+
543+
def test_listKeywordsForTS_NoneTC(self):
544+
self.api.loadScenario(SCENARIO_KEYWORDS)
545+
response = self.api.listKeywordsForTS('noTestCase')
546+
self.assertEqual({}, response)
547+
548+
def test_listKeywordsForTS_NoneKW(self):
549+
self.api.loadScenario(SCENARIO_KEYWORDS)
550+
response = self.api.listKeywordsForTS('noKeywords')
551+
self.assertEqual({'8144' : []}, response)
552+
553+
def test_listKeywordsForTS_Id_Int(self):
554+
self.api.loadScenario(SCENARIO_KEYWORDS)
555+
response = self.api.listKeywordsForTS(4711)
556+
self.assertEqual({'8144' : ['KeyWord01', 'KeyWord03']}, response)
557+
558+
def test_listKeywordsForTS_Id_String(self):
559+
self.api.loadScenario(SCENARIO_KEYWORDS)
560+
response = self.api.listKeywordsForTS('4711')
561+
self.assertEqual({'8144' : ['KeyWord01', 'KeyWord03']}, response)
562+
563+
def test_listKeywordsForTS_Multi(self):
564+
self.api.loadScenario(SCENARIO_KEYWORDS)
565+
response = self.api.listKeywordsForTS('deepFalse3')
566+
self.assertEqual({'8144' : ['KeyWord01', 'KeyWord03'],
567+
'8159' : ['KeyWord02'], '8169' : []}, response)
568+
475569

476570

477571
if __name__ == "__main__":

0 commit comments

Comments
 (0)