def query_json(json_content, query, delimiter='.',context=""): """ Do an xpath-like query with json_content. @param (dict/list/string) json_content json_content = { "ids": [1, 2, 3, 4], "person": { "name": { "first_name": "Leo", "last_name": "Lee", }, "age": 29, "cities": ["Guangzhou", "Shenzhen"] } } @param (str) query "person.name.first_name" => "Leo" "person.name.first_name.0" => "L" "person.cities.0" => "Guangzhou" @return queried result """ raise_flag = False response_body = u"response body: {}\n".format(json_content) try: for key in query.split(delimiter): variable_key = testcase.extract_variables(key) if variable_key: key0 = variable_key[0] # $a ->a key1 = "$"+key0 # $a ->$a variable_key_value = context.testcase_parser.get_bind_variable(key0) #查询变量对应值 key = variable_key_value print('变量换值成功{}->{}'.format(key1,key)) if isinstance(json_content, (list, basestring)): json_content = json_content[int(key)] elif isinstance(json_content, dict): json_content = json_content[key] else: logger.log_error( "invalid type value: {}({})".format(json_content, type(json_content))) raise_flag = True except (KeyError, ValueError, IndexError): raise_flag = True if raise_flag: err_msg = u"Failed to extract! => {}\n".format(query) err_msg += response_body logger.log_error(err_msg) raise exceptions.ExtractFailure(err_msg) return json_content
def eval_check_item(self, validator, resp_obj): """ evaluate check item in validator @param (dict) validator {"check": "status_code", "comparator": "eq", "expect": 201} {"check": "$resp_body_success", "comparator": "eq", "expect": True} @param (object) resp_obj @return (dict) validator info { "check": "status_code", "check_value": 200, "expect": 201, "comparator": "eq" } """ check_item = validator["check"] # check_item should only be the following 5 formats: # 1, variable reference, e.g. $token # 2, function reference, e.g. ${is_status_code_200($status_code)} # 3, dict or list, maybe containing variable/function reference, e.g. {"var": "$abc"} # 4, string joined by delimiter. e.g. "status_code", "headers.content-type" # 5, regex string, e.g. "LB[\d]*(.*)RB[\d]*" if isinstance(check_item, (dict, list)) \ or testcase.extract_variables(check_item) \ or testcase.extract_functions(check_item): # format 1/2/3 check_value = self.eval_content(check_item) else: try: # format 4/5 check_value = resp_obj.extract_field(check_item) except exception.ParseResponseError: msg = "failed to extract check item from response!\n" msg += "response content: {}".format(resp_obj.content) raise exception.ParseResponseError(msg) validator["check_value"] = check_value # expect_value should only be in 2 types: # 1, variable reference, e.g. $expect_status_code # 2, actual value, e.g. 200 expect_value = self.eval_content(validator["expect"]) validator["expect"] = expect_value validator["check_result"] = "unchecked" return validator
def eval_check_item(self, validator, resp_obj): """ evaluate check item in validator @param (dict) validator {"check": "status_code", "comparator": "eq", "expect": 201} {"check": "$resp_body_success", "comparator": "eq", "expect": True} @param (object) resp_obj @return (dict) validator info { "check": "status_code", "check_value": 200, "expect": 201, "comparator": "eq" } """ check_item = validator["check"] # check_item should only be the following 5 formats: # 1, variable reference, e.g. $token # 2, function reference, e.g. ${is_status_code_200($status_code)} # 3, dict or list, maybe containing variable/function reference, e.g. {"var": "$abc"} # 4, string joined by delimiter. e.g. "status_code", "headers.content-type" # 5, regex string, e.g. "LB[\d]*(.*)RB[\d]*" if isinstance(check_item, (dict, list)) \ or testcase.extract_variables(check_item) \ or testcase.extract_functions(check_item): # format 1/2/3 check_value = self.eval_content(check_item) else: try: # format 4/5 check_value = resp_obj.extract_field(check_item) except exception.ParseResponseError: msg = "failed to extract check item from response!\n" msg += "response content: {}".format(resp_obj.content) raise exception.ParseResponseError(msg) validator["check_value"] = check_value # expect_value should only be in 2 types: # 1, variable reference, e.g. $expect_status_code # 2, actual value, e.g. 200 expect_value = self.eval_content(validator["expect"]) validator["expect"] = expect_value return validator
def eval_check_item(self, validator, resp_obj): """ evaluate check item in validator @param (dict) validator {"check": "status_code", "comparator": "eq", "expect": 201} {"check": "$resp_body_success", "comparator": "eq", "expect": True} @param (object) resp_obj @return (dict) validator info { "check": "status_code", "check_value": 200, "expect": 201, "comparator": "eq" } """ check_item = validator["check"] # check_item should only be in 3 types: # 1, variable reference, e.g. $token # 2, string joined by delimiter. e.g. "status_code", "headers.content-type" # 3, regex string, e.g. "LB[\d]*(.*)RB[\d]*" if testcase.extract_variables(check_item): # type 1 check_value = self.testcase_parser.eval_content_variables( check_item) else: try: # type 2 or type 3 check_value = resp_obj.extract_field(check_item) except exception.ParseResponseError: raise exception.ParseResponseError( "failed to extract check item in response!") validator["check_value"] = check_value # expect_value should only be in 2 types: # 1, variable reference, e.g. $expect_status_code # 2, actual value, e.g. 200 expect_value = self.testcase_parser.eval_content_variables( validator["expect"]) validator["expect"] = expect_value return validator
def parse_validator(self, validator, resp_obj): """ parse validator, validator maybe in two format @param (dict) validator format1: this is kept for compatiblity with the previous versions. {"check": "status_code", "comparator": "eq", "expect": 201} {"check": "$resp_body_success", "comparator": "eq", "expect": True} format2: recommended new version {'eq': ['status_code', 201]} {'eq': ['$resp_body_success', True]} @param (object) resp_obj @return (dict) validator info { "check_item": check_item, "check_value": check_value, "expect_value": expect_value, "comparator": comparator } """ if not isinstance(validator, dict): raise exception.ParamsError( "invalid validator: {}".format(validator)) if "check" in validator and len(validator) > 1: # format1 check_item = validator.get("check") if "expect" in validator: expect_value = validator.get("expect") elif "expected" in validator: expect_value = validator.get("expected") else: raise exception.ParamsError( "invalid validator: {}".format(validator)) comparator = validator.get("comparator", "eq") elif len(validator) == 1: # format2 comparator = list(validator.keys())[0] compare_values = validator[comparator] if not isinstance(compare_values, list) or len(compare_values) != 2: raise exception.ParamsError( "invalid validator: {}".format(validator)) check_item, expect_value = compare_values else: raise exception.ParamsError( "invalid validator: {}".format(validator)) # check_item should only be in 3 type: # 1, variable reference, e.g. $token # 2, string joined by delimiter. e.g. "status_code", "headers.content-type" # 3, regex string, e.g. "LB[\d]*(.*)RB[\d]*" if testcase.extract_variables(check_item): # type 1 check_value = self.testcase_parser.eval_content_variables( check_item) else: try: # type 2 or type 3 check_value = resp_obj.extract_field(check_item) except exception.ParseResponseError: raise exception.ParseResponseError( "failed to extract check item in response!") expect_value = self.testcase_parser.eval_content_variables( expect_value) validator_dict = { "check_item": check_item, "check_value": check_value, "expect_value": expect_value, "comparator": comparator } return validator_dict
def test_extract_variables(self): self.assertEqual( testcase.extract_variables("$var"), ["var"] ) self.assertEqual( testcase.extract_variables("$var123"), ["var123"] ) self.assertEqual( testcase.extract_variables("$var_name"), ["var_name"] ) self.assertEqual( testcase.extract_variables("var"), [] ) self.assertEqual( testcase.extract_variables("a$var"), ["var"] ) self.assertEqual( testcase.extract_variables("$v ar"), ["v"] ) self.assertEqual( testcase.extract_variables(" "), [] ) self.assertEqual( testcase.extract_variables("$abc*"), ["abc"] ) self.assertEqual( testcase.extract_variables("${func()}"), [] ) self.assertEqual( testcase.extract_variables("${func(1,2)}"), [] ) self.assertEqual( testcase.extract_variables("${gen_md5($TOKEN, $data, $random)}"), ["TOKEN", "data", "random"] )
def test_extract_variables(self): self.assertEqual( testcase.extract_variables("$var"), ["var"] ) self.assertEqual( testcase.extract_variables("$var123"), ["var123"] ) self.assertEqual( testcase.extract_variables("$var_name"), ["var_name"] ) self.assertEqual( testcase.extract_variables("var"), [] ) self.assertEqual( testcase.extract_variables("a$var"), ["var"] ) self.assertEqual( testcase.extract_variables("$v ar"), ["v"] ) self.assertEqual( testcase.extract_variables(" "), [] ) self.assertEqual( testcase.extract_variables("$abc*"), ["abc"] ) self.assertEqual( testcase.extract_variables("${func()}"), [] ) self.assertEqual( testcase.extract_variables("${func(1,2)}"), [] ) self.assertEqual( testcase.extract_variables("${gen_md5($TOKEN, $data, $random)}"), ["TOKEN", "data", "random"] )
def parse_validator(self, validator, resp_obj): """ parse validator, validator maybe in two format @param (dict) validator format1: this is kept for compatiblity with the previous versions. {"check": "status_code", "comparator": "eq", "expect": 201} {"check": "$resp_body_success", "comparator": "eq", "expect": True} format2: recommended new version {'eq': ['status_code', 201]} {'eq': ['$resp_body_success', True]} @param (object) resp_obj @return (dict) validator info { "check_item": check_item, "check_value": check_value, "expect_value": expect_value, "comparator": comparator } """ if not isinstance(validator, dict): raise exception.ParamsError("invalid validator: {}".format(validator)) if "check" in validator and len(validator) > 1: # format1 check_item = validator.get("check") if "expect" in validator: expect_value = validator.get("expect") elif "expected" in validator: expect_value = validator.get("expected") else: raise exception.ParamsError("invalid validator: {}".format(validator)) comparator = validator.get("comparator", "eq") elif len(validator) == 1: # format2 comparator = list(validator.keys())[0] compare_values = validator[comparator] if not isinstance(compare_values, list) or len(compare_values) != 2: raise exception.ParamsError("invalid validator: {}".format(validator)) check_item, expect_value = compare_values else: raise exception.ParamsError("invalid validator: {}".format(validator)) # check_item should only be in 3 type: # 1, variable reference, e.g. $token # 2, string joined by delimiter. e.g. "status_code", "headers.content-type" # 3, regex string, e.g. "LB[\d]*(.*)RB[\d]*" if testcase.extract_variables(check_item): # type 1 check_value = self.testcase_parser.eval_content_variables(check_item) else: try: # type 2 or type 3 check_value = resp_obj.extract_field(check_item) except exception.ParseResponseError: raise exception.ParseResponseError("failed to extract check item in response!") expect_value = self.testcase_parser.eval_content_variables(expect_value) validator_dict = { "check_item": check_item, "check_value": check_value, "expect_value": expect_value, "comparator": comparator } return validator_dict
def do_action(self, action): browser = self.browser retcode = n_step = 0 retmsg = None self.element = None action_before = action.get("BEFORE", None) if (action_before != None): logger.log_debug("func[%s]" % (action_before)) self.retval = self._eval_content_with_bindings(action_before) retcode, retmsg, n_step = self._parse_func_return(self.retval) if (retcode == 0 and n_step != 0): return 0 elif (retcode != 0): logger.log_error("Execute[BEFORE FUNC:%s] ERROR[%d][%s]" % (action_before, retcode, retmsg)) return retcode # if(action.has_key("FIND")): action_find = action.get("FIND", None) if (action_find != None): loc_tag = self._eval_content_with_bindings(action["TAG"]) if (action["FIND"] == "ID"): # element=browser.find_element_by_id(action["TAG"]) self.element = WebDriverWait(browser, 60, 0.5).until( EC.presence_of_element_located((By.ID, loc_tag))) elif (action["FIND"] == "CSS"): # element=browser.find_element_by_css_selector(action["TAG"]) self.element = WebDriverWait(browser, 60, 0.5).until( EC.presence_of_element_located((By.CSS_SELECTOR, loc_tag))) elif (action["FIND"] == "NAME"): # element=browser.find_element_by_name(action["TAG"]) self.element = WebDriverWait(browser, 60, 0.5).until( EC.presence_of_element_located((By.NAME, loc_tag))) elif (action["FIND"] == "TAG"): self.element = browser.find_elements_by_tag_name(loc_tag) # element=WebDriverWait(browser,60,0.5).until( # EC.presence_of_element_located((By.TAG_NAME, loc_tag))) elif (action["FIND"] == "NONE"): self.element = None else: logger.log_error("FIND ERROR[%s]" % (action["STEPNAME"])) retcode = -1 return retcode if (action["ACTION"] == "CLICK"): self.element.click() elif (action["ACTION"] == "CLEAR"): self.element.clear() elif (action["ACTION"] == "SEND_KEYS"): content = self._eval_content_with_bindings(action["CONTENT"]) self.element.send_keys(content) elif (action["ACTION"] == "GET"): content = self._eval_content_with_bindings(action["CONTENT"]) browser.get(content) elif (action["ACTION"] == "SWITCH_FRAME"): frame_name = "" for el in self.element: frame_name = el.get_attribute("name") if (action["CONTENT"] in frame_name): break else: frame_name = "" if (frame_name == ""): logger.log_error("FRAME[%s] not found" % (action["CONTENT"])) retcode = -3 return retcode else: browser.switch_to_frame(frame_name) else: func_name = action["ACTION"] logger.log_debug("func[%s]" % (func_name)) self.retval = self._eval_content_with_bindings(func_name) retcode, retmsg, n_step = self._parse_func_return(self.retval) if (retcode == 0 and n_step != 0): return retcode elif (retcode == 0 and "ACTION_RETURN" in action and action["ACTION_RETURN"] != None): retvar_list = testcase.extract_variables( action["ACTION_RETURN"]) data_dic = {} for i, key in enumerate(retvar_list): if (i in self.retval): data_dic[key.strip()] = self.retval[i] else: raise NameError("ACTION_RETURN error[%s] [%s]" % (func_name, action["ACTION_RETURN"])) self.context.bind_extracted_variables(data_dic) elif (retcode != 0): logger.log_error("Execute[ACTION FUNC:%s] ERROR[%d][%s]" % (func_name, retcode, retmsg)) return retcode # if(action.has_key("AFTER")): action_after = action.get("AFTER", None) if (action_after != None): logger.log_debug("func[%s]" % (action_after)) self.retval = self._eval_content_with_bindings(action_after) retcode, retmsg, n_step = self._parse_func_return(self.retval) if (retcode == 0 and n_step != 0): return retcode elif (retcode != 0): logger.log_error("Execute[AFTER FUNC:%s] ERROR[%d][%s]" % (action_after, retcode, retmsg)) return retcode return retcode