Merge lp:~tsimonq2/ubuntu-qa-website/python-library-merge into lp:ubuntu-qa-website

Proposed by Simon Quigley
Status: Merged
Merged at revision: 427
Proposed branch: lp:~tsimonq2/ubuntu-qa-website/python-library-merge
Merge into: lp:ubuntu-qa-website
Diff against target: 1271 lines (+1210/-0)
12 files modified
python-library/qatracker.py (+535/-0)
python-library/tests/run (+35/-0)
python-library/tests/setup.sql (+4/-0)
python-library/tests/test_bug.py (+17/-0)
python-library/tests/test_build.py (+98/-0)
python-library/tests/test_milestone.py (+56/-0)
python-library/tests/test_product.py (+51/-0)
python-library/tests/test_rebuilds.py (+69/-0)
python-library/tests/test_result.py (+173/-0)
python-library/tests/test_rpc.py (+27/-0)
python-library/tests/test_series.py (+77/-0)
python-library/tests/test_testcase.py (+68/-0)
To merge this branch: bzr merge lp:~tsimonq2/ubuntu-qa-website/python-library-merge
Reviewer Review Type Date Requested Status
Nicholas Skaggs Pending
Review via email: mp+287711@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'python-library'
=== added file 'python-library/qatracker.py'
--- python-library/qatracker.py 1970-01-01 00:00:00 +0000
+++ python-library/qatracker.py 2016-03-01 21:32:25 +0000
@@ -0,0 +1,535 @@
1#!/usr/bin/python3
2# -*- coding: utf-8 -*-
3
4# Copyright (C) 2011, 2012 Canonical Ltd.
5# Author: Stéphane Graber <stgraber@ubuntu.com>
6
7# This library is free software; you can redistribute it and/or
8# modify it under the terms of the GNU Lesser General Public
9# License as published by the Free Software Foundation; either
10# version 2.1 of the License, or (at your option) any later version.
11
12# This library is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15# Lesser General Public License for more details.
16
17# You should have received a copy of the GNU Lesser General Public
18# License along with this library; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
20# USA
21
22try:
23 import xmlrpc.client as xmlrpclib
24except ImportError:
25 import xmlrpclib
26
27import base64
28from datetime import datetime
29
30# Taken from qatracker/qatracker.modules (PHP code)
31# cat qatracker.module | grep " = array" | sed -e 's/^\$//g' \
32# -e 's/array(/[/g' -e 's/);/]/g' -e "s/t('/\"/g" -e "s/')/\"/g"
33### AUTO-GENERATED ->
34qatracker_build_milestone_status = ["Active", "Re-building", "Disabled",
35 "Superseded", "Ready"]
36qatracker_milestone_notify = ["No", "Yes"]
37qatracker_milestone_autofill = ["No", "Yes"]
38qatracker_milestone_status = ["Testing", "Released", "Archived"]
39qatracker_milestone_series_status = ["Active", "Disabled"]
40qatracker_milestone_series_manifest_status = ["Active", "Disabled"]
41qatracker_product_status = ["Active", "Disabled"]
42qatracker_product_type = ["iso", "package", "hardware"]
43qatracker_product_download_type = ["HTTP", "RSYNC", "ZSYNC",
44 "GPG signature", "MD5 checksum", "Comment",
45 "Torrent"]
46qatracker_testsuite_testcase_status = ["Mandatory", "Disabled", "Run-once",
47 "Optional"]
48qatracker_result_result = ["Failed", "Passed", "In progress"]
49qatracker_result_status = ["Active", "Disabled"]
50qatracker_rebuild_status = ["Requested", "Queued", "Building", "Built",
51 "Published", "Canceled"]
52### <- AUTO-GENERATED
53
54
55class QATrackerRPCObject():
56 """Base class for objects received over XML-RPC"""
57
58 CONVERT_BOOL = []
59 CONVERT_DATE = []
60 CONVERT_INT = []
61
62 def __init__(self, tracker, rpc_dict):
63 # Convert the dict we get from the API into an object
64
65 for key in rpc_dict:
66 if key in self.CONVERT_INT:
67 try:
68 setattr(self, key, int(rpc_dict[key]))
69 except ValueError:
70 setattr(self, key, None)
71 elif key in self.CONVERT_BOOL:
72 setattr(self, key, rpc_dict[key] == "true")
73 elif key in self.CONVERT_DATE:
74 try:
75 setattr(self, key, datetime.strptime(rpc_dict[key],
76 '%Y-%m-%d %H:%M:%S'))
77 except ValueError:
78 setattr(self, key, None)
79 else:
80 setattr(self, key, str(rpc_dict[key]))
81
82 self.tracker = tracker
83
84 def __repr__(self):
85 return "%s: %s" % (self.__class__.__name__, self.title)
86
87
88class QATrackerBug(QATrackerRPCObject):
89 """A bug entry"""
90
91 CONVERT_INT = ['bugnumber', 'count']
92 CONVERT_DATE = ['earliest_report', 'latest_report']
93
94 def __repr__(self):
95 return "%s: %s" % (self.__class__.__name__, self.bugnumber)
96
97
98class QATrackerBuild(QATrackerRPCObject):
99 """A build entry"""
100
101 CONVERT_INT = ['id', 'productid', 'userid', 'status']
102 CONVERT_DATE = ['date']
103
104 def __repr__(self):
105 return "%s: %s" % (self.__class__.__name__, self.id)
106
107 def add_result(self, testcase, result, comment='', hardware='', bugs={}):
108 """Add a result to the build"""
109
110 if (self.tracker.access not in ("user", "admin") and
111 self.tracker.access is not None):
112 raise Exception("Access denied, you need 'user' but are '%s'" %
113 self.tracker.access)
114
115 build_testcase = None
116
117 # FIXME: Supporting 'str' containing the testcase name would be nice
118 if isinstance(testcase, QATrackerTestcase):
119 build_testcase = testcase.id
120 elif isinstance(testcase, int):
121 build_testcase = testcase
122
123 if not build_testcase:
124 raise IndexError("Couldn't find testcase: %s" % (testcase,))
125
126 if isinstance(result, list):
127 raise TypeError("result must be a string or an integer")
128
129 build_result = self.tracker._get_valid_id_list(qatracker_result_result,
130 result)
131
132 if not isinstance(bugs, dict):
133 raise TypeError("bugs must be a dict")
134
135 for bug in bugs:
136 if not isinstance(bug, int) or bug <= 0:
137 raise ValueError("A bugnumber must be a number >= 0")
138
139 if not isinstance(bugs[bug], int) or bugs[bug] not in (0, 1):
140 raise ValueError("A bugimportance must be in (0,1)")
141
142 resultid = int(self.tracker.tracker.results.add(self.id,
143 build_testcase,
144 build_result[0],
145 str(comment),
146 str(hardware),
147 bugs))
148 if resultid == -1:
149 raise Exception("Couldn't post your result.")
150
151 new_result = None
152 for entry in self.get_results(build_testcase, 0):
153 if entry.id == resultid:
154 new_result = entry
155 break
156
157 return new_result
158
159 def get_results(self, testcase, status=qatracker_result_status):
160 """Get a list of results for the given build and testcase"""
161
162 build_testcase = None
163
164 # FIXME: Supporting 'str' containing the testcase name would be nice
165 if isinstance(testcase, QATrackerTestcase):
166 build_testcase = testcase.id
167 elif isinstance(testcase, int):
168 build_testcase = testcase
169
170 if not build_testcase:
171 raise IndexError("Couldn't find testcase: %s" % (testcase,))
172
173 record_filter = self.tracker._get_valid_id_list(
174 qatracker_result_status,
175 status)
176
177 if len(record_filter) == 0:
178 return []
179
180 results = []
181 for entry in self.tracker.tracker.results.get_list(
182 self.id, build_testcase, list(record_filter)):
183 results.append(QATrackerResult(self.tracker, entry))
184
185 return results
186
187
188class QATrackerMilestone(QATrackerRPCObject):
189 """A milestone entry"""
190
191 CONVERT_INT = ['id', 'status', 'series']
192 CONVERT_BOOL = ['notify']
193
194 def get_bugs(self):
195 """Returns a list of all bugs linked to this milestone"""
196
197 bugs = []
198 for entry in self.tracker.tracker.bugs.get_list(self.id):
199 bugs.append(QATrackerBug(self.tracker, entry))
200
201 return bugs
202
203 def add_build(self, product, version, note="", notify=True):
204 """Add a build to the milestone"""
205
206 if self.status != 0:
207 raise TypeError("Only active milestones are accepted")
208
209 if self.tracker.access != "admin" and self.tracker.access is not None:
210 raise Exception("Access denied, you need 'admin' but are '%s'" %
211 self.tracker.access)
212
213 if not isinstance(notify, bool):
214 raise TypeError("notify must be a boolean")
215
216 build_product = None
217
218 if isinstance(product, QATrackerProduct):
219 build_product = product
220 else:
221 valid_products = self.tracker.get_products(0)
222
223 for entry in valid_products:
224 if (entry.title.lower() == str(product).lower() or
225 entry.id == product):
226 build_product = entry
227 break
228
229 if not build_product:
230 raise IndexError("Couldn't find product: %s" % product)
231
232 if build_product.status != 0:
233 raise TypeError("Only active products are accepted")
234
235 self.tracker.tracker.builds.add(build_product.id, self.id,
236 str(version), str(note), notify)
237
238 new_build = None
239 for entry in self.get_builds(0):
240 if (entry.productid == build_product.id
241 and entry.version == str(version)):
242 new_build = entry
243 break
244
245 return new_build
246
247 def get_builds(self, status=qatracker_build_milestone_status):
248 """Get a list of builds for the milestone"""
249
250 record_filter = self.tracker._get_valid_id_list(
251 qatracker_build_milestone_status, status)
252
253 if len(record_filter) == 0:
254 return []
255
256 builds = []
257 for entry in self.tracker.tracker.builds.get_list(self.id,
258 list(record_filter)):
259 builds.append(QATrackerBuild(self.tracker, entry))
260
261 return builds
262
263
264class QATrackerProduct(QATrackerRPCObject):
265 CONVERT_INT = ['id', 'type', 'status']
266
267 def get_testcases(self, series,
268 status=qatracker_testsuite_testcase_status):
269 """Get a list of testcases associated with the product"""
270
271 record_filter = self.tracker._get_valid_id_list(
272 qatracker_testsuite_testcase_status, status)
273
274 if len(record_filter) == 0:
275 return []
276
277 if isinstance(series, QATrackerMilestone):
278 seriesid = series.series
279 elif isinstance(series, int):
280 seriesid = series
281 else:
282 raise TypeError("series needs to be a valid QATrackerMilestone"
283 " instance or an integer")
284
285 testcases = []
286 for entry in self.tracker.tracker.testcases.get_list(
287 self.id, seriesid, list(record_filter)):
288 testcases.append(QATrackerTestcase(self.tracker, entry))
289
290 return testcases
291
292
293class QATrackerRebuild(QATrackerRPCObject):
294 CONVERT_INT = ['id', 'seriesid', 'productid', 'milestoneid', 'requestedby',
295 'changedby', 'status']
296 CONVERT_DATE = ['requestedat', 'changedat']
297
298 def __repr__(self):
299 return "%s: %s" % (self.__class__.__name__, self.id)
300
301 def save(self):
302 """Save any change that happened on this entry.
303 NOTE: At the moment only supports the status field."""
304
305 if (self.tracker.access != "admin" and
306 self.tracker.access is not None):
307 raise Exception("Access denied, you need 'admin' but are '%s'" %
308 self.tracker.access)
309
310 retval = self.tracker.tracker.rebuilds.update_status(self.id,
311 self.status)
312 if retval is not True:
313 raise Exception("Failed to update rebuild")
314
315 return retval
316
317
318class QATrackerResult(QATrackerRPCObject):
319 CONVERT_INT = ['id', 'reporterid', 'revisionid', 'result', 'changedby',
320 'status']
321 CONVERT_DATE = ['date', 'lastchange']
322 __deleted = False
323
324 def __repr__(self):
325 return "%s: %s" % (self.__class__.__name__, self.id)
326
327 def delete(self):
328 """Remove the result from the tracker"""
329
330 if (self.tracker.access not in ("user", "admin") and
331 self.tracker.access is not None):
332 raise Exception("Access denied, you need 'user' but are '%s'" %
333 self.tracker.access)
334
335 if self.__deleted:
336 raise IndexError("Result has already been removed")
337
338 retval = self.tracker.tracker.results.delete(self.id)
339 if retval is not True:
340 raise Exception("Failed to remove result")
341
342 self.status = 1
343 self.__deleted = True
344
345 def save(self):
346 """Save any change that happened on this entry"""
347
348 if (self.tracker.access not in ("user", "admin") and
349 self.tracker.access is not None):
350 raise Exception("Access denied, you need 'user' but are '%s'" %
351 self.tracker.access)
352
353 if self.__deleted:
354 raise IndexError("Result no longer exists")
355
356 retval = self.tracker.tracker.results.update(self.id, self.result,
357 self.comment,
358 self.hardware,
359 self.bugs)
360 if retval is not True:
361 raise Exception("Failed to update result")
362
363 return retval
364
365
366class QATrackerSeries(QATrackerRPCObject):
367 CONVERT_INT = ['id', 'status']
368
369 def get_manifest(self, status=qatracker_milestone_series_manifest_status):
370 """Get a list of products in the series' manifest"""
371
372 record_filter = self.tracker._get_valid_id_list(
373 qatracker_milestone_series_manifest_status, status)
374
375 if len(record_filter) == 0:
376 return []
377
378 manifest_entries = []
379 for entry in self.tracker.tracker.series.get_manifest(
380 self.id, list(record_filter)):
381 manifest_entries.append(QATrackerSeriesManifest(
382 self.tracker, entry))
383
384 return manifest_entries
385
386
387class QATrackerSeriesManifest(QATrackerRPCObject):
388 CONVERT_INT = ['id', 'productid', 'status']
389
390 def __repr__(self):
391 return "%s: %s" % (self.__class__.__name__, self.product_title)
392
393
394class QATrackerTestcase(QATrackerRPCObject):
395 CONVERT_INT = ['id', 'status', 'weight', 'suite']
396
397
398class QATracker():
399 def __init__(self, url, username=None, password=None):
400 class AuthTransport(xmlrpclib.Transport):
401 def set_auth(self, auth):
402 self.auth = auth
403
404 def get_host_info(self, host):
405 host, extra_headers, x509 = \
406 xmlrpclib.Transport.get_host_info(self, host)
407 if extra_headers is None:
408 extra_headers = []
409 extra_headers.append(('Authorization', 'Basic %s' % auth))
410 return host, extra_headers, x509
411
412 if username and password:
413 try:
414 auth = str(base64.b64encode(
415 bytes('%s:%s' % (username, password), 'utf-8')),
416 'utf-8')
417 except TypeError:
418 auth = base64.b64encode('%s:%s' % (username, password))
419
420 transport = AuthTransport()
421 transport.set_auth(auth)
422 drupal = xmlrpclib.ServerProxy(url, transport=transport)
423 else:
424 drupal = xmlrpclib.ServerProxy(url)
425
426 # Call listMethods() so if something is wrong we know it immediately
427 drupal.system.listMethods()
428
429 # Get our current access
430 self.access = drupal.qatracker.get_access()
431
432 self.tracker = drupal.qatracker
433
434 def _get_valid_id_list(self, status_list, status):
435 """ Get a list of valid keys and a list or just a single
436 entry of input to check against the list of valid keys.
437 The function looks for valid indexes and content, doing
438 case insensitive checking for strings and returns a list
439 of indexes for the list of valid keys. """
440
441 def process(status_list, status):
442 valid_status = [entry.lower() for entry in status_list]
443
444 if isinstance(status, int):
445 if status < 0 or status >= len(valid_status):
446 raise IndexError("Invalid status: %s" % status)
447 return int(status)
448
449 if isinstance(status, str):
450 status = status.lower()
451 if status not in valid_status:
452 raise IndexError("Invalid status: %s" % status)
453 return valid_status.index(status)
454
455 raise TypeError("Invalid status type: %s (expected str or int)" %
456 type(status))
457
458 record_filter = set()
459
460 if isinstance(status, list):
461 for entry in status:
462 record_filter.add(process(status_list, entry))
463 else:
464 record_filter.add(process(status_list, status))
465
466 return list(record_filter)
467
468 def get_bugs(self):
469 """Get a list of all bugs reported on the site"""
470
471 bugs = []
472 for entry in self.tracker.bugs.get_list(0):
473 bugs.append(QATrackerBug(self, entry))
474
475 return bugs
476
477 def get_milestones(self, status=qatracker_milestone_status):
478 """Get a list of all milestones"""
479
480 record_filter = self._get_valid_id_list(qatracker_milestone_status,
481 status)
482
483 if len(record_filter) == 0:
484 return []
485
486 milestones = []
487 for entry in self.tracker.milestones.get_list(list(record_filter)):
488 milestones.append(QATrackerMilestone(self, entry))
489
490 return milestones
491
492 def get_products(self, status=qatracker_product_status):
493 """Get a list of all products"""
494
495 record_filter = self._get_valid_id_list(qatracker_product_status,
496 status)
497
498 if len(record_filter) == 0:
499 return []
500
501 products = []
502 for entry in self.tracker.products.get_list(list(record_filter)):
503 products.append(QATrackerProduct(self, entry))
504
505 return products
506
507 def get_rebuilds(self, status=qatracker_rebuild_status):
508 """Get a list of all rebuilds"""
509
510 record_filter = self._get_valid_id_list(
511 qatracker_rebuild_status, status)
512
513 if len(record_filter) == 0:
514 return []
515
516 rebuilds = []
517 for entry in self.tracker.rebuilds.get_list(list(record_filter)):
518 rebuilds.append(QATrackerRebuild(self, entry))
519
520 return rebuilds
521
522 def get_series(self, status=qatracker_milestone_series_status):
523 """Get a list of all series"""
524
525 record_filter = self._get_valid_id_list(
526 qatracker_milestone_series_status, status)
527
528 if len(record_filter) == 0:
529 return []
530
531 series = []
532 for entry in self.tracker.series.get_list(list(record_filter)):
533 series.append(QATrackerSeries(self, entry))
534
535 return series
0536
=== added directory 'python-library/tests'
=== added file 'python-library/tests/run'
--- python-library/tests/run 1970-01-01 00:00:00 +0000
+++ python-library/tests/run 2016-03-01 21:32:25 +0000
@@ -0,0 +1,35 @@
1#!/usr/bin/python3
2import unittest
3import os
4import re
5import shutil
6import sys
7
8coverage = True
9try:
10 from coverage import coverage
11 cov = coverage()
12 cov.start()
13except ImportError:
14 print("No coverage report, make sure python-coverage is installed")
15 coverage = False
16
17sys.path.insert(0, '.')
18
19if len(sys.argv) > 1:
20 test_filter = sys.argv[1]
21else:
22 test_filter = ''
23
24tests = [t[:-3] for t in os.listdir('tests')
25 if t.startswith('test_') and t.endswith('.py') and
26 re.search(test_filter, t)]
27tests.sort()
28suite = unittest.TestLoader().loadTestsFromNames(tests)
29res = unittest.TextTestRunner(verbosity=2).run(suite)
30
31if coverage:
32 if os.path.exists('tests/coverage'):
33 shutil.rmtree('tests/coverage')
34 cov.stop()
35 cov.html_report(include=["qatracker.py"], directory='tests/coverage')
036
=== added file 'python-library/tests/setup.sql'
--- python-library/tests/setup.sql 1970-01-01 00:00:00 +0000
+++ python-library/tests/setup.sql 2016-03-01 21:32:25 +0000
@@ -0,0 +1,4 @@
1INSERT INTO users (uid, name, data, status) VALUES (99999, 'user', 'a:1:{s:17:"qatracker_api_key";s:4:"user";}', 1);
2INSERT INTO users (uid, name, data, status) VALUES (99998, 'admin', 'a:1:{s:17:"qatracker_api_key";s:5:"admin";}', 1);
3INSERT INTO users_roles (uid, rid) VALUES (99999, 2);
4INSERT INTO users_roles (uid, rid) VALUES (99998, 4);
05
=== added file 'python-library/tests/test_bug.py'
--- python-library/tests/test_bug.py 1970-01-01 00:00:00 +0000
+++ python-library/tests/test_bug.py 2016-03-01 21:32:25 +0000
@@ -0,0 +1,17 @@
1import unittest
2import qatracker
3import datetime
4
5URL = 'http://iso.qa.dev.stgraber.org/xmlrpc.php'
6
7
8class BugTests(unittest.TestCase):
9 def setUp(self):
10 self.instance = qatracker.QATracker(URL)
11
12 def test_all_bugs(self):
13 bugs = self.instance.get_bugs()
14 if bugs:
15 self.assertIsInstance(bugs[0].bugnumber, int)
16 self.assertIsInstance(bugs[0].earliest_report, datetime.datetime)
17 self.assertTrue(str(bugs[0]).startswith('QATrackerBug: '))
018
=== added file 'python-library/tests/test_build.py'
--- python-library/tests/test_build.py 1970-01-01 00:00:00 +0000
+++ python-library/tests/test_build.py 2016-03-01 21:32:25 +0000
@@ -0,0 +1,98 @@
1import unittest
2import qatracker
3
4URL = 'http://iso.qa.dev.stgraber.org/xmlrpc.php'
5
6
7class BuildTests(unittest.TestCase):
8 def setUp(self):
9 self.instance = qatracker.QATracker(URL, 'admin', 'admin')
10 self.milestone = self.instance.get_milestones('testing')[0]
11
12 def test_build_lower(self):
13 self.assertIsInstance(self.milestone.get_builds('active'), list)
14
15 def test_build_mixed(self):
16 self.assertIsInstance(self.milestone.get_builds('DisAblEd'), list)
17
18 def test_build_upper(self):
19 self.assertIsInstance(self.milestone.get_builds('RE-BUILDING'), list)
20
21 def test_build_id(self):
22 self.assertIsInstance(self.milestone.get_builds(3), list)
23
24 def test_build_list(self):
25 self.assertIsInstance(self.milestone.get_builds(['Re-Building', 0,
26 'DISABLED',
27 'SuperSeded']), list)
28
29 def test_build_empty_list(self):
30 self.assertEquals(self.milestone.get_builds([]), [])
31
32 def test_build_all(self):
33 self.assertIsInstance(self.milestone.get_builds(), list)
34
35 def test_build_type(self):
36 build = self.milestone.get_builds(0)[0]
37 self.assertIsInstance(build, qatracker.QATrackerBuild)
38 self.assertIsInstance(build.status, int)
39 self.assertIsInstance(build.version, str)
40
41 def test_build_repr(self):
42 build = self.milestone.get_builds(0)[0]
43 self.assertTrue(str(build).startswith('QATrackerBuild: '))
44
45 def test_build_add_by_name(self):
46 product = self.instance.get_products(0)[0]
47 self.milestone.add_build(product.title, '1234', '', False)
48
49 def test_build_add_by_id(self):
50 product = self.instance.get_products(0)[0]
51 build = self.milestone.add_build(product.id, '1234', '', False)
52 self.assertEquals(build.productid, product.id)
53 self.assertEquals(build.version, '1234')
54 self.assertEquals(build.note, '')
55
56 def test_build_invalid_add_disabled_product_by_id(self):
57 product = self.instance.get_products(1)[0]
58 self.assertRaises(IndexError, self.milestone.add_build,
59 product=product.id, version='1234')
60
61 def test_build_invalid_add_disabled_product_by_object(self):
62 product = self.instance.get_products(1)[0]
63 self.assertRaises(TypeError, self.milestone.add_build,
64 product=product, version='1234')
65
66 def test_build_invalid_add_disabled_milestone_by_object(self):
67 milestone = self.instance.get_milestones('archived')[0]
68 product = self.instance.get_products(1)[0]
69 self.assertRaises(TypeError, milestone.add_build,
70 product=product, version='1234')
71
72 def test_build_invalid_add_invalid_by_name(self):
73 self.assertRaises(IndexError, self.milestone.add_build,
74 product='bmaifno', version='1234')
75
76 def test_build_invalid_add_invalid_by_id(self):
77 self.assertRaises(IndexError, self.milestone.add_build,
78 product=-1, version='1234')
79
80 def test_build_invalid_add_invalid_notify(self):
81 product = self.instance.get_products(0)[0]
82 self.assertRaises(TypeError, self.milestone.add_build,
83 product=product.id, version='1234', notify=object())
84
85 def test_build_invalid_add_invalid_no_access(self):
86 instance = qatracker.QATracker(URL, 'user', 'user')
87 milestone = instance.get_milestones('testing')[0]
88 self.assertRaises(Exception, milestone.add_build, product=0,
89 version='1234')
90
91 def test_build_invalid_id(self):
92 self.assertRaises(IndexError, self.milestone.get_builds, (-1))
93
94 def test_build_invalid_string(self):
95 self.assertRaises(IndexError, self.milestone.get_builds, ('bla'))
96
97 def test_build_invalid_type(self):
98 self.assertRaises(TypeError, self.milestone.get_builds, (object()))
099
=== added file 'python-library/tests/test_milestone.py'
--- python-library/tests/test_milestone.py 1970-01-01 00:00:00 +0000
+++ python-library/tests/test_milestone.py 2016-03-01 21:32:25 +0000
@@ -0,0 +1,56 @@
1import unittest
2import qatracker
3
4URL = 'http://iso.qa.dev.stgraber.org/xmlrpc.php'
5
6
7class MilestoneTests(unittest.TestCase):
8 def setUp(self):
9 self.instance = qatracker.QATracker(URL)
10
11 def test_milestone_lower(self):
12 milestones = self.instance.get_milestones('testing')
13 self.assertIsInstance(milestones, list)
14
15 def test_milestone_mixed(self):
16 milestones = self.instance.get_milestones('RelEaSed')
17 self.assertIsInstance(milestones, list)
18
19 def test_milestone_upper(self):
20 milestones = self.instance.get_milestones('ARCHIVED')
21 self.assertIsInstance(milestones, list)
22
23 def test_milestone_id(self):
24 milestones = self.instance.get_milestones(2)
25 self.assertIsInstance(milestones, list)
26
27 def test_milestone_list(self):
28 milestones = self.instance.get_milestones(['testing', 2, 'archIved'])
29 self.assertIsInstance(milestones, list)
30
31 def test_milestone_empty_list(self):
32 self.assertEquals(self.instance.get_milestones([]), [])
33
34 def test_milestone_all(self):
35 self.assertIsInstance(self.instance.get_milestones(), list)
36
37 def test_milestone_type(self):
38 milestone = self.instance.get_milestones(2)[10]
39 self.assertIsInstance(milestone, qatracker.QATrackerMilestone)
40 self.assertIsInstance(milestone.notify, bool)
41 self.assertIsInstance(milestone.status, int)
42 self.assertIsInstance(milestone.title, str)
43 self.assertIsInstance(milestone.get_bugs(), list)
44
45 def test_milestone_repr(self):
46 milestone = self.instance.get_milestones(2)[0]
47 self.assertTrue(str(milestone).startswith('QATrackerMilestone: '))
48
49 def test_milestone_invalid_id(self):
50 self.assertRaises(IndexError, self.instance.get_milestones, (-1))
51
52 def test_milestone_invalid_string(self):
53 self.assertRaises(IndexError, self.instance.get_milestones, ('bla'))
54
55 def test_milestone_invalid_type(self):
56 self.assertRaises(TypeError, self.instance.get_milestones, (object()))
057
=== added file 'python-library/tests/test_product.py'
--- python-library/tests/test_product.py 1970-01-01 00:00:00 +0000
+++ python-library/tests/test_product.py 2016-03-01 21:32:25 +0000
@@ -0,0 +1,51 @@
1import unittest
2import qatracker
3
4URL = 'http://iso.qa.dev.stgraber.org/xmlrpc.php'
5
6
7class ProductTests(unittest.TestCase):
8 def setUp(self):
9 self.instance = qatracker.QATracker(URL)
10
11 def test_product_lower(self):
12 self.assertIsInstance(self.instance.get_products('active'), list)
13
14 def test_product_mixed(self):
15 self.assertIsInstance(self.instance.get_products('DisAblEd'), list)
16
17 def test_product_upper(self):
18 self.assertIsInstance(self.instance.get_products('ACTIVE'), list)
19
20 def test_product_id(self):
21 self.assertIsInstance(self.instance.get_products(1), list)
22
23 def test_product_list(self):
24 self.assertIsInstance(self.instance.get_products(['ActivE', 1,
25 'DISABLED',
26 'disabled']), list)
27
28 def test_product_empty_list(self):
29 self.assertEquals(self.instance.get_products([]), [])
30
31 def test_product_all(self):
32 self.assertIsInstance(self.instance.get_products(), list)
33
34 def test_product_type(self):
35 product = self.instance.get_products(0)[0]
36 self.assertIsInstance(product, qatracker.QATrackerProduct)
37 self.assertIsInstance(product.status, int)
38 self.assertIsInstance(product.title, str)
39
40 def test_product_repr(self):
41 product = self.instance.get_products(0)[0]
42 self.assertTrue(str(product).startswith('QATrackerProduct: '))
43
44 def test_product_invalid_id(self):
45 self.assertRaises(IndexError, self.instance.get_products, (-1))
46
47 def test_product_invalid_string(self):
48 self.assertRaises(IndexError, self.instance.get_products, ('bla'))
49
50 def test_product_invalid_type(self):
51 self.assertRaises(TypeError, self.instance.get_products, (object()))
052
=== added file 'python-library/tests/test_rebuilds.py'
--- python-library/tests/test_rebuilds.py 1970-01-01 00:00:00 +0000
+++ python-library/tests/test_rebuilds.py 2016-03-01 21:32:25 +0000
@@ -0,0 +1,69 @@
1import unittest
2import qatracker
3from datetime import datetime
4
5URL = 'http://iso.qa.dev.stgraber.org/xmlrpc.php'
6
7
8class ProductTests(unittest.TestCase):
9 def setUp(self):
10 self.instance = qatracker.QATracker(URL, 'admin', 'admin')
11
12 def test_rebuilds_lower(self):
13 self.assertIsInstance(self.instance.get_rebuilds('requested'), list)
14
15 def test_rebuilds_mixed(self):
16 self.assertIsInstance(self.instance.get_rebuilds('BuIlDing'), list)
17
18 def test_rebuilds_upper(self):
19 self.assertIsInstance(self.instance.get_rebuilds('PUBLISHED'), list)
20
21 def test_rebuilds_id(self):
22 self.assertIsInstance(self.instance.get_rebuilds(3), list)
23
24 def test_rebuilds_list(self):
25 self.assertIsInstance(self.instance.get_rebuilds(['reQuested', 1,
26 'PUBLISHED',
27 'canceled']), list)
28
29 def test_rebuilds_empty_list(self):
30 self.assertEquals(self.instance.get_rebuilds([]), [])
31
32 def test_rebuilds_all(self):
33 self.assertIsInstance(self.instance.get_rebuilds(), list)
34
35 def test_rebuilds_type(self):
36 rebuild = self.instance.get_rebuilds()[0]
37 self.assertIsInstance(rebuild, qatracker.QATrackerRebuild)
38 self.assertIsInstance(rebuild.id, int)
39 self.assertIsInstance(rebuild.product_title, str)
40 self.assertIsInstance(rebuild.requestedat, datetime)
41
42 def test_rebuilds_repr(self):
43 rebuild = self.instance.get_rebuilds()[0]
44 self.assertTrue(str(rebuild).startswith('QATrackerRebuild: '))
45
46 def test_rebuilds_invalid_id(self):
47 self.assertRaises(IndexError, self.instance.get_rebuilds, -1)
48
49 def test_rebuilds_invalid_string(self):
50 self.assertRaises(IndexError, self.instance.get_rebuilds, 'bla')
51
52 def test_rebuilds_invalid_type(self):
53 self.assertRaises(TypeError, self.instance.get_rebuilds, object())
54
55 def test_rebuilds_invalid_save_no_access(self):
56 instance = qatracker.QATracker(URL)
57 rebuild = instance.get_rebuilds()[0]
58 rebuild.status = 2
59 self.assertRaises(Exception, rebuild.save)
60
61 def test_rebuilds_valid_save(self):
62 rebuild = self.instance.get_rebuilds()[0]
63 rebuild.status = 2
64 self.assertTrue(rebuild.save())
65
66 def test_rebuilds_invalid_status_save(self):
67 rebuild = self.instance.get_rebuilds()[0]
68 rebuild.status = 99
69 self.assertRaises(Exception, rebuild.save)
070
=== added file 'python-library/tests/test_result.py'
--- python-library/tests/test_result.py 1970-01-01 00:00:00 +0000
+++ python-library/tests/test_result.py 2016-03-01 21:32:25 +0000
@@ -0,0 +1,173 @@
1import unittest
2import qatracker
3import datetime
4
5URL = 'http://iso.qa.dev.stgraber.org/xmlrpc.php'
6
7
8class ResultTests(unittest.TestCase):
9 def setUp(self):
10 self.instance = qatracker.QATracker(URL, 'user', 'user')
11 self.milestone = self.instance.get_milestones('testing')[0]
12 self.builds = self.milestone.get_builds('active')
13
14 def test_result_by_object(self):
15 results = []
16 for product in self.instance.get_products('active'):
17 builds = [build for build in self.builds
18 if build.productid == product.id]
19 if len(builds) == 0:
20 continue
21
22 for testcase in product.get_testcases(self.milestone, 'mandatory'):
23 build = builds[0]
24 results += build.get_results(testcase)
25 if len(results) > 0:
26 break
27 else:
28 continue
29 break
30
31 result = results[0]
32 self.assertIsInstance(result, qatracker.QATrackerResult)
33 self.assertIsInstance(result.id, int)
34 self.assertIsInstance(result.date, datetime.datetime)
35 self.assertIsInstance(result.comment, str)
36 self.assertTrue(str(result).startswith('QATrackerResult: '))
37
38 def test_result_by_id(self):
39 results = []
40 for product in self.instance.get_products('active'):
41 builds = [build for build in self.builds
42 if build.productid == product.id]
43 if len(builds) == 0:
44 continue
45
46 for testcase in product.get_testcases(self.milestone, 'mandatory'):
47 build = builds[0]
48 results += build.get_results(testcase.id)
49 if len(results) > 0:
50 break
51 else:
52 continue
53 break
54
55 result = results[0]
56 self.assertIsInstance(result, qatracker.QATrackerResult)
57 self.assertIsInstance(result.id, int)
58 self.assertIsInstance(result.date, datetime.datetime)
59 self.assertIsInstance(result.comment, str)
60 self.assertTrue(str(result).startswith('QATrackerResult: '))
61
62 def test_result_add_by_object(self):
63 testcase = None
64 build = None
65
66 for product in self.instance.get_products('active'):
67 builds = [build for build in self.builds
68 if build.productid == product.id]
69 if len(builds) == 0:
70 continue
71
72 build = builds[0]
73 testcase = product.get_testcases(self.milestone, 'mandatory')[0]
74 break
75
76 result = build.add_result(testcase, 'failed')
77 self.assertIsInstance(result, qatracker.QATrackerResult)
78 self.assertIsInstance(result.id, int)
79 self.assertIsInstance(result.date, datetime.datetime)
80 self.assertIsInstance(result.comment, str)
81 self.assertEquals(result.result, 0)
82 self.assertTrue(str(result).startswith('QATrackerResult: '))
83
84 result.comment = "edited"
85 result.save()
86 result.delete()
87
88 self.assertRaises(Exception, result.save)
89
90 def test_result_add_by_id(self):
91 testcase = None
92 build = None
93
94 for product in self.instance.get_products('active'):
95 builds = [build for build in self.builds
96 if build.productid == product.id]
97 if len(builds) == 0:
98 continue
99
100 build = builds[0]
101 testcase = product.get_testcases(self.milestone, 'mandatory')[0]
102 break
103
104 result = build.add_result(testcase.id, 2)
105 self.assertIsInstance(result, qatracker.QATrackerResult)
106 self.assertIsInstance(result.id, int)
107 self.assertIsInstance(result.date, datetime.datetime)
108 self.assertIsInstance(result.comment, str)
109 self.assertEquals(result.result, 2)
110 self.assertTrue(str(result).startswith('QATrackerResult: '))
111
112 result.delete()
113
114 self.assertRaises(Exception, result.delete)
115
116 def test_result_invalid_remove(self):
117 result = qatracker.QATrackerResult(self.instance, {'id': '0'})
118 self.assertRaises(Exception, result.delete)
119
120 def test_result_invalid_remove_no_access(self):
121 instance = qatracker.QATracker(URL)
122 result = qatracker.QATrackerResult(instance, {'id': '0'})
123 self.assertRaises(Exception, result.delete)
124
125 def test_result_invalid_save(self):
126 result = qatracker.QATrackerResult(self.instance, {'id': '0',
127 'comment': '',
128 'result': '0',
129 'hardware': '',
130 'bugs': {}})
131 self.assertRaises(Exception, result.save)
132
133 def test_result_invalid_save_no_access(self):
134 instance = qatracker.QATracker(URL)
135 result = qatracker.QATrackerResult(instance, {'id': '0'})
136 self.assertRaises(Exception, result.save)
137
138 def test_result_invalid_add_invalid_testcase(self):
139 self.assertRaises(IndexError, self.builds[0].add_result,
140 testcase=object(), result='in progress')
141
142 def test_result_invalid_add_invalid_result(self):
143 self.assertRaises(TypeError, self.builds[0].add_result,
144 testcase=1, result=['in progress'])
145
146 def test_result_invalid_add_invalid_bugs(self):
147 self.assertRaises(TypeError, self.builds[0].add_result,
148 testcase=1, result='in progress', bugs="bla")
149
150 def test_result_invalid_add_invalid_bugnumber(self):
151 self.assertRaises(ValueError, self.builds[0].add_result,
152 testcase=1, result='in progress', bugs={-1: 0})
153
154 def test_result_invalid_add_invalid_bugimportance(self):
155 self.assertRaises(ValueError, self.builds[0].add_result,
156 testcase=1, result='in progress', bugs={123: 'a'})
157
158 def test_result_invalid_add_invalid_response(self):
159 self.assertRaises(Exception, self.builds[0].add_result,
160 testcase=-1, result='in progress')
161
162 def test_result_invalid_add_invalid_no_access(self):
163 instance = qatracker.QATracker(URL)
164 milestone = instance.get_milestones('testing')[0]
165 builds = milestone.get_builds('active')
166 self.assertRaises(Exception, builds[0].add_result,
167 testcase=10, result='in progress')
168
169 def test_result_invalid_id(self):
170 self.assertRaises(IndexError, self.builds[0].get_results, (object()))
171
172 def test_result_invalid_no_status(self):
173 self.assertEquals(self.builds[0].get_results(1234, []), [])
0174
=== added file 'python-library/tests/test_rpc.py'
--- python-library/tests/test_rpc.py 1970-01-01 00:00:00 +0000
+++ python-library/tests/test_rpc.py 2016-03-01 21:32:25 +0000
@@ -0,0 +1,27 @@
1import unittest
2import qatracker
3
4URL = 'http://iso.qa.dev.stgraber.org/xmlrpc.php'
5
6try:
7 import xmlrpc.client as xmlrpclib
8except ImportError:
9 import xmlrpclib
10
11
12class RPCTests(unittest.TestCase):
13 def test_rpc_anonymous(self):
14 tracker = qatracker.QATracker(URL)
15 self.assertEquals(tracker.access, 'public')
16
17 def test_rpc_authenticated_user(self):
18 tracker = qatracker.QATracker(URL, 'user', 'user')
19 self.assertEquals(tracker.access, 'user')
20
21 def test_rpc_authenticated_admin(self):
22 tracker = qatracker.QATracker(URL, 'admin', 'admin')
23 self.assertEquals(tracker.access, 'admin')
24
25 def test_rpc_invalid_target(self):
26 self.assertRaises(xmlrpclib.ProtocolError, qatracker.QATracker,
27 ("%s.invalid" % URL))
028
=== added file 'python-library/tests/test_series.py'
--- python-library/tests/test_series.py 1970-01-01 00:00:00 +0000
+++ python-library/tests/test_series.py 2016-03-01 21:32:25 +0000
@@ -0,0 +1,77 @@
1import unittest
2import qatracker
3
4URL = 'http://iso.qa.dev.stgraber.org/xmlrpc.php'
5
6
7class ProductTests(unittest.TestCase):
8 def setUp(self):
9 self.instance = qatracker.QATracker(URL)
10
11 def test_series_lower(self):
12 self.assertIsInstance(self.instance.get_series('active'), list)
13
14 def test_series_mixed(self):
15 self.assertIsInstance(self.instance.get_series('DisAblEd'), list)
16
17 def test_series_upper(self):
18 self.assertIsInstance(self.instance.get_series('ACTIVE'), list)
19
20 def test_series_id(self):
21 self.assertIsInstance(self.instance.get_series(1), list)
22
23 def test_series_list(self):
24 self.assertIsInstance(self.instance.get_series(['AcTiVe', 1,
25 'DISABLED',
26 'active']), list)
27
28 def test_series_empty_list(self):
29 self.assertEquals(self.instance.get_series([]), [])
30
31 def test_series_all(self):
32 self.assertIsInstance(self.instance.get_series(), list)
33
34 def test_series_type(self):
35 series = self.instance.get_series()[0]
36 self.assertIsInstance(series, qatracker.QATrackerSeries)
37 self.assertIsInstance(series.id, int)
38 self.assertIsInstance(series.title, str)
39
40 def test_series_repr(self):
41 series = self.instance.get_series()[0]
42 self.assertTrue(str(series).startswith('QATrackerSeries: '))
43
44 def test_series_invalid_id(self):
45 self.assertRaises(IndexError, self.instance.get_series, -1)
46
47 def test_series_invalid_string(self):
48 self.assertRaises(IndexError, self.instance.get_series, 'bla')
49
50 def test_series_invalid_type(self):
51 self.assertRaises(TypeError, self.instance.get_series, object())
52
53 def test_series_manifest_all(self):
54 self.assertIsInstance(self.instance.get_series()[0].get_manifest(),
55 list)
56
57 def test_series_manifest_none(self):
58 self.assertIsInstance(self.instance.get_series()[0].get_manifest([]),
59 list)
60
61 def test_series_manifest_type(self):
62 for series in self.instance.get_series():
63 manifest = series.get_manifest()
64 if manifest:
65 self.assertIsInstance(manifest[0],
66 qatracker.QATrackerSeriesManifest)
67 self.assertIsInstance(manifest[0].productid, int)
68 self.assertIsInstance(manifest[0].product_title, str)
69 break
70
71 def test_series_manifest_repr(self):
72 for series in self.instance.get_series():
73 manifest = series.get_manifest()
74 if manifest:
75 self.assertTrue(str(manifest[0]).startswith(
76 'QATrackerSeriesManifest: '))
77 break
078
=== added file 'python-library/tests/test_testcase.py'
--- python-library/tests/test_testcase.py 1970-01-01 00:00:00 +0000
+++ python-library/tests/test_testcase.py 2016-03-01 21:32:25 +0000
@@ -0,0 +1,68 @@
1import unittest
2import qatracker
3
4URL = 'http://iso.qa.dev.stgraber.org/xmlrpc.php'
5
6
7class TestcaseTests(unittest.TestCase):
8 def setUp(self):
9 self.instance = qatracker.QATracker(URL)
10 self.product = self.instance.get_products(0)[0]
11 self.milestone = self.instance.get_milestones()[0]
12
13 def test_testcase_lower(self):
14 self.assertIsInstance(self.product.get_testcases(self.milestone,
15 'mandatory'), list)
16
17 def test_testcase_mixed(self):
18 self.assertIsInstance(self.product.get_testcases(self.milestone,
19 'DisAblEd'), list)
20
21 def test_testcase_upper(self):
22 self.assertIsInstance(self.product.get_testcases(self.milestone,
23 'RUN-ONCE'), list)
24
25 def test_testcase_id(self):
26 self.assertIsInstance(self.product.get_testcases(self.milestone,
27 3), list)
28
29 def test_testcase_seriesid(self):
30 self.assertIsInstance(self.product.get_testcases(self.milestone.series,
31 3), list)
32
33 def test_testcase_list(self):
34 self.assertIsInstance(self.product.get_testcases(self.milestone,
35 ['Run-once', 0,
36 'DISABLED',
37 'optional']), list)
38
39 def test_testcase_empty_list(self):
40 self.assertEquals(self.product.get_testcases(self.milestone, []), [])
41
42 def test_testcase_all(self):
43 self.assertIsInstance(self.product.get_testcases(self.milestone), list)
44
45 def test_testcase_type(self):
46 testcase = self.product.get_testcases(self.milestone, 0)[0]
47 self.assertIsInstance(testcase, qatracker.QATrackerTestcase)
48 self.assertIsInstance(testcase.status, int)
49 self.assertIsInstance(testcase.title, str)
50
51 def test_testcase_repr(self):
52 testcase = self.product.get_testcases(self.milestone, 0)[0]
53 self.assertTrue(str(testcase).startswith('QATrackerTestcase: '))
54
55 def test_testcase_invalid_id(self):
56 self.assertRaises(IndexError, self.product.get_testcases,
57 self.milestone, -1)
58
59 def test_testcase_invalid_string(self):
60 self.assertRaises(IndexError, self.product.get_testcases,
61 self.milestone, 'bla')
62
63 def test_testcase_invalid_type(self):
64 self.assertRaises(TypeError, self.product.get_testcases,
65 self.milestone, object())
66
67 def test_testcase_invalid_seriesid(self):
68 self.assertRaises(TypeError, self.product.get_testcases, object(), 3)

Subscribers

People subscribed via source and target branches