def _get_json_path_assertion(jsonpath, expected_value, json_validation, expect_null, invert): """ :type jsonpath: str :type expected_value: str :type json_validation: bool :type expect_null: bool :return: lxml.etree.Element """ package = "com.atlantbh.jmeter.plugins.jsonutils.jsonpathassertion" element = etree.Element("%s.JSONPathAssertion" % package, guiclass="%s.gui.JSONPathAssertionGui" % package, testclass="%s.JSONPathAssertion" % package, testname="JSon path assertion") element.append(JMX._string_prop("JSON_PATH", jsonpath)) element.append(JMX._string_prop("EXPECTED_VALUE", expected_value)) element.append(JMX._bool_prop("JSONVALIDATION", json_validation)) element.append(JMX._bool_prop("EXPECT_NULL", expect_null)) element.append(JMX._bool_prop("INVERT", invert)) return element
def __add_jsr_elements(children, req): """ :type children: etree.Element :type req: Request """ jsrs = req.config.get("jsr223", []) if not isinstance(jsrs, list): jsrs = [jsrs] for idx, _ in enumerate(jsrs): jsr = ensure_is_dict(jsrs, idx, sub_key='script-text') lang = jsr.get("language", "groovy") script_file = jsr.get("script-file", None) script_text = jsr.get("script-text", None) if not script_file and not script_text: raise TaurusConfigError("jsr223 element must specify one of 'script-file' or 'script-text'") parameters = jsr.get("parameters", "") execute = jsr.get("execute", "after") cache_key = str(jsr.get("compile-cache", True)).lower() children.append(JMX._get_jsr223_element(lang, script_file, parameters, execute, script_text, cache_key)) children.append(etree.Element("hashTree"))
def __gen_datasources(self, scenario): sources = scenario.get("data-sources", []) if not sources: return [] if not isinstance(sources, list): raise TaurusConfigError("data-sources '%s' is not a list" % sources) elements = [] for idx, source in enumerate(sources): source = ensure_is_dict(sources, idx, "path") source_path = source["path"] jmeter_var_pattern = re.compile("\${.+\}") delimiter = source.get('delimiter', None) if jmeter_var_pattern.search(source_path): msg = "Path to CSV contains JMeter variable/function, can't check for file existence: %s" self.log.warning(msg, source_path) if not delimiter: delimiter = ',' self.log.warning( "Can't detect CSV dialect, default delimiter will be '%s'", delimiter) else: modified_path = self.executor.engine.find_file(source_path) if not os.path.isfile(modified_path): raise TaurusConfigError("data-sources path not found: %s" % modified_path) if not delimiter: delimiter = self.__guess_delimiter(modified_path) source_path = get_full_path(modified_path) config = JMX._get_csv_config(source_path, delimiter, source.get("quoted", False), source.get("loop", True), source.get("variable-names", "")) elements.append(config) elements.append(etree.Element("hashTree")) return elements
def _get_extractor(varname, headers, regexp, template, match_no, default='NOT_FOUND'): """ :type varname: str :type regexp: str :type template: str|int :type match_no: int :type default: str :rtype: lxml.etree.Element """ if isinstance(template, int): template = '$%s$' % template if headers.lower() == 'headers': headers = 'true' elif headers.lower() == 'http-code': headers = 'code' else: headers = 'body' element = etree.Element("RegexExtractor", guiclass="RegexExtractorGui", testclass="RegexExtractor", testname="Get %s" % varname, enabled="true") element.append(JMX._string_prop("RegexExtractor.useHeaders", headers)) element.append(JMX._string_prop("RegexExtractor.refname", varname)) element.append(JMX._string_prop("RegexExtractor.regex", regexp)) element.append(JMX._string_prop("Sample.scope", "parent")) element.append(JMX._string_prop("RegexExtractor.template", template)) element.append(JMX._string_prop("RegexExtractor.default", default)) element.append( JMX._string_prop("RegexExtractor.match_number", match_no)) return element
def process_pass_fail(self): """ :return: etree element """ mods = self.engine.reporters + self.engine.services # TODO: remove it after migrating to service pass_fail_objects = [_x for _x in mods if isinstance(_x, PassFailStatus)] self.log.debug("Processing passfail objects: %s", pass_fail_objects) fail_criteria = [] for pf_obj in pass_fail_objects: if pf_obj.criteria: for _fc in pf_obj.criteria: fail_criteria.append(_fc) root_xml_element = etree.Element("testsuite", name='bzt_pass_fail', package="bzt") bza_report_info = self.get_bza_report_info() classname = bza_report_info[0][1] if bza_report_info else "bzt-" + str(self.__hash__()) report_urls = [info_item[0] for info_item in bza_report_info] for fc_obj in fail_criteria: testcase_etree = self.__process_criteria(classname, fc_obj, report_urls) root_xml_element.append(testcase_etree) return root_xml_element
def save_report(self, fname): """ :type fname: str """ try: if os.path.exists(fname): self.log.warning("File %s already exists, it will be overwritten", fname) else: dirname = os.path.dirname(fname) if dirname and not os.path.exists(dirname): os.makedirs(dirname) testsuites = etree.Element("testsuites") for _, suite in iteritems(self.test_suites): testsuites.append(suite) etree_obj = etree.ElementTree(testsuites) self.log.info("Writing JUnit XML report into: %s", fname) with open(get_full_path(fname), 'wb') as _fds: etree_obj.write(_fds, xml_declaration=True, encoding="UTF-8", pretty_print=True) except BaseException: raise TaurusInternalException("Cannot create file %s" % fname)
def process_pass_fail(self, xunit): """ :type xunit: XUnitFileWriter """ mods = self.engine.reporters + self.engine.services # TODO: remove it after passfail is only reporter pass_fail_objects = [ _x for _x in mods if isinstance(_x, PassFailStatus) ] self.log.debug("Processing passfail objects: %s", pass_fail_objects) fail_criteria = [] for pf_obj in pass_fail_objects: if pf_obj.criteria: for _fc in pf_obj.criteria: fail_criteria.append(_fc) for fc_obj in fail_criteria: if 'label' in fc_obj.config: data = (fc_obj.config['subject'], fc_obj.config['label'], fc_obj.config['condition'], fc_obj.config['threshold']) tpl = "%s of %s%s%s" else: data = (fc_obj.config['subject'], fc_obj.config['condition'], fc_obj.config['threshold']) tpl = "%s%s%s" if fc_obj.config['timeframe']: tpl += " for %s" data += (fc_obj.config['timeframe'], ) disp_name = tpl % data if fc_obj.is_triggered and fc_obj.fail: errors = [ etree.Element("error", message=str(fc_obj), type="pass/fail criteria triggered") ] else: errors = () xunit.add_test_case(disp_name, errors)
def process_sample_labels(self, xunit): """ :type xunit: XUnitFileWriter """ labels = self.last_second[DataPoint.CUMULATIVE] for key in sorted(labels.keys()): if key == "": # skip total label continue errors = [] for er_dict in labels[key][KPISet.ERRORS]: err_message = str(er_dict["rc"]) err_type = str(er_dict["msg"]) err_desc = "total errors of this type:" + str(er_dict["cnt"]) err_element = etree.Element("error", message=err_message, type=err_type) err_element.text = err_desc errors.append(err_element) xunit.add_test_case(key, errors)
def _get_json_extractor(varname, jsonpath, default='NOT_FOUND', from_variable=None): """ :type varname: str :type default: str :rtype: lxml.etree.Element """ package = "com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor" element = etree.Element("%s.JSONPathExtractor" % package, guiclass="%s.gui.JSONPathExtractorGui" % package, testclass="%s.JSONPathExtractor" % package, testname="Get %s" % varname) element.append(JMX._string_prop("VAR", varname)) element.append(JMX._string_prop("JSONPATH", jsonpath)) element.append(JMX._string_prop("DEFAULT", default)) if from_variable: element.append(JMX._string_prop("VARIABLE", from_variable)) element.append(JMX._string_prop("SUBJECT", "VAR")) return element
def _add_shaper(self, jmx): """ Add shaper :param jmx: JMX :return: """ if not self.load.duration: self.log.warning("You must set 'ramp-up' and/or 'hold-for' when using 'throughput' option") return etree_shaper = jmx.get_rps_shaper() if self.load.ramp_up: if isinstance(self.load.throughput, numeric_types) and self.load.duration: start_rps = self.load.throughput / float(self.load.duration) else: start_rps = 1 jmx.add_rps_shaper_schedule(etree_shaper, start_rps, self.load.throughput, self.load.ramp_up) if self.load.hold: jmx.add_rps_shaper_schedule(etree_shaper, self.load.throughput, self.load.throughput, self.load.hold) jmx.append(JMeterScenarioBuilder.TEST_PLAN_SEL, etree_shaper) jmx.append(JMeterScenarioBuilder.TEST_PLAN_SEL, etree.Element("hashTree"))
def __add_boundary_ext(self, children, req): extractors = req.config.get("extract-boundary") for varname, cfg in iteritems(extractors): subj = cfg.get('subject', 'body') left = cfg.get( 'left', TaurusConfigError( "Left boundary is missing for boundary extractor %s" % varname)) right = cfg.get( 'right', TaurusConfigError( "Right boundary is missing for boundary extractor %s" % varname)) match_no = cfg.get('match-no', 1) defvalue = cfg.get('default', 'NOT_FOUND') scope = cfg.get("scope", None) from_var = cfg.get("from-variable", None) extractor = JMX._get_boundary_extractor(varname, subj, left, right, match_no, defvalue, scope, from_var) children.append(extractor) children.append(etree.Element("hashTree"))
def _get_xpath_extractor(varname, xpath, default, validate_xml, ignore_whitespace, use_tolerant_parser): """ :type varname: str :type xpath: str :type default: str :type validate_xml: bool :type ignore_whitespace: bool :type use_tolerant_parser: bool :rtype: lxml.etree.Element """ element = etree.Element("XPathExtractor", guiclass="XPathExtractorGui", testclass="XPathExtractor", testname="Get %s" % varname) element.append(JMX._string_prop("XPathExtractor.refname", varname)) element.append(JMX._string_prop("XPathExtractor.xpathQuery", xpath)) element.append(JMX._string_prop("XPathExtractor.default", default)) element.append(JMX._bool_prop("XPathExtractor.validate", validate_xml)) element.append( JMX._bool_prop("XPathExtractor.whitespace", ignore_whitespace)) element.append( JMX._bool_prop("XPathExtractor.tolerant", use_tolerant_parser)) return element
def _get_loop_controller(loops): """ Generates Loop Controller Expected values(by JMeter): LoopController.loops(iterations): int LoopController.continue_forever: boolean :return: etree element, LoopController """ if loops == 'forever': iterations = -1 else: iterations = loops controller = etree.Element("LoopController", guiclass="LoopControlPanel", testclass="LoopController", testname="Loop Controller") controller.append( JMX._bool_prop("LoopController.continue_forever", False)) # always false except of root LC controller.append( JMX._string_prop("LoopController.loops", str(iterations))) return controller
def __gen_data_sources(self, scenario): elements = [] for source in scenario.get_data_sources(): source_path = source["path"] delimiter = source.get("delimiter") if has_variable_pattern(source_path): msg = "Path to CSV contains JMeter variable/function, can't check for file existence: %s" self.log.warning(msg, source_path) if not delimiter: delimiter = ',' self.log.warning("Can't detect CSV dialect, default delimiter will be '%s'", delimiter) else: source_path = self.executor.engine.find_file(source_path) if not os.path.isfile(source_path): raise TaurusConfigError("data-sources path not found: %s" % source_path) if not delimiter: delimiter = guess_delimiter(source_path) config = JMX._get_csv_config(source_path, delimiter, source.get("quoted", False), source.get("loop", True), source.get("variable-names", "")) elements.append(config) elements.append(etree.Element("hashTree")) return elements
def __gen_sessions(self, scenario): sessions = etree.Element("sessions") session = etree.Element("session", name="taurus_requests", probability="100", type="ts_http") for request in scenario.get_requests(): request_elem = etree.Element("request") http_elem = etree.Element("http", url=request.url, method=request.method, version="1.1") if request.body: http_elem.set('contents', request.body) headers = copy.deepcopy(scenario.get_headers()) headers.update(copy.deepcopy(request.headers)) for header_name, header_value in iteritems(headers): http_elem.append(etree.Element("http_header", name=header_name, value=header_value)) request_elem.append(http_elem) session.append(request_elem) if request.think_time is not None: think_time = int(dehumanize_time(request.think_time)) session.append(etree.Element("thinktime", value=str(think_time), random="false")) sessions.append(session) return sessions
def __gen_sessions(self, scenario): sessions = etree.Element("sessions") session = etree.Element("session", name="taurus_requests", probability="100", type="ts_http") for request in scenario.get_requests(): if not isinstance(request, HTTPRequest): msg = "Tsung config generator doesn't support '%s' blocks, skipping" self.log.warning(msg, request.NAME) continue request_elem = etree.Element("request") http_elem = etree.Element("http", url=request.url, method=request.method, version="1.1") if request.body: http_elem.set('contents', request.body) headers = copy.deepcopy(scenario.get_headers()) headers.update(copy.deepcopy(request.headers)) for header_name, header_value in iteritems(headers): http_elem.append( etree.Element("http_header", name=header_name, value=header_value)) request_elem.append(http_elem) session.append(request_elem) if request.think_time is not None: think_time = int(dehumanize_time(request.think_time)) session.append( etree.Element("thinktime", value=str(think_time), random="false")) sessions.append(session) return sessions
def _get_simple_controller(name): return etree.Element("GenericController", guiclass="LogicControllerGui", testclass="GenericController", testname=name)
def gen_method_statement(self, statement, indent="8"): statement_elem = etree.Element("statement", indent=indent) statement_elem.text = statement return statement_elem
def gen_method_definition(self, method_name, params, indent="4"): def_tmpl = "def {method_name}({params}):" method_def_element = etree.Element("method_definition", indent=indent) method_def_element.text = def_tmpl.format(method_name=method_name, params=",".join(params)) return method_def_element
def gen_class_definition(self, class_name, inherits_from, indent="0"): def_tmpl = "class {class_name}({inherits_from}):" class_def_element = etree.Element("class_definition", indent=indent) class_def_element.text = def_tmpl.format(class_name=class_name, inherits_from="".join(inherits_from)) return class_def_element
def add_imports(self): imports = etree.Element("imports") imports.text = NoseTest.IMPORTS return imports
def _get_http_defaults(default_address=None, timeout=None, retrieve_resources=None, concurrent_pool_size=4, content_encoding=None, resources_regex=None): """ :rtype: lxml.etree.Element """ cfg = etree.Element("ConfigTestElement", guiclass="HttpDefaultsGui", testclass="ConfigTestElement", testname="Defaults") if retrieve_resources: cfg.append(JMX._bool_prop("HTTPSampler.image_parser", True)) cfg.append(JMX._bool_prop("HTTPSampler.concurrentDwn", True)) if concurrent_pool_size: cfg.append( JMX._string_prop("HTTPSampler.concurrentPool", concurrent_pool_size)) params = etree.Element("elementProp", name="HTTPsampler.Arguments", elementType="Arguments", guiclass="HTTPArgumentsPanel", testclass="Arguments", testname="user_defined") cfg.append(params) if default_address: parsed_url = parse.urlsplit(default_address) if parsed_url.scheme: cfg.append( JMX._string_prop("HTTPSampler.protocol", parsed_url.scheme)) if parsed_url.netloc: netloc = parsed_url.netloc if ':' in netloc: index = netloc.rfind(':') cfg.append( JMX._string_prop("HTTPSampler.port", netloc[index + 1:])) netloc = netloc[:index] cfg.append(JMX._string_prop("HTTPSampler.domain", netloc)) if timeout: cfg.append(JMX._string_prop("HTTPSampler.connect_timeout", timeout)) cfg.append( JMX._string_prop("HTTPSampler.response_timeout", timeout)) if content_encoding: cfg.append( JMX._string_prop("HTTPSampler.contentEncoding", content_encoding)) if resources_regex: cfg.append( JMX._string_prop("HTTPSampler.embedded_url_re", resources_regex)) return cfg
def gen_decorator_statement(decorator_name, indent=4): def_tmpl = "@{decorator_name}" decorator_element = etree.Element("decorator_statement", indent=str(indent)) decorator_element.text = def_tmpl.format(decorator_name=decorator_name) return decorator_element
def _get_results_tree(): dbg_tree = etree.Element("ResultCollector", testname="View Results Tree", testclass="ResultCollector", guiclass="ViewResultsFullVisualizer") return dbg_tree
def _get_http_request(url, label, method, timeout, body, keepalive, files=(), encoding=None, follow_redirects=True): """ Generates HTTP request :type method: str :type label: str :type url: str :rtype: lxml.etree.Element """ proxy = etree.Element("HTTPSamplerProxy", guiclass="HttpTestSampleGui", testclass="HTTPSamplerProxy") proxy.set("testname", label) args = JMX._get_arguments_panel("HTTPsampler.Arguments") if isinstance(body, string_types): JMX.__add_body_from_string(args, body, proxy) elif isinstance(body, dict): JMX.__add_body_from_script(args, body, proxy) elif body: msg = "Cannot handle 'body' option of type %s: %s" raise TaurusInternalException(msg % (type(body), body)) parsed_url = parse.urlparse(url) JMX.__add_hostnameport_2sampler(parsed_url, proxy, url) path = parsed_url.path if parsed_url.query: path += "?" + parsed_url.query proxy.append(JMX._string_prop("HTTPSampler.path", path)) proxy.append(JMX._string_prop("HTTPSampler.method", method)) proxy.append(JMX._bool_prop("HTTPSampler.use_keepalive", keepalive)) proxy.append( JMX._bool_prop("HTTPSampler.follow_redirects", follow_redirects)) proxy.append(JMX._bool_prop("HTTPSampler.auto_redirects", False)) if timeout is not None: proxy.append( JMX._string_prop("HTTPSampler.connect_timeout", timeout)) proxy.append( JMX._string_prop("HTTPSampler.response_timeout", timeout)) if encoding is not None: proxy.append( JMX._string_prop("HTTPSampler.contentEncoding", encoding)) if files: proxy.append(JMX._bool_prop("HTTPSampler.DO_MULTIPART_POST", True)) proxy.append( JMX._bool_prop("HTTPSampler.BROWSER_COMPATIBLE_MULTIPART", True)) files_prop = JMX._element_prop("HTTPsampler.Files", "HTTPFileArgs") files_coll = JMX._collection_prop("HTTPFileArgs.files") for file_dict in files: file_elem = JMX._element_prop(file_dict['path'], "HTTPFileArg") file_elem.append( JMX._string_prop("File.path", file_dict['path'])) file_elem.append( JMX._string_prop("File.paramname", file_dict["param"])) file_elem.append( JMX._string_prop("File.mimetype", file_dict['mime-type'])) files_coll.append(file_elem) files_prop.append(files_coll) proxy.append(files_prop) return proxy
def gen_statement(statement, indent=8): statement_elem = etree.Element("statement", indent=str(indent)) statement_elem.text = statement return statement_elem
def _get_cookie_mgr(scenario=None): """ :rtype: lxml.etree.Element """ mgr = etree.Element("CookieManager", guiclass="CookiePanel", testclass="CookieManager", testname="Cookies") mgr.append(JMX._bool_prop("CookieManager.clearEachIteration", True)) mgr.append( JMX._string_prop( "CookieManager.implementation", "org.apache.jmeter.protocol.http.control.HC4CookieHandler")) if scenario: cookies = scenario.get(Scenario.COOKIES, []) if cookies: cookies_coll = JMX._collection_prop("CookieManager.cookies") mgr.append(cookies_coll) for cookie in cookies: if not isinstance(cookie, dict): raise TaurusConfigError( "Cookie must be dictionary: %s" % cookie) c_name = cookie.get( "name", TaurusConfigError("Name of cookie isn't found: %s" % cookie)) c_value = cookie.get( "value", TaurusConfigError("Value of cookie isn't found: %s" % cookie)) c_domain = cookie.get( "domain", TaurusConfigError("Domain of cookie isn't found: %s" % cookie)) c_path = cookie.get("path", "") c_secure = cookie.get("secure", False) # follow params are hardcoded in JMeter c_expires = 0 c_path_specified = True c_domain_specified = True c_elem = etree.Element("elementProp", name=c_name, elementType="Cookie", testname=c_name) c_elem.append(JMX._string_prop("Cookie.value", c_value)) c_elem.append(JMX._string_prop("Cookie.domain", c_domain)) c_elem.append(JMX._string_prop("Cookie.path", c_path)) c_elem.append(JMX._bool_prop("Cookie.secure", c_secure)) c_elem.append(JMX._long_prop("Cookie.expires", c_expires)) c_elem.append( JMX._bool_prop("Cookie.path_specified", c_path_specified)) c_elem.append( JMX._bool_prop("Cookie.domain_specified", c_domain_specified)) cookies_coll.append(c_elem) return mgr
def __init__(self): self.root = etree.Element("NoseTest") self.tree = etree.ElementTree(self.root)
def __add_think_time(self, children, req): think_time = req.priority_option('think-time') if think_time is not None: children.append( JMX._get_constant_timer(self.smart_time(think_time))) children.append(etree.Element("hashTree"))
def __init__(self, scenario, parent_logger): self.root = etree.Element("PythonCode") self.tree = etree.ElementTree(self.root) self.log = parent_logger.getChild(self.__class__.__name__) self.scenario = scenario