| # |
| # TestRail API binding for Python 3.x (API v2, available since |
| # TestRail 3.0) |
| # Compatible with TestRail 3.0 and later. |
| # |
| # Learn more: |
| # |
| # http://docs.gurock.com/testrail-api2/start |
| # http://docs.gurock.com/testrail-api2/accessing |
| # |
| # Copyright Gurock Software GmbH. See license.md for details. |
| # |
| |
| import requests |
| import json |
| import base64 |
| |
| |
| class APIClient: |
| def __init__(self, base_url): |
| self.user = '' |
| self.password = '' |
| if not base_url.endswith('/'): |
| base_url += '/' |
| self.__url = base_url + 'index.php?/api/v2/' |
| |
| # |
| # Send Get |
| # |
| # Issues a GET request (read) against the API and returns the result |
| # (as Python dict) or filepath if successful file download |
| # |
| # Arguments: |
| # |
| # uri The API method to call including parameters |
| # (e.g. get_case/1) |
| # |
| # filepath The path and file name for attachment download |
| # Used only for 'get_attachment/:attachment_id' |
| # |
| def send_get(self, uri, filepath=None): |
| return self.__send_request('GET', uri, filepath) |
| |
| # |
| # Send POST |
| # |
| # Issues a POST request (write) against the API and returns the result |
| # (as Python dict). |
| # |
| # Arguments: |
| # |
| # uri The API method to call including parameters |
| # (e.g. add_case/1) |
| # data The data to submit as part of the request (as |
| # Python dict, strings must be UTF-8 encoded) |
| # If adding an attachment, must be the path |
| # to the file |
| # |
| def send_post(self, uri, data): |
| return self.__send_request('POST', uri, data) |
| |
| def __send_request(self, method, uri, data): |
| url = self.__url + uri |
| |
| auth = str( |
| base64.b64encode( |
| bytes('%s:%s' % (self.user, self.password), 'utf-8') |
| ), |
| 'ascii' |
| ).strip() |
| headers = {'Authorization': 'Basic ' + auth} |
| |
| if method == 'POST': |
| if uri[:14] == 'add_attachment': # add_attachment API method |
| files = {'attachment': (open(data, 'rb'))} |
| response = requests.post(url, headers=headers, files=files) |
| files['attachment'].close() |
| else: |
| headers['Content-Type'] = 'application/json' |
| payload = bytes(json.dumps(data), 'utf-8') |
| response = requests.post(url, headers=headers, data=payload) |
| else: |
| headers['Content-Type'] = 'application/json' |
| response = requests.get(url, headers=headers) |
| |
| if response.status_code > 201: |
| try: |
| error = response.json() |
| except: # response.content not formatted as JSON |
| error = str(response.content) |
| raise APIError('TestRail API returned HTTP %s (%s)' % (response.status_code, error)) |
| else: |
| if uri[:15] == 'get_attachment/': # Expecting file, not JSON |
| try: |
| open(data, 'wb').write(response.content) |
| return (data) |
| except: |
| return ("Error saving attachment.") |
| else: |
| return response.json() |
| |
| |
| class APIError(Exception): |
| pass |