def test_parse_content_template_unicode(self): """ Unicode parsing tests """ node = {'template': u'myval 😽 $var'} handler = ContentHandler.parse_content(node) context = Context() context.bind_variable('var', 'cheese') self.assertEqual(u'myval 😽 cheese', handler.get_content(context))
def test_variable_binding(self): """ Test that tests successfully bind variables """ element = 3 test_config = [{ "url": "/ping" }, { "name": "cheese" }, { "expected_status": ["200", 204, "202"] }, { "variable_binds": { 'var': 'value' } }] context = Context() test = TestCase('', None, context) test.parse(test_config) binds = test.variable_binds self.assertEqual(1, len(binds)) self.assertEqual('value', binds['var']) # Test that updates context correctly test.pre_update(context) self.assertEqual('value', context.get_value('var'))
def test_parse_test_templated_headers(self): """ Test parsing with templated headers """ heads = {"Accept": "Application/json", "$AuthHeader": "$AuthString"} templated_heads = { "Accept": "Application/json", "apikey": "magic_passWord" } context = Context() context.bind_variables({ 'AuthHeader': 'apikey', 'AuthString': 'magic_passWord' }) # If this doesn't throw errors we have silent failures input_invalid = { "url": "/ping", "method": "DELETE", "NAME": "foo", "group": "bar", "body": "<xml>input</xml>", "headers": 'goat' } try: test = TestCase('', None, context) test.parse(input_invalid) fail("Expected error not thrown") except ValidatorError: pass
def __init__(self, base_url, extract_binds, variable_binds, context=None, config=None): self.__base_url = base_url self.__url = None self.__body = None self.__config = config if config else TestCaseConfig() self.__auth_username = None self.__auth_password = None self.__delay = 0 self.__verbose = False self.__ssl_insecure = False self.__response_headers = None self.__response_code = None self.__passed = False self.__failure_list = [] self.__abs_url = False self.__header_dict = {} self.__http_method = EnumHttpMethod.GET.name self.__group = TestCaseGroup.DEFAULT_GROUP self.__name = TestCase.DEFAULT_NAME self._should_stop_on_failure = False self._test_run_delay = 0 self._auth_type = AuthType.BASIC self._curl_options = None self.__variable_binds_dict = variable_binds if variable_binds else {} self.__generator_binds_dict = {} self.__extract_binds_dict = extract_binds if extract_binds else {} self.__validator_list = [] self.__expected_http_status_code_list = [200] self.__context = Context() if context is None else context self.templates = {} self.result = None self.config = config
def test_parse_validator_comparator(self): """ Test parsing a comparator validator """ test_config = { 'name': 'Default', 'url': '/api', 'validators': [{ 'comparator': { 'jsonpath_mini': 'id', 'comparator': 'eq', 'expected': { 'template': '$id' } } }] } test = TestCase('', None, None) test.parse(test_config) self.assertTrue(test.validators) self.assertEqual(1, len(test.validators)) context = Context() context.bind_variable('id', 3) myjson = '{"id": "3"}' failure = test.validators[0].validate(myjson, context=context) self.assertTrue(test.validators[0].validate(myjson, context=context)) self.assertFalse(test.validators[0].validate(myjson))
def test_invalid_gen_type(self): c = Context() with self.assertRaises(ValueError) as context: c.add_generator('example', [1, 2, 3]) self.assertTrue('Cannot add generator' in str(context.exception)) self.assertRaises(ValueError, c.add_generator, 'example', [1, 2, 3])
def test_url_templating(self): context = Context() test = TestCase('', None, None, context) test.url = {'template': "$cheese"} self.assertTrue(test.is_dynamic()) self.assertEqual({'template': '$cheese'}, test.url) self.assertTrue(test.templates['url']) context.bind_variable('cheese', 'liquid_cheese') self.assertEqual('liquid_cheese', test.url)
def test_header_templating(self): context = Context() test = TestCase('', None, None, context) head_templated = {'x': {'template': "$val"}} context.bind_variables({'val': 'gouda'}) # No templating applied test.headers = head_templated self.assertEqual(1, len(test.headers)) self.assertEqual('gouda', test.headers['x'])
def test_test_content_templating(self): context = Context() test = TestCase('', None, None, context) handler = ContentHandler() handler.is_template_content = True handler.content = '{"first_name": "Gaius","id": "$id","last_name": "Baltar","login": "******"}' context.bind_variables({'id': 9, 'login': '******'}) test.body = handler test.pre_update(context=context) self.assertEqual( string.Template(handler.content).safe_substitute( context.get_values()), test.body)
def test_parse_content_templated(self): """ Test parsing of templated content """ node = {'template': 'myval $var'} handler = ContentHandler.parse_content(node) context = Context() context.bind_variable('var', 'cheese') self.assertEqual(node['template'], handler.content) self.assertEqual('myval cheese', handler.get_content(context)) self.assertTrue(handler.is_dynamic()) self.assertFalse(handler.is_file) self.assertFalse(handler.is_template_path) self.assertTrue(handler.is_template_content)
def test_mixing_binds(self): """ Ensure that variables are set correctly when mixing explicit declaration and variables """ context = Context() context.add_generator('gen', count_gen()) context.bind_variable('foo', '100') self.assertEqual(1, context.mod_count) context.bind_generator_next('foo', 'gen') self.assertEqual(1, context.get_value('foo')) self.assertEqual(2, context.mod_count)
def test_generator_bind(self): """ Test generator setting to variables """ context = Context() self.assertEqual(0, len(context.get_generators())) my_gen = count_gen() context.add_generator('gen', my_gen) context.bind_generator_next('foo', 'gen') self.assertEqual(1, context.mod_count) self.assertEqual(1, context.get_value('foo')) self.assertTrue(2, next(context.get_generator('gen'))) self.assertTrue(3, next(my_gen))
def test_parse_extractor_bind(self): """ Test parsing of extractors """ test_config = { "url": '/api', 'extract_binds': { 'id': { 'jsonpath_mini': 'idfield' }, 'name': { 'jsonpath_mini': 'firstname' } } } context = Context() test = TestCase('', None, None, context) test.parse(test_config) test.pre_update(context) self.assertTrue(test.extract_binds) self.assertEqual(2, len(test.extract_binds)) self.assertTrue('id' in test.extract_binds) self.assertTrue('name' in test.extract_binds) # # Test extractors config'd correctly for extraction myjson = '{"idfield": 3, "firstname": "bob"}' extracted = test.extract_binds['id'].extract(myjson) self.assertEqual(3, extracted) # extracted = test.extract_binds['name'].extract(myjson) self.assertEqual('bob', extracted)
def test_content_templating(self): """ Test content and templating of it """ handler = ContentHandler() body = '$variable value' templated_body = 'bar value' context = Context() context.bind_variable('variable', 'bar') # No templating handler.setup(body, is_template_content=False) self.assertEqual(body, handler.get_content()) self.assertEqual(body, handler.get_content(context)) self.assertRaises(TypeError, handler.setup, []) # Templating handler.setup(body, is_template_content=True) self.assertEqual(body, handler.get_content()) self.assertEqual(templated_body, handler.get_content(context))
def test_generator(self): """ Test adding a generator """ context = Context() self.assertEqual(0, len(context.get_generators())) my_gen = count_gen() context.add_generator('gen', my_gen) self.assertEqual(1, len(context.get_generators())) self.assertTrue('gen' in context.get_generators()) self.assertTrue(context.get_generator('gen') is not None)
def test_abstract_extractor_templating(self): """ Test that abstract extractors template the query """ class A(validators.AbstractExtractor): def extract_internal(self, query=None, body=None, headers=None, args=None): ... ext = A() ext.query = '$val.vee' ext.is_templated = True context = Context() context.bind_variable('val', 'foo') self.assertEqual('$val.vee', ext.templated_query()) self.assertEqual('foo.vee', ext.templated_query(context=context)) ext._is_templated = False self.assertEqual('$val.vee', ext.templated_query(context=context))
def test_abstract_extractor_readableconfig(self): """ Test human-readable extractor config string output """ config = 'key.val' extractor = validators.parse_extractor('jsonpath_mini', config) expected_string = 'Extractor Type: jsonpath_mini, Query: "key.val", Templated?: False' self.assertEqual(expected_string, extractor.get_readable_config()) # Check empty context & args uses okay context = Context() self.assertEqual(expected_string, extractor.get_readable_config(context=context)) context.bind_variable('foo', 'bar') self.assertEqual(expected_string, extractor.get_readable_config(context=context)) extractor.args = dict() self.assertEqual(expected_string, extractor.get_readable_config(context=context)) # Check args output is handled correctly extractor.args = {'caseSensitive': True} self.assertEqual(expected_string + ", Args: " + str(extractor.args), extractor.get_readable_config(context=context)) # Check template handling is okay config = {'template': 'key.$templated'} context.bind_variable('templated', 'val') extractor = validators.parse_extractor('jsonpath_mini', config) expected_string = 'Extractor Type: jsonpath_mini, Query: "key.val", Templated?: True' self.assertEqual(expected_string, extractor.get_readable_config(context=context))
def test_parse_extractor_minijson(self): config = 'key.val' extractor = validators.MiniJsonExtractor.parse(config) myjson = '{"key": {"val": 3}}' context = Context() context.bind_variable('node', 'val') extracted = extractor.extract(body=myjson) self.assertEqual(3, extracted) self.assertEqual(extracted, extractor.extract(body=myjson, context=context)) try: val = extractor.extract(body='[31{]') self.fail("Should throw exception on invalid JSON") except ValueError: pass # Templating config = {'template': 'key.$node'} extract = validators.MiniJsonExtractor.parse(config) self.assertEqual(3, extract.extract(myjson, context=context))
def __init__(self, name, context=None, extract_binds=None, variable_binds=None, config=None): self.__testcase_list = [] self.__benchmark_list = [] self.__config = None self.__name = name self.__testcase_file = set() self.__context = context if context else Context() self.__extract_binds = extract_binds if extract_binds else {} self.__variable_binds = variable_binds if variable_binds else {} self.__is_global = None self.config = config
def test_update_context_variables(self): variable_binds = {'foo': 'correct', 'test': 'value'} context = Context() test = TestCase('', None, variable_binds, context=context) context.bind_variable('foo', 'broken') test.pre_update(context) self.assertEqual('correct', context.get_value('foo')) self.assertEqual('value', context.get_value('test'))
def test_parse_validator(self): """ Test basic parsing using registry """ config = { 'jsonpath_mini': 'key.val', 'comparator': 'eq', 'expected': 3 } validator = validators.parse_validator('comparator', config) myjson = '{"key": {"val": 3}}' comp = validator.validate(body=myjson) self.assertTrue(comp) validator = validators.parse_validator('comparator', config) my_body_str = '<html></html>' comp = validator.validate(body=my_body_str) self.assertEqual(comp.message, 'Extractor threw exception') validator = validators.parse_validator('comparator', config) myjson_1 = '{"key": {"val": 4}}' comp = validator.validate(body=myjson_1) self.assertFalse(comp) # Try it with templating # Try it with templating config['jsonpath_mini'] = {'template': 'key.$node'} validator = validators.parse_validator('comparator', config) context = Context() context.bind_variable('node', 'val') comp = validator.validate(myjson, context=context) self.assertTrue(comp) # Try it with templating del config['jsonpath_mini'] config['jmespath'] = {'template': 'key.$node'} validator = validators.parse_validator('comparator', config) context = Context() context.bind_variable('node', 'val') comp = validator.validate(myjson, context=context) self.assertTrue(comp)
def test_unicode_templating(self): """ A couple combination of templating using Unicode data """ handler = ContentHandler() context = Context() # ASCII body, unicode data body = '$variable value' context.bind_variable('variable', u'😽') handler.setup(body, is_template_content=True) self.assertEqual(body, handler.get_content()) self.assertEqual(u'😽 value', handler.get_content(context)) # Unicode body, ASCII data context.bind_variable('variable', u'string') body = u'$variable 😽 value' handler.setup(body, is_template_content=True) self.assertEqual(u'$variable 😽 value', handler.get_content()) self.assertEqual(u'string 😽 value', handler.get_content(context)) # All the Unicodes, all the times! context.bind_variable('variable', u'😽') body = u'$variable 😽 value' handler.setup(body, is_template_content=True) self.assertEqual(u'😽 😽 value', handler.get_content(context))
def test_validator_comparator_templating(self): """ Try templating comparator validator """ config = { 'jsonpath_mini': { 'template': 'key.$node' }, 'comparator': 'eq', 'expected': 3 } context = Context() context.bind_variable('node', 'val') myjson_pass = '******' myjson_fail = '{"id": 3, "key": {"val": 4}}' comp = validators.ComparatorValidator.parse(config) self.assertTrue(comp.validate(body=myjson_pass, context=context)) self.assertFalse(comp.validate(body=myjson_fail, context=context)) # Template expected config['expected'] = {'template': '$id'} context.bind_variable('id', 3) self.assertTrue(comp.validate(body=myjson_pass, context=context)) self.assertFalse(comp.validate(body=myjson_fail, context=context))
def test_content_file_template(self): """ Test file read and templating of read files in this directory """ variables = {'id': 1, 'login': '******'} context = Context() file_path = os.path.dirname(os.path.realpath(__file__)) file_path = os.path.join(file_path, 'person_body_template.json') file_content = None with open(file_path, 'r') as f: file_content = f.read() # Test basic read handler = ContentHandler() handler.setup(file_path, is_file=True) self.assertEqual(file_content, handler.get_content()) # Test templating of read content handler.setup(file_path, is_file=True, is_template_content=True) self.assertEqual(file_content, handler.get_content()) self.assertEqual(file_content, handler.get_content( context)) # No substitution substituted = string.Template(file_content).safe_substitute(variables) context.bind_variables(variables) self.assertEqual(substituted, handler.get_content(context)) # Test path templating templated_file_path = '$filepath' context.bind_variable('filepath', file_path) handler.setup(file_path, is_file=True, is_template_path=True) self.assertEqual(file_content, handler.get_content(context)) # Test double templating with files handler.setup(file_path, is_file=True, is_template_path=True, is_template_content=True) self.assertEqual(substituted, handler.get_content(context=context))
class TestCase: DEFAULT_NAME = "NO NAME" KEYWORD_DICT = {k: v for k, v in TestCaseKeywords.__dict__.items() if not k.startswith('__')} def __init__(self, base_url, extract_binds, variable_binds, context=None, config=None): self.__base_url = base_url self.__url = None self.__body = None self.__config = config if config else TestCaseConfig() self.__auth_username = None self.__auth_password = None self.__delay = 0 self.__verbose = False self.__ssl_insecure = False self.__response_headers = None self.__response_code = None self.__passed = False self.__failure_list = [] self.__abs_url = False self.__header_dict = {} self.__http_method = EnumHttpMethod.GET.name self.__group = TestCaseGroup.DEFAULT_GROUP self.__name = TestCase.DEFAULT_NAME self._should_stop_on_failure = False self._test_run_delay = 0 self._auth_type = AuthType.BASIC self._curl_options = None self.__variable_binds_dict = variable_binds if variable_binds else {} self.__generator_binds_dict = {} self.__extract_binds_dict = extract_binds if extract_binds else {} self.__validator_list = [] self.__expected_http_status_code_list = [200] self.__context = Context() if context is None else context self.templates = {} self.result = None self.config = config def __str__(self): return json.dumps(self, default=Parser.safe_to_json) @property def config(self) -> Optional[TestCaseConfig]: return self.__config @config.setter def config(self, config_object: TestCaseConfig): if config_object: self.variable_binds.update(config_object.variable_binds) self.generator_binds.update(config_object.generators) @property def auth_username(self): return self.__auth_username @auth_username.setter def auth_username(self, username): self.__auth_username = Parser.coerce_string_to_ascii(username) @property def ssl_insecure(self): return self.__ssl_insecure @ssl_insecure.setter def ssl_insecure(self, val): self.__ssl_insecure = bool(val) @property def auth_password(self): return self.__auth_password @auth_password.setter def auth_password(self, password): self.__auth_password = Parser.coerce_string_to_ascii(password) @property def http_method(self): return self.__http_method @http_method.setter def http_method(self, method: str): __method = ["GET", "PUT", "POST", "DELETE", "PATCH"] if method.upper() not in __method: raise HttpMethodError("Method %s is not supported." % method) self.__http_method = method.upper() @property def name(self): return self.__name @property def group(self): return self.__group @property def is_passed(self): return bool(self.__passed) @property def url(self): val = self.realize_template("url", self.__context) if val is None: val = self.__url if not self.__abs_url: val = urljoin(self.__base_url, val) if isinstance(val, dict): logger.warning("URL is not applied template values.") return val @url.setter def url(self, value): if isinstance(value, dict): # this is the templated url , we need to convert it into actual URL template_str = Parser.lowercase_keys(value)['template'] self.set_template("url", Parser.coerce_to_string(template_str)) self.__url = value else: self.__url = value @property def generator_binds(self): return self.__generator_binds_dict @property def delay(self): return self.__delay @generator_binds.setter def generator_binds(self, value: Dict): binds_dict = Parser.flatten_dictionaries(value) __binds_dict = {str(k): str(v) for k, v in binds_dict.items()} self.__generator_binds_dict.update(__binds_dict) @property def variable_binds(self): return self.__variable_binds_dict @property def extract_binds(self): return self.__extract_binds_dict @extract_binds.setter def extract_binds(self, bind_dict): bind_dict = Parser.flatten_dictionaries(bind_dict) for variable_name, extractor in bind_dict.items(): if not isinstance(extractor, dict) or len(extractor) == 0: raise BindError("Extractors must be defined as maps of extractorType:{configs} with 1 entry") if len(extractor) > 1: raise BindError("Cannot define multiple extractors for given variable name") for extractor_type, extractor_config in extractor.items(): self.__extract_binds_dict[variable_name] = parse_extractor(extractor_type, extractor_config) @property def expected_http_status_code_list(self): return [int(x) for x in self.__expected_http_status_code_list] @expected_http_status_code_list.setter def expected_http_status_code_list(self, value): self.__expected_http_status_code_list = value @property def validators(self): return self.__validator_list @validators.setter def validators(self, validator_list): if not isinstance(validator_list, list): raise ValidatorError('Misconfigured validator section, must be a list of validators') for validator in validator_list: if not isinstance(validator, dict): raise ValidatorError("Validators must be defined as validatorType:{configs} ") for validator_type, validator_config in validator.items(): validator = parse_validator(validator_type, validator_config) self.__validator_list.append(validator) @property def headers(self) -> Dict: # if not self.templates.get('headers'): # return self.__header_dict context_values = self.__context.get_values() header_dict = {} for key, header in self.__header_dict.items(): if isinstance(header, dict): if key == 'template': for k, v in header.items(): templated_string = string.Template(v).safe_substitute(context_values) header_dict[k] = templated_string continue templated_value = header.get('template') if templated_value: templated_string = string.Template(templated_value).safe_substitute(context_values) header_dict[key] = templated_string else: logger.warning("Skipping the header: %s. We don't support mapping as header" % header) else: header_dict[key] = header return header_dict @headers.setter def headers(self, headers): config_value = Parser.flatten_dictionaries(headers) if isinstance(config_value, dict): for key, value in config_value.items(): if isinstance(value, dict): if value.get('template'): self.set_template("headers", value.get('template')) self.__header_dict.update(config_value) else: raise ValidatorError("Illegal header type: headers must be a dictionary or list of dictionary keys") def set_template(self, variable_name, template_string): self.templates[variable_name] = string.Template(str(template_string)) @property def body(self): if isinstance(self.__body, str) or self.__body is None: return self.__body return self.__body.get_content(context=self.__context) @body.setter def body(self, value): if value: if isinstance(value, bytes): self.__body = ContentHandler.parse_content(value.decode()) elif isinstance(value, str): self.__body = ContentHandler.parse_content(value) else: self.__body = value else: self.__body = value @property def failures(self): return self.__failure_list def realize_template(self, variable_name, context): if (context or self.templates) is None or (variable_name not in self.templates): return None if not context.get_values(): return None val = self.templates[variable_name].safe_substitute(context.get_values()) return val def parse(self, testcase_dict): testcase_dict = Parser.flatten_lowercase_keys_dict(testcase_dict) for keyword in TestCase.KEYWORD_DICT.keys(): value = testcase_dict.get(keyword) if value is None: continue if keyword == TestCaseKeywords.auth_username: self.auth_username = value elif keyword == TestCaseKeywords.auth_password: self.auth_password = value elif keyword == TestCaseKeywords.method: self.http_method = value elif keyword == TestCaseKeywords.delay: self.__delay = int(value) elif keyword == TestCaseKeywords.group: self.__group = value elif keyword == TestCaseKeywords.name: self.__name = value elif keyword == TestCaseKeywords.url: self.url = value elif keyword == TestCaseKeywords.extract_binds: self.extract_binds = value elif keyword == TestCaseKeywords.validators: self.validators = value elif keyword == TestCaseKeywords.headers: self.headers = value elif keyword == TestCaseKeywords.variable_binds: self.__variable_binds_dict = Parser.flatten_dictionaries(value) elif keyword == TestCaseKeywords.generator_binds: self.__generator_binds_dict = {str(k): str(v) for k, v in Parser.flatten_dictionaries(value)} elif keyword == TestCaseKeywords.options: raise NotImplementedError("Yet to Support") elif keyword == TestCaseKeywords.body: self.body = value elif keyword == TestCaseKeywords.absolute_urls: self.__abs_url = Parser.safe_to_bool(value) expected_status = testcase_dict.get(TestCaseKeywords.expected_status, []) if expected_status: self.expected_http_status_code_list = expected_status else: if self.http_method in ["POST", "PUT", "DELETE"]: self.expected_http_status_code_list = [200, 201, 204] def pre_update(self, context): if self.variable_binds: context.bind_variables(self.variable_binds) if self.generator_binds: for key, value in self.generator_binds.items(): context.bind_generator_next(key, value) def post_update(self, context): if self.extract_binds: for key, value in self.extract_binds.items(): result = value.extract( body=self.body, headers=self.headers, context=context) if result: context.bind_variable(key, result) def is_dynamic(self): if self.templates or (isinstance(self.__body, ContentHandler) and self.__body.is_dynamic()): return True return False def render(self): if self.is_dynamic() or self.__context is not None: if isinstance(self.__body, ContentHandler): self.__body = self.__body.get_content(self.__context) def __perform_validation(self) -> List: failure_list = [] for validator in self.validators: logger.debug("Running validator: %s" % validator.name) validate_result = validator.validate(body=self.body, headers=self.headers, context=self.__context) if not validate_result: self.__passed = False if hasattr(validate_result, 'details'): failure_list.append(validate_result) return failure_list def run(self, context=None, timeout=None, curl_handler=None): if context is None: context = self.__context self.pre_update(context) self.render() if timeout is None: timeout = DEFAULT_TIMEOUT if curl_handler: try: # Check the curl handle isn't closed, and reuse it if possible curl_handler.getinfo(curl_handler.HTTP_CODE) # Below clears the cookies & curl options for clean run # But retains the DNS cache and connection pool curl_handler.reset() curl_handler.setopt(curl_handler.COOKIELIST, "ALL") except pycurl.error: curl_handler = pycurl.Curl() curl_handler.setopt(pycurl.CAINFO, certifi.where()) # Fix for #29 curl_handler.setopt(pycurl.FOLLOWLOCATION, 1) # Support for HTTP 301 else: curl_handler = pycurl.Curl() body_byte, header_byte = self.__default_curl_config(curl_handler, timeout) if self.config.timeout: curl_handler.setopt(pycurl.CONNECTTIMEOUT, self.config.timeout) if self.__ssl_insecure: curl_handler.setopt(pycurl.SSL_VERIFYPEER, 0) curl_handler.setopt(pycurl.SSL_VERIFYHOST, 0) if self.body: logger.debug("Request body %s" % self.body) curl_handler.setopt(curl_handler.READFUNCTION, BytesIO(bytes(self.body, 'utf-8')).read) if self.auth_username and self.auth_password: curl_handler.setopt(pycurl.USERPWD, self.auth_username + ':' + self.auth_password) self.__configure_curl_method(curl_handler) head = self.headers self.__configure_curl_headers(curl_handler, head) if self.__delay: time.sleep(self.__delay) try: logger.info("Hitting %s" % self.url) curl_handler.perform() except pycurl.error as e: logger.error("Unknown Exception", exc_info=True) self.__passed = False curl_handler.close() trace = traceback.format_exc() self.__failure_list.append( Failure(message="Curl Exception: {0}".format(e), details=trace, failure_type=FAILURE_CURL_EXCEPTION)) return self.body = body_byte.getvalue() body_byte.close() response_code = curl_handler.getinfo(pycurl.RESPONSE_CODE) self.__response_code = int(response_code) if self.config.print_bodies: print(self.body) try: response_headers = Parser.parse_headers(header_byte.getvalue()) self.__response_headers = response_headers logger.debug("RESPONSE HEADERS: %s" % self.__response_headers) header_byte.close() except Exception as e: # Need to catch the expected exception trace = traceback.format_exc() self.__failure_list.append(Failure( message="Header parsing exception: {0}".format(e), details=trace, failure_type=FAILURE_TEST_EXCEPTION) ) self.__passed = False curl_handler.close() return if self.__response_code in self.expected_http_status_code_list: self.__passed = True self.__failure_list.extend(self.__perform_validation()) self.post_update(context) else: self.__passed = False failure_message = "Invalid HTTP response code: response code {0} not in expected codes {1}".format( self.__response_code, self.expected_http_status_code_list ) self.__failure_list.append( Failure(message=failure_message, details=None, failure_type=FAILURE_INVALID_RESPONSE) ) curl_handler.close() @staticmethod def __configure_curl_headers(curl_handler, head): if head.get('content-type'): content_type = head['content-type'] head[u'content-type'] = '%s ; charset=UTF-8' % content_type headers = ["%s:%s" % (header_name, header_value) for header_name, header_value in head.items()] headers.append("Expect:") headers.append("Connection: close") logger.debug("Request headers %s " % head) curl_handler.setopt(curl_handler.HTTPHEADER, headers) def __configure_curl_method(self, curl_handler): body_length = len(self.body) if self.body else 0 if self.http_method == EnumHttpMethod.POST.name: curl_handler.setopt(EnumHttpMethod.POST.value, 1) curl_handler.setopt(pycurl.POSTFIELDSIZE, body_length) elif self.http_method == EnumHttpMethod.PUT.name: curl_handler.setopt(EnumHttpMethod.PUT.value, 1) curl_handler.setopt(pycurl.INFILESIZE, body_length) elif self.http_method == EnumHttpMethod.PATCH.name: curl_handler.setopt(EnumHttpMethod.PATCH.value, EnumHttpMethod.PATCH.name) curl_handler.setopt(pycurl.POSTFIELDS, self.body) elif self.http_method == EnumHttpMethod.DELETE.name: curl_handler.setopt(EnumHttpMethod.DELETE.value, EnumHttpMethod.DELETE.name) if self.body: curl_handler.setopt(pycurl.POSTFIELDS, self.body) curl_handler.setopt(pycurl.POSTFIELDSIZE, body_length) elif self.http_method == EnumHttpMethod.HEAD.name: curl_handler.setopt(pycurl.NOBODY, 1) curl_handler.setopt(EnumHttpMethod.HEAD.value, EnumHttpMethod.HEAD.name) else: curl_handler.setopt(pycurl.CUSTOMREQUEST, self.http_method.upper()) if self.body: curl_handler.setopt(pycurl.POSTFIELDS, self.body) curl_handler.setopt(pycurl.POSTFIELDSIZE, body_length) def __default_curl_config(self, curl_handler, timeout): body_byte = BytesIO() header_byte = BytesIO() curl_handler.setopt(curl_handler.URL, str(self.url)) curl_handler.setopt(curl_handler.TIMEOUT, timeout) curl_handler.setopt(pycurl.WRITEFUNCTION, body_byte.write) curl_handler.setopt(pycurl.HEADERFUNCTION, header_byte.write) curl_handler.setopt(pycurl.VERBOSE, self.__verbose) return body_byte, header_byte
def test_basic_ids(self): """ Test starting ids """ ids1 = generators.generator_basic_ids() ids2 = generators.generator_basic_ids() self.generator_repeat_test(ids1) self.generator_repeat_test(ids2) self.assertEqual(next(ids1), next(ids2)) c = Context() c.variables = {'x': '$x'} x = generators.factory_generate_ids(1, increment=0)() c.add_generator('x', x) self.assertEqual(c.bind_generator_next('x', 'x'), c.bind_generator_next('x', 'x')) c.bind_variable('x', 1) var1 = c.get_value('x') c.bind_variable('x', 1) var2 = c.get_value('x') self.assertEqual(var1, var2)
def test_variables(self): """ Test bind/return of variables """ context = Context() context.variables = {} self.assertTrue(context.get_value('foo') is None) self.assertEqual(0, context.mod_count) context.bind_variable('foo', 'bar') self.assertEqual('bar', context.get_value('foo')) self.assertEqual('bar', context.get_values()['foo']) self.assertEqual(1, context.mod_count) context.bind_variable('foo', 'bar2') self.assertEqual('bar2', context.get_value('foo')) self.assertEqual(2, context.mod_count)
def test_config(self): config_object = TestCaseConfig() context = Context() config_list = [{ 'variable_binds': { 'content_type': 'application/json', 'pid': 5 } }] config_object.parse(config_list) test_case = TestCase('', None, None, context, config=config_object) self.assertEqual(test_case.variable_binds, { 'content_type': 'application/json', 'pid': 5 }) testcase_list = [{ 'name': 'Create/update person 7, no template' }, { 'url': '/api/person/7/' }, { 'method': 'PUT' }, { 'headers': { 'template': { 'Content-Type': '$content_type' } } }, { 'body': '{"first_name": "Gaius","id": "7","last_name": "Romani","login": "******"}' }] test_case.parse(testcase_list) test_case.pre_update(context) self.assertEqual({'Content-Type': 'application/json'}, test_case.headers) testcase_list = [ { 'name': 'Create/update person 7, no template' }, { 'url': { 'template': '/api/person/$pid/' } }, { 'method': 'PUT' }, { 'headers': { 'template': { 'Content-Type': '$content_type' } } }, { 'body': '{"first_name": "Gaius","id": "7","last_name": "Romani","login": "******"}' }, [] # Make sure it will not through exception or error ] test_case.parse(testcase_list) test_case.pre_update(context) self.assertEqual('/api/person/5/', test_case.url) testcase_list = [ { 'auth_username': '******' }, { 'auth_password': '******' }, ] test_case.parse(testcase_list) test_case.pre_update(context) self.assertEqual(bytes('5', 'utf-8'), test_case.auth_password) self.assertEqual(bytes('Abhilash', 'utf-8'), test_case.auth_username) _input = [{ "url": '/test' }, { 'extract_binds': [{ 'id': { 'jsonpath_mini': 'key.val' } }] }] test_case.parse(_input) test_case.pre_update(context) self.assertIsInstance(test_case.extract_binds['id'], MiniJsonExtractor) testcase_list = [{ 'name': 'Create/update person 7, no template' }, { 'url': '/api/person/7/' }, { 'method': 'PUT' }, { 'headers': { 'Content-Type': { 'template': '$content_type' } } }, { 'body': '{"first_name": "Gaius","id": "7","last_name": "Romani","login": "******"}' }] test_case.parse(testcase_list) test_case.pre_update(context) self.assertEqual({'Content-Type': 'application/json'}, test_case.headers) testcase_list = [{ 'name': 'Create/update person 7, no template' }, { 'url': '/api/person/7/' }, { 'method': 'PUT' }, { 'headers': { 'Content-Type': { 'x': 'application/json' } } }, { 'body': '{"first_name": "Gaius","id": "7","last_name": "Romani","login": "******"}' }] test_case.parse(testcase_list) test_case.pre_update(context) self.assertEqual({'Content-Type': 'application/json'}, test_case.headers) testcase_list = [ { 'name': 'Create/update person 7, no template' }, { 'delay': '5' }, { 'method': 'PUT' }, ] test_case.parse(testcase_list) test_case.pre_update(context) self.assertEqual(5, test_case.delay) config_list = [{'generators': "H"}] self.assertRaises(TypeError, config_object.parse, config_list) test_case = TestCase('https://api.github.com', None, None) testcase_list = [ { 'name': 'Get github user abihijo89-to' }, { 'url': '/search/users?q=abhijo89-to' }, { 'method': 'GET' }, { 'headers': { 'Content-Type': 'application/json' } }, ] test_case.parse(testcase_list) test_case.run() self.assertTrue(test_case.is_passed)
def __init__(self): self.__context = Context() self.__extract_binds = {} self.__variable_binds = {} self.config = TestCaseConfig()
def test_update_context_generators(self): """ Test updating context variables using generator """ variable_binds = {'foo': 'initial_value'} generator_binds = {'foo': 'gen'} context = Context() test = TestCase('', None, variable_binds, context=context) test.generator_binds = generator_binds context.bind_variable('foo', 'broken') context.add_generator('gen', generators.generator_basic_ids()) context.bind_generator_next('foo', 'gen') self.assertEqual(1, context.get_value('foo')) context.bind_generator_next('foo', 'gen') self.assertEqual(2, context.get_value('foo'))