Merge lp:~fgimenez/qakit/snappy into lp:qakit

Proposed by Federico Gimenez
Status: Work in progress
Proposed branch: lp:~fgimenez/qakit/snappy
Merge into: lp:qakit
Diff against target: 386 lines (+114/-69)
6 files modified
qakit/practitest/auth.py (+4/-7)
qakit/practitest/config.ini.sample (+1/-2)
qakit/practitest/practisubunit.py (+1/-5)
qakit/practitest/practitest.py (+38/-22)
qakit/practitest/report_subunit_results_to_practitest.py (+69/-32)
qakit/practitest/subunit_results.py (+1/-1)
To merge this branch: bzr merge lp:~fgimenez/qakit/snappy
Reviewer Review Type Date Requested Status
Canonical Platform QA Team Pending
Review via email: mp+290747@code.launchpad.net

Description of the change

Updated to work with the new token api authentication. Other fixes:

* config file path
* hardcoded filter id moved to arg
* removed hardcoded field ids (in progress)

You can create a TestSet with:

python3 -m qakit.practitest.report_subunit_results_to_practitest results.subunit create name="testing" device="openstack-amd64" level="Regression" release="15.10" build="mybuild" buildinfo="mybuildinfo"

having a config.ini file in qakit/practitest/config.ini (there's a sample in that directory)

And update it with:

python3 -m qakit.practitest.report_subunit_results_to_practitest results.subunit update --no_ask_confirm $TESTSET_DISPLAY_ID

or, if the system_id is available:

python3 -m qakit.practitest.report_subunit_results_to_practitest results.subunit update --no_ask_confirm --testset_system_id $TESTSET_SYSTEM_ID

To post a comment you must log in.
lp:~fgimenez/qakit/snappy updated
52. By Federico Gimenez

Fixed update test_number argument name; prevented duplicated tests in new test set

53. By Federico Gimenez

Extract id from name

54. By Federico Gimenez

Do not return 'exists' entries when getting tests by name

55. By Federico Gimenez

optional confirm; enabled system_id as param

56. By Federico Gimenez

system_id path of execution for updates refactored

57. By Federico Gimenez

create action does not require a results file

58. By Federico Gimenez

making logger to write to stdout

59. By Federico Gimenez

reverted build and buildinfo, added ids

Unmerged revisions

59. By Federico Gimenez

reverted build and buildinfo, added ids

58. By Federico Gimenez

making logger to write to stdout

57. By Federico Gimenez

create action does not require a results file

56. By Federico Gimenez

system_id path of execution for updates refactored

55. By Federico Gimenez

optional confirm; enabled system_id as param

54. By Federico Gimenez

Do not return 'exists' entries when getting tests by name

53. By Federico Gimenez

Extract id from name

52. By Federico Gimenez

Fixed update test_number argument name; prevented duplicated tests in new test set

51. By Federico Gimenez

updated to token auth; added custom_filter_id param; updated field ids (more iterations on this soon)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'qakit/practitest/auth.py'
2--- qakit/practitest/auth.py 2015-06-23 14:57:17 +0000
3+++ qakit/practitest/auth.py 2016-04-06 13:11:29 +0000
4@@ -19,15 +19,12 @@
5 import time
6
7
8-def compose_headers(api_key, api_secret_key, content_type='application/json'):
9- """Return auth headers incorporating give api key details."""
10- ts = str(int(time.time()))
11- signature = hashlib.md5(
12- (api_key+api_secret_key+ts).encode()).hexdigest()
13+def compose_headers(api_token, content_type='application/json'):
14+ """Return auth headers incorporating give api token details."""
15 auth_header = {
16 'Authorization':
17- 'custom api_key={}, signature={}, ts={}'.format(
18- api_key, signature, ts)
19+ 'custom api_token={}'.format(
20+ api_token)
21 }
22 if content_type is not None:
23 auth_header['Content-Type'] = content_type
24
25=== modified file 'qakit/practitest/config.ini.sample'
26--- qakit/practitest/config.ini.sample 2015-04-15 19:03:17 +0000
27+++ qakit/practitest/config.ini.sample 2016-04-06 13:11:29 +0000
28@@ -1,6 +1,5 @@
29 [DEFAULT]
30 PRACTITEST_PROJECT_ID = <PROJECT ID>
31-PRACTITEST_API_KEY = <API KEY>
32-PRACTITEST_API_SECRET_KEY = <API SECRET KEY>
33+PRACTITEST_API_TOKEN = <API TOKEN>
34 PRACTITEST_USER_EMAIL = <EMAIL ADDRESS>
35 LP_SUBSCRIBE=<LP USER ID>
36
37=== modified file 'qakit/practitest/practisubunit.py'
38--- qakit/practitest/practisubunit.py 2015-06-28 13:29:54 +0000
39+++ qakit/practitest/practisubunit.py 2016-04-06 13:11:29 +0000
40@@ -69,11 +69,7 @@
41 # NOTE: this is the expensive operation--need the tests
42 # list b/c custom fields appear in the *test* only, need
43 # to make a relation between instance and test on name
44- subunit_test_name = \
45- self.practisubunit_session.get_instance_custom_field(
46- practitest_instance,
47- 'External ID',
48- practitest_tests)
49+ subunit_test_name = practitest_instance['name']
50 if subunit_test_name:
51 result['test_name'] = subunit_test_name
52 subunit_result = \
53
54=== modified file 'qakit/practitest/practitest.py'
55--- qakit/practitest/practitest.py 2015-11-30 18:24:48 +0000
56+++ qakit/practitest/practitest.py 2016-04-06 13:11:29 +0000
57@@ -68,21 +68,19 @@
58
59 class PractitestSession:
60
61- def __init__(self, project_id, api_key, api_secret_key, user_email=None):
62+ def __init__(self, project_id, api_token, user_email=None):
63 self.project_id = project_id
64- self.api_key = api_key
65- self.api_secret_key = api_secret_key
66+ self.api_token = api_token
67 self.user_email = user_email
68
69 def pt_field(self, name):
70 """Maps PT fields to their IDs"""
71- PT_FIELDS = {'device': 10476,
72- 'level': 10490,
73- 'release': 10433,
74- 'build': 10578,
75- 'buildinfo': 10872,
76- 'external_id': 10589,
77- 'tester': 30429
78+ PT_FIELDS = {'device': 17224,
79+ 'level': 17221,
80+ 'release': 17220,
81+ 'build': 17213,
82+ 'buildinfo': 17214,
83+ 'external_id': 17219
84 }
85 return '___f_{}'.format(PT_FIELDS[name])
86
87@@ -95,15 +93,14 @@
88 response = requests.get(
89 url=url,
90 headers=auth.compose_headers(
91- self.api_key,
92- self.api_secret_key),
93+ self.api_token),
94 data=json.dumps(params))
95 response.raise_for_status()
96 return response
97
98
99 def _get_all(self, url, params={}):
100-
101+
102 def needs_new_page(pagination):
103 total_read = int(pagination['page']) * int(pagination['limit'])
104 return int(pagination['total_entities']) - total_read > 0
105@@ -134,7 +131,7 @@
106 logging.debug(
107 'Posting to {} with data {} and files {}'.format(
108 url, data, files
109- )
110+ )
111 )
112 content_type = None
113 if not files:
114@@ -145,8 +142,7 @@
115 data=data,
116 files=files,
117 headers=auth.compose_headers(
118- self.api_key,
119- self.api_secret_key,
120+ self.api_token,
121 content_type=content_type
122 )
123 )
124@@ -162,8 +158,7 @@
125 url=url,
126 data=json.dumps(data),
127 headers=auth.compose_headers(
128- self.api_key,
129- self.api_secret_key
130+ self.api_token
131 )
132 )
133 return req
134@@ -194,7 +189,7 @@
135 return self._get(url).json()
136
137 def get_testset(self, id):
138- """Return a testset given its id.
139+ """Return a testset given its display_id.
140
141 See http://support.practitest.com/customer/portal/articles/1140223-testsets-api . # NOQA
142
143@@ -209,9 +204,30 @@
144 raise ValueError("TestSet {} not found!".format(id))
145 else:
146 raise
147-
148-
149- def create_testset(self, name, priority, device,
150+
151+ def get_testset_by_display_id(self, id):
152+ return self.get_testset(id)
153+
154+ def get_testset_by_system_id(self, system_id):
155+ display_id = self._get_testset_display_id_by_field('system_id', system_id)
156+ return self.get_testset(display_id)
157+
158+ def _get_testset_display_id_by_field(self, field_name, field_value):
159+ """Return a testset display_id given a field name and value.
160+
161+ See http://support.practitest.com/customer/portal/articles/1140223-testsets-api . # NOQA
162+
163+ :param field_name: PractiTest field name.
164+ :param field_value: PractiTest field value for the given field name.
165+
166+ """
167+ url = PROD_PRACTITEST + '/sets.json'
168+ testsets=self._get(url).json()
169+ for testset in testsets['data']:
170+ if testset[field_name] == field_value:
171+ return testset['display_id']
172+
173+ def create_testset(self, name, priority, device,
174 level, release, build, buildinfo):
175 """
176 Create a test set with the name and priority provided.
177
178=== modified file 'qakit/practitest/report_subunit_results_to_practitest.py'
179--- qakit/practitest/report_subunit_results_to_practitest.py 2015-09-08 19:35:55 +0000
180+++ qakit/practitest/report_subunit_results_to_practitest.py 2016-04-06 13:11:29 +0000
181@@ -17,6 +17,7 @@
182
183 import argparse
184 import configparser
185+import logging
186 import os
187 import sys
188
189@@ -28,23 +29,49 @@
190 'Sanity/Mako': '55739',
191 'Web': '55419'}
192
193+logger = logging.getLogger(__name__)
194+logger.setLevel(logging.INFO)
195+stdout_handler = logging.StreamHandler(sys.stdout)
196+logger.addHandler(stdout_handler)
197
198 def _parse_arguments():
199 """Parse command-line args, returning an argparse dict."""
200 parser = argparse.ArgumentParser(
201 'Report subunit suite results to Practitest.')
202- parser.add_argument('filepath', help='subunit result filepath')
203 subparsers = parser.add_subparsers()
204 update_parser = subparsers.add_parser(
205 'update',
206 help='Update an existing test set with results'
207 )
208 update_parser.add_argument(
209- 'number',
210- type=int,
211- help='PractiTest TestSet #'
212- )
213- update_parser.set_defaults(func=_update_testset)
214+ 'testset_display_id',
215+ default=0,
216+ nargs='?',
217+ type=int,
218+ help='PractiTest TestSet display id',
219+ )
220+ update_parser.add_argument(
221+ '--testset_system_id',
222+ type=int,
223+ help='PractiTest TestSet system id'
224+ )
225+ update_parser.add_argument(
226+ '--ask_confirm',
227+ dest='ask_confirm',
228+ action='store_true',
229+ help='Ask confirmation for uploading results'
230+ )
231+ update_parser.add_argument(
232+ '--no_ask_confirm',
233+ dest='ask_confirm',
234+ action='store_false',
235+ help='Ask confirmation for uploading results'
236+ )
237+ update_parser.add_argument(
238+ 'filepath',
239+ help='subunit result filepath'
240+ )
241+ update_parser.set_defaults(func=_update_testset, ask_confirm=True)
242 create_parser = subparsers.add_parser(
243 'create',
244 help='Create a new testset with the results'
245@@ -74,6 +101,10 @@
246 help='The output of system-image-cli -i',
247 )
248 create_parser.add_argument(
249+ '--custom_filter_id',
250+ help='Custom test filter, if any',
251+ )
252+ create_parser.add_argument(
253 '--manual', '-m',
254 help='Add the manual tests for the specified domain '
255 'to the test set as well.'
256@@ -82,7 +113,7 @@
257 return parser.parse_args()
258
259
260-def _confirm_name_of_testset(practitest_testset_number,
261+def _confirm_name_of_testset(practitest_testset_display_id,
262 practitest_session):
263 """Double-check the name and assigned tester of the numbered TestSet.
264
265@@ -90,11 +121,11 @@
266 wrong TestSet, e.g.
267
268 """
269- testset = practitest_session.get_testset(practitest_testset_number)
270+ testset = practitest_session.get_testset(practitest_testset_display_id)
271 confirmation = input(
272 ("TestSet {}: '{}', assigned to {}--"
273 "upload test results (Y/n)? ").format(
274- practitest_testset_number,
275+ practitest_testset_display_id,
276 testset['name'],
277 testset['assigned_to']['value']))
278 return confirmation != 'n'
279@@ -119,28 +150,32 @@
280 config_file.read(config_filepath)
281 config = {}
282 for var_name in ('PRACTITEST_PROJECT_ID',
283- 'PRACTITEST_API_KEY',
284- 'PRACTITEST_API_SECRET_KEY'):
285+ 'PRACTITEST_API_TOKEN'):
286 new_var_name = var_name.lower().replace('practitest_', '')
287 config[new_var_name] = _read_config_for_var(var_name,
288 config_file)
289 return config
290
291
292-def _create_testset(args, practisubunit_session, results):
293+def _create_testset(args, practisubunit_session):
294 testset = practisubunit_session.create_testset(
295 args.name, 'medium',
296 args.device, args.level,
297 args.release, args.build,
298 args.buildinfo
299 )
300- _create_instances(results, testset, practisubunit_session,
301- args.manual)
302+ _create_instances(testset, practisubunit_session,
303+ args.custom_filter_id, args.manual)
304 return testset
305
306-def _update_testset(args, practisubunit_session):
307- _confirm_name_of_testset(args.testset_number, practisubunit_session)
308- testset = practisubunit_session.get_testset(args.testset_number)
309+def _update_testset(args, practisubunit_session, results):
310+ if args.ask_confirm:
311+ _confirm_name_of_testset(args.testset_display_id, practisubunit_session)
312+
313+ if args.testset_display_id != 0:
314+ testset = practisubunit_session.get_testset_by_display_id(args.testset_display_id)
315+ else:
316+ testset = practisubunit_session.get_testset_by_system_id(args.testset_system_id)
317 return testset
318
319 def _report_to_practitest(project_id, testset, practisubunit_session, results):
320@@ -156,7 +191,7 @@
321 )
322 )
323
324-def _create_instances(results, testset, session, manual=None):
325+def _create_instances(testset, session, custom_filter_id, manual=None):
326 # First get all the automated tests in PractiTest
327 # 57803 is the ID of the 'Automated' filter
328 instances = []
329@@ -165,16 +200,8 @@
330 manual_ids = [test['system_id'] for test in tests]
331 instances.extend(manual_ids)
332 else:
333- tests = session.get_tests(filter_id='57803')
334- external_ids = [test[session.pt_field('external_id')]['value']
335- for test in tests]
336- for test in results:
337- try:
338- instances.append(
339- tests[external_ids.index(test['id'])]['system_id']
340- )
341- except ValueError:
342- continue
343+ instances = [test['system_id'] for test in session.get_tests(
344+ filter_id=custom_filter_id)]
345
346 session.create_instances(testset['id'], instances)
347
348@@ -182,12 +209,22 @@
349 def main():
350 args = _parse_arguments()
351 config = _read_config(
352- os.path.join(os.path.dirname(__name__),
353+ os.path.join(os.path.dirname(__file__),
354 'config.ini'))
355 practisubunit_session = practisubunit.PractiSubunitSession(**config)
356- results = subunit_results.parse(args.filepath)
357- testset = args.func(args, practisubunit_session, results)
358- _report_to_practitest(config['project_id'], testset, practisubunit_session, results)
359+ if args.func.__name__ == '_create_testset':
360+ testset=_create_testset(args, practisubunit_session)
361+ logger.info(
362+ 'Created TestSet with display_id {}'.format(testset['id']))
363+ else:
364+ results = subunit_results.parse(args.filepath)
365+ testset = _update_testset(args, practisubunit_session, results)
366+ _report_to_practitest(
367+ config['project_id'],
368+ testset,
369+ practisubunit_session,
370+ results
371+ )
372
373 if __name__ == '__main__':
374 sys.exit(main())
375
376=== modified file 'qakit/practitest/subunit_results.py'
377--- qakit/practitest/subunit_results.py 2015-04-15 19:03:17 +0000
378+++ qakit/practitest/subunit_results.py 2016-04-06 13:11:29 +0000
379@@ -38,6 +38,6 @@
380 def get_subunit_test_by_name(test_name, subunit_results):
381 """Returns the named test from the given subunit suite."""
382 for result in subunit_results:
383- if result['id'] == test_name:
384+ if result['id'] == test_name and result['status'] != 'exists':
385 return result
386 return None

Subscribers

People subscribed via source and target branches