Best Python code snippet using tempest_python
restful_api.py
Source:restful_api.py
...118 if save_request:119 try:120 if full_request:121 request_file_path = cls._get_log_request_file_path(dir_request, transact_id, ext='json')122 cls._log_request_full(response, request_file_path)123 else:124 request_file_path = cls._get_log_request_file_path(dir_request, transact_id)125 cls._log_request(response, request_file_path)126 except Exception as exc:127 log.error('Exception logging rest transaction request: id={} exc={} trace...'.format(transact_id, exc),128 exc_info=True)129 if save_response:130 try:131 if full_response:132 response_file_path = cls._get_log_response_file_path(dir_response, transact_id, ext='json')133 cls._log_response_full(response, response_file_path)134 else:135 response_file_path = cls._get_log_response_file_path(dir_response, transact_id)136 cls._log_response(response, response_file_path)137 except Exception as exc:138 log.error('Exception logging rest transaction response: id={} exc={} trace...'.format(transact_id, exc),139 exc_info=True)140 @classmethod141 def _log_request_full(cls, response, request_file_path):142 """log the full request side of a transaction"""143 assert isinstance(response, requests.Response)144 req = response.request145 assert isinstance(req, requests.PreparedRequest)146 data = {147 'url': req.url,148 'headers': dict(req.headers),149 'method': req.method,150 'body': cls._get_body_from_req(req),151 '__meta__': 'PreparedRequest object: not Request object'152 }153 utils.write_json(request_file_path, data, json_kwargs={'indent': 4, 'sort_keys': True})154 @classmethod155 def _log_response_full(cls, response, response_file_path):...
test_tempest.py
Source:test_tempest.py
1# Copyright (c) 2015 Russell Sim <russell.sim@gmail.com>2#3# All Rights Reserved.4#5# Licensed under the Apache License, Version 2.0 (the "License");6# you may not use this file except in compliance with the License.7# You may obtain a copy of the License at8#9# http://www.apache.org/licenses/LICENSE-2.010#11# Unless required by applicable law or agreed to in writing, software12# distributed under the License is distributed on an "AS IS" BASIS,13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or14# implied.15# See the License for the specific language governing permissions and16# limitations under the License.17from __future__ import unicode_literals18try:19 from StringIO import StringIO20except ImportError:21 from io import StringIO22import unittest23from fairy_slipper.cmd import tempest_log24SIMPLE_LOG = """2015-09-04 15:51:29.023 18793 DEBUG tempest_lib.common.rest_client [req-30784c0a-e9a1-4411-a7c1-20715b26598f ] Request (FlavorsV2TestJSON:setUpClass): 200 POST http://192.168.122.201:5000/v2.0/tokens252015-09-04 15:51:29.023 18793 DEBUG tempest_lib.common.rest_client [req-30784c0a-e9a1-4411-a7c1-20715b26598f ] Request - Headers: {}26 Body: None27 Response - Headers: {'status': '200', 'content-length': '2987', 'vary': 'X-Auth-Token', 'server': 'Apache/2.4.7 (Ubuntu)', 'connection': 'close', 'date': 'Sun, 13 Sep 2015 07:43:01 GMT', 'content-type': 'application/json', 'x-openstack-request-id': 'req-1'}28 Body: None292015-09-04 15:51:45.472 18793 INFO tempest_lib.common.rest_client [req-b710aeba-6263-4a49-bf50-2da42227c870 ] Request (FlavorsV2TestJSON:test_get_flavor): 200 POST http://192.168.122.201:5000/v2.0/tokens302015-09-04 15:51:45.472 18793 DEBUG tempest_lib.common.rest_client [req-b710aeba-6263-4a49-bf50-2da42227c870 ] Request - Headers: {}31 Body: None32 Response - Headers: {'status': '200', 'content-length': '2987', 'vary': 'X-Auth-Token', 'server': 'Apache/2.4.7 (Ubuntu)', 'connection': 'close', 'date': 'Sun, 13 Sep 2015 07:43:01 GMT', 'content-type': 'application/json', 'x-openstack-request-id': 'req-2'}33 Body: None34""" # noqa35SIMPLE_LOG_BODY = """2015-09-04 15:51:29.007 18793 INFO tempest_lib.common.rest_client [req-9e329507-e0ce-448c-a363-f49e39dd96b0 ] Request (FlavorsV2TestJSON:test_get_flavor): 200 GET http://192.168.122.201:8774/v2.1/6b45254f6f7c44a1b65ddb8218932226/flavors/1 0.117s362015-09-04 15:51:29.007 18793 DEBUG tempest_lib.common.rest_client [req-9e329507-e0ce-448c-a363-f49e39dd96b0 ] Request - Headers: {'Content-Type': 'application/json', 'Accept': 'application/json', 'X-Auth-Token': '<omitted>'}37 Body: None38 Response - Headers: {'status': '200', 'content-length': '430', 'content-location': 'http://192.168.122.201:8774/v2.1/6b45254f6f7c44a1b65ddb8218932226/flavors/1', 'x-compute-request-id': 'req-959a09e8-3628-419d-964a-1be4ca604232', 'vary': 'X-OpenStack-Nova-API-Version', 'connection': 'close', 'x-openstack-nova-api-version': '2.1', 'date': 'Sun, 13 Sep 2015 07:43:01 GMT', 'content-type': 'application/json'}39 Body: {"flavor": {"name": "m1.tiny", "links": [{"href": "http://192.168.122.201:8774/v2.1/6b45254f6f7c44a1b65ddb8218932226/flavors/1", "rel": "self"}, {"href": "http://192.168.122.201:8774/6b45254f6f7c44a1b65ddb8218932226/flavors/1", "rel": "bookmark"}], "ram": 512, "OS-FLV-DISABLED:disabled": false, "vcpus": 1, "swap": "", "os-flavor-access:is_public": true, "rxtx_factor": 1.0, "OS-FLV-EXT-DATA:ephemeral": 0, "disk": 1, "id": "1"}}40""" # noqa41DEBUG_LOG = """2015-09-04 15:54:42.296 18793 INFO tempest_lib.common.rest_client [req-39c6042e-5a4a-4517-9fe9-32b34cfaa5a8 ] Request (TestSessionsTenantIsolation:test_delete_session_in_env_from_another_tenant): 403 DELETE http://127.0.0.1:8082/v1/environments/7501923609b145ec88eeb4a5c93e371c/sessions/db214e36e0494c4e9dc67fb0df8548f7 0.010s422015-09-04 15:54:42.296 18793 DEBUG tempest_lib.common.rest_client [req-39c6042e-5a4a-4517-9fe9-32b34cfaa5a8 ] Request - Headers: {'Content-Type': 'application/json', 'Accept': 'application/json', 'X-Auth-Token': '<omitted>'}43 Body: None44 Response - Headers: {'status': '403', 'content-length': '75', 'connection': 'close', 'date': 'Fri, 04 Sep 2015 15:54:42 GMT', 'content-type': 'text/plain; charset=UTF-8', 'x-openstack-request-id': 'req-39c6042e-5a4a-4517-9fe9-32b34cfaa5a8'}45 Body: 403 Forbidden46User is not authorized to access these tenant resources47 _log_request_full /opt/stack/new/tempest/.venv/local/lib/python2.7/site-packages/tempest_lib/common/rest_client.py:411482015-09-04 15:52:13.727 18793 INFO tempest_lib.common.rest_client [req-0ff36a16-dacd-49c8-9835-7ce92d50f5a7 ] Request (TestEnvironmentsTenantIsolation:tearDown): 200 DELETE http://127.0.0.1:8082/v1/environments/c32c6d5095c4476da549ed065e9b5196 0.054s492015-09-04 15:52:13.727 18793 DEBUG tempest_lib.common.rest_client [req-0ff36a16-dacd-49c8-9835-7ce92d50f5a7 ] Request - Headers: {'Content-Type': 'application/json', 'Accept': 'application/json', 'X-Auth-Token': '<omitted>'}50 Body: None51 Response - Headers: {'status': '200', 'content-length': '0', 'connection': 'close', 'date': 'Fri, 04 Sep 2015 15:52:13 GMT', 'content-type': 'application/json', 'x-openstack-request-id': 'req-0ff36a16-dacd-49c8-9835-7ce92d50f5a7'}52 Body: _log_request_full /opt/stack/new/tempest/.venv/local/lib/python2.7/site-packages/tempest_lib/common/rest_client.py:41153""" # noqa54DEBUG_LOG_AUTH = """2015-09-04 15:49:46.056 14923 INFO tempest_lib.common.rest_client [req-280bc347-e650-473e-92bb-bcc59103e12c ] Request (main): 200 POST http://127.0.0.1:5000/v2.0/tokens552015-09-04 15:49:46.056 14923 DEBUG tempest_lib.common.rest_client [req-280bc347-e650-473e-92bb-bcc59103e12c ] Request - Headers: {}56 Body: None57 Response - Headers: {'server': 'Apache/2.4.7 (Ubuntu)', 'vary': 'X-Auth-Token', 'x-openstack-request-id': 'req-280bc347-e650-473e-92bb-bcc59103e12c', 'content-length': '4846', 'connection': 'close', 'status': '200', 'content-type': 'application/json', 'date': 'Fri, 04 Sep 2015 15:49:42 GMT'}58 Body: None _log_request_full /opt/stack/new/tempest/.tox/venv/local/lib/python2.7/site-packages/tempest_lib/common/rest_client.py:41159""" # noqa60def db_to_call_list(db):61 calls = []62 for req in sorted(db.requests):63 calls.append((db.requests[req], db.responses[req]))64 return calls65class TestLogParser(unittest.TestCase):66 maxDiff = 1000067 def test_simple_parse(self):68 result = db_to_call_list(69 tempest_log.parse_logfile(StringIO(SIMPLE_LOG)))70 self.assertEqual(result, [71 ({'url': '/v2.0/tokens',72 'service': 'identity',73 'headers': {},74 'body': None,75 'method': 'POST'},76 {'status_code': '200',77 'body': None,78 'headers': {'status': '200',79 'content-length': '0',80 'date': 'Sun, 13 Sep 2015 07:43:01 GMT',81 'content-type': 'application/json',82 'x-openstack-request-id': 'req-1',83 'vary': 'X-Auth-Token',84 'connection': 'close',85 'server': 'Apache/2.4.7 (Ubuntu)'}}),86 ({'url': '/v2.0/tokens',87 'service': 'identity',88 'headers': {},89 'body': None,90 'method': 'POST'},91 {'status_code': '200',92 'body': None,93 'headers': {'status': '200',94 'content-length': '0',95 'date': 'Sun, 13 Sep 2015 07:43:01 GMT',96 'content-type': 'application/json',97 'x-openstack-request-id': 'req-2',98 'vary': 'X-Auth-Token',99 'connection': 'close',100 'server': 'Apache/2.4.7 (Ubuntu)'}})])101 def test_body_parse(self):102 result = db_to_call_list(103 tempest_log.parse_logfile(StringIO(SIMPLE_LOG_BODY)))104 self.assertEqual(result, [105 ({'url': '/v2.1/6b45254f6f7c44a1b65ddb8218932226/flavors/1',106 'headers': {'content-type': 'application/json',107 'content-length': '0',108 'accept': 'application/json',109 'x-auth-token': '<omitted>'},110 'body': None,111 'method': 'GET',112 'service': 'compute'},113 {'body': '{\n "flavor": {\n "OS-FLV-DISABLED:disabled": false,\n "OS-FLV-EXT-DATA:ephemeral": 0,\n "disk": 1,\n "id": "1",\n "links": [\n {\n "href": "http://192.168.122.201:8774/v2.1/6b45254f6f7c44a1b65ddb8218932226/flavors/1",\n "rel": "self"\n },\n {\n "href": "http://192.168.122.201:8774/6b45254f6f7c44a1b65ddb8218932226/flavors/1",\n "rel": "bookmark"\n }\n ],\n "name": "m1.tiny",\n "os-flavor-access:is_public": true,\n "ram": 512,\n "rxtx_factor": 1.0,\n "swap": "",\n "vcpus": 1\n }\n}', # noqa114 'status_code': '200',115 'headers': {'status': '200', 'content-length': '548',116 'content-location': 'http://192.168.122.201:8774/v2.1/6b45254f6f7c44a1b65ddb8218932226/flavors/1', # noqa117 'x-openstack-nova-api-version': '2.1',118 'date': 'Sun, 13 Sep 2015 07:43:01 GMT',119 'vary': 'X-OpenStack-Nova-API-Version',120 'x-compute-request-id': 'req-959a09e8-3628-419d-964a-1be4ca604232', # noqa121 'content-type': 'application/json',122 'connection': 'close'}})])123 def test_debug_log(self):124 result = db_to_call_list(125 tempest_log.parse_logfile(StringIO(DEBUG_LOG)))126 self.assertEqual(result, [127 ({'body': None,128 'headers': {'accept': 'application/json',129 'content-type': 'application/json',130 'content-length': '0',131 'x-auth-token': '<omitted>'},132 'method': 'DELETE',133 'service': 'application-catalog',134 'url': '/v1/environments/c32c6d5095c4476da549ed065e9b5196'},135 {'body': None,136 'headers': {'connection': 'close',137 'content-length': '0',138 'content-type': 'application/json',139 'date': 'Fri, 04 Sep 2015 15:52:13 GMT',140 'status': '200',141 'x-openstack-request-id':142 'req-0ff36a16-dacd-49c8-9835-7ce92d50f5a7'},143 'status_code': '200'}),144 ({'body': None,145 'headers': {'accept': 'application/json',146 'content-type': 'application/json',147 'content-length': '0',148 'x-auth-token': '<omitted>'},149 'method': 'DELETE',150 'service': 'application-catalog',151 'url': '/v1/environments/7501923609b145ec88eeb4a5c93e371c'152 '/sessions/db214e36e0494c4e9dc67fb0df8548f7'},153 {'body': '403 Forbidden\n'154 'User is not authorized to access these tenant resources\n\n',155 'headers': {'connection': 'close',156 'content-length': '13',157 'content-type': 'text/plain; charset=UTF-8',158 'date': 'Fri, 04 Sep 2015 15:54:42 GMT',159 'status': '403',160 'x-openstack-request-id':161 'req-39c6042e-5a4a-4517-9fe9-32b34cfaa5a8'},162 'status_code': '403'})])163 def test_debug_admin_log(self):164 result = db_to_call_list(165 tempest_log.parse_logfile(StringIO(DEBUG_LOG_AUTH)))166 self.assertEqual(result, [167 ({'body': None,168 'headers': {},169 'method': 'POST',170 'service': 'identity',171 'url': '/v2.0/tokens'},172 {'body': None,173 'headers': {'connection': 'close',174 'content-length': '0',175 'content-type': 'application/json',176 'date': 'Fri, 04 Sep 2015 15:49:42 GMT',177 'server': 'Apache/2.4.7 (Ubuntu)',178 'status': '200',179 'vary': 'X-Auth-Token',180 'x-openstack-request-id':181 'req-280bc347-e650-473e-92bb-bcc59103e12c'},...
tempest_log.py
Source:tempest_log.py
1# Copyright (c) 2015 Russell Sim <russell.sim@gmail.com>2#3# All Rights Reserved.4#5# Licensed under the Apache License, Version 2.0 (the "License");6# you may not use this file except in compliance with the License.7# You may obtain a copy of the License at8#9# http://www.apache.org/licenses/LICENSE-2.010#11# Unless required by applicable law or agreed to in writing, software12# distributed under the License is distributed on an "AS IS" BASIS,13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or14# implied.15# See the License for the specific language governing permissions and16# limitations under the License.17from __future__ import print_function18from __future__ import unicode_literals19from collections import defaultdict20import json21import logging22from os import path23import re24import six25try:26 import urlparse27except ImportError:28 import urllib.parse as urlparse29log = logging.getLogger(__name__)30DEFAULT_PORTS = {31 '5000': 'identity',32 '35357': 'identity',33 '8774': 'compute',34 '8776': 'volume',35 '8773': 'compute-ec2',36 '9292': 'image',37 '9696': 'networking',38 '9292': 'image',39 '8082': 'application-catalog',40 '8004': 'orchestration',41 '8080': 'object',42 '8777': 'telemetry',43}44PYTHON_LOG_PREFIX_RE = ("^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}) \d+ "45 "(?P<log_level>[A-Z]+) (?P<logger_name>\S+) "46 "\[(?P<tags>[^\[\]]+)\] ")47REQUEST_RE = re.compile(PYTHON_LOG_PREFIX_RE + "Request (?P<test>\([^()]+\)):"48 " (?P<status_code>\d+)"49 " (?P<method>[A-Z]+) (?P<url>\S+)")50REQUEST1_RE = re.compile(PYTHON_LOG_PREFIX_RE + "Request")51RUBBISH_LINE_RE = re.compile("^ _log_request_full \S+:\d+$")52REQ_RE = re.compile('(req-[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}'53 '-[a-z0-9]{4}-[a-z0-9]{12})')54class DB(object):55 def __init__(self):56 self.requests = {}57 self.responses = {}58 def _normalize_headers(self, headers):59 return {k.lower(): v for k, v in headers.items()}60 def exists(self, req):61 if req in self.requests:62 return True63 return False64 def create(self, req, request):65 url = urlparse.urlsplit(request['url'])66 port = url.netloc.split(':')[-1]67 service = DEFAULT_PORTS[port]68 self.requests[req] = {69 'service': service,70 'url': urlparse.urlunsplit(('', '') + url[2:]),71 'method': request['method']}72 self.responses[req] = {73 'status_code': request['status_code']}74 def set_request_headers(self, req, headers):75 self.requests[req]['headers'] = self._normalize_headers(headers)76 def set_response_headers(self, req, headers):77 self.responses[req]['headers'] = self._normalize_headers(headers)78 def get_req_or_resp_length(self, req):79 if self.responses[req].get('headers') is not None:80 return int(self.responses[req]['headers'].get('content-length', 0))81 else:82 return int(self.requests[req]['headers'].get('content-length', 0))83 def set_req_or_resp_length(self, req_id, content_length):84 if self.responses[req_id].get('headers'):85 h = self.responses[req_id].get('headers')86 h['content-length'] = content_length87 self.responses[req_id]['headers'] = h88 else:89 if self.requests[req_id].get('headers'):90 h = self.requests[req_id].get('headers')91 h['content-length'] = content_length92 self.requests[req_id]['headers'] = h93 def get_req_or_resp_content_type(self, req):94 if self.responses[req].get('headers') is not None:95 return self.responses[req]['headers'].get('content-type',96 'text/plain')97 else:98 return self.requests[req]['headers'].get('content-type',99 'text/plain')100 def append_req_or_resp_body(self, req_id, string):101 if self.responses[req_id].get('headers') is not None:102 self.responses[req_id]['body'] += string103 else:104 self.requests[req_id]['body'] += string105 def set_req_or_resp_body(self, req_id, string):106 if self.responses[req_id].get('headers') is not None:107 self.responses[req_id]['body'] = string108 else:109 self.requests[req_id]['body'] = string110def parse_logfile(log_file):111 """Yet another shonky stream parser."""112 content_length = 0113 current_req_id = ''114 db = DB()115 for line in log_file:116 if RUBBISH_LINE_RE.match(line):117 continue118 request = REQUEST_RE.match(line)119 if request:120 request_dict = request.groupdict()121 try:122 current_req_id = REQ_RE.match(request_dict['tags']).groups()[0]123 except AttributeError:124 # Swift calls don't have the req tag125 current_req_id = ''126 if current_req_id:127 db.create(current_req_id, request_dict)128 else:129 start_request = REQUEST1_RE.match(line)130 if start_request:131 line = re.sub(PYTHON_LOG_PREFIX_RE, '', line)132 try:133 current_req_id = REQ_RE.match(134 start_request.groupdict()['tags']).groups()[0]135 except AttributeError:136 # Swift calls don't have the req tag137 current_req_id = ''138 # Skip all boto logs139 if 'boto' == start_request.groupdict()['logger_name']:140 current_req_id = ''141 try:142 key, value = line.split(':', 1)143 except ValueError:144 # For some wacky reason, when you request JSON,145 # sometimes you get text. Handle this rad behaviour.146 if not current_req_id:147 continue148 try:149 db.append_req_or_resp_body(current_req_id, line)150 except TypeError:151 log.warning('Failed to find body to add to.')152 continue153 if not current_req_id:154 continue155 if not db.exists(current_req_id):156 log.warning("Can't find request %r" % current_req_id)157 current_req_id = ''158 continue159 key = key.strip()160 value = value.strip()161 if key == 'Request - Headers':162 if current_req_id:163 db.set_request_headers(current_req_id, eval(value))164 if key == 'Response - Headers':165 if current_req_id:166 db.set_response_headers(current_req_id, eval(value))167 if key == 'Body':168 if not current_req_id:169 continue170 content_length = db.get_req_or_resp_length(current_req_id)171 content_type = db.get_req_or_resp_content_type(current_req_id)172 # Trim any messages that are by accident on the end of173 # the line174 if '_log_request_full' in value:175 value = value.split('_log_request_full')[0]176 if '_check_samples' in value:177 value = value.split('_check_samples')[0]178 if content_length == 0:179 body = None180 elif value[:4] == 'None':181 body = None182 elif 'application/json' in content_type:183 try:184 body = json.loads(value)185 except ValueError:186 body = value187 log.warning("Failed to as JSON %r", value)188 try:189 body = eval(value)190 log.warning("Succeed parsing as Python %r", value)191 except Exception:192 body = value193 if not isinstance(body, six.string_types):194 body = json.dumps(body, indent=2,195 sort_keys=True,196 separators=(',', ': '))197 else:198 body = value199 if body is None:200 content_length = '0'201 else:202 content_length = str(len(body))203 db.set_req_or_resp_body(current_req_id, body)204 db.set_req_or_resp_length(current_req_id, content_length)205 return db206def main1(log_file, output_dir):207 log.info('Reading %s' % log_file)208 calls = parse_logfile(open(log_file))209 services = defaultdict(list)210 for req in calls.requests:211 call = (calls.requests[req], calls.responses[req])212 services[call[0]['service']].append(call)213 for service, calls in services.items():214 pathname = path.join(output_dir, '%s-examples.json' % (service))215 with open(pathname, 'w') as out_file:216 json.dump(calls, out_file, indent=2)217def main():218 import argparse219 parser = argparse.ArgumentParser(220 formatter_class=argparse.ArgumentDefaultsHelpFormatter)221 parser.add_argument(222 '-v', '--verbose', action='count', default=0,223 help="Increase verbosity (specify multiple times for more)")224 parser.add_argument(225 '-o', '--output-dir', action='store',226 help="The directory to output the JSON files too.")227 parser.add_argument(228 'filename',229 help="File to convert")230 args = parser.parse_args()231 log_level = logging.WARNING232 if args.verbose == 1:233 log_level = logging.INFO234 elif args.verbose >= 2:235 log_level = logging.DEBUG236 logging.basicConfig(237 level=log_level,238 format='%(asctime)s %(name)s %(levelname)s %(message)s')239 filename = path.abspath(args.filename)...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!