def __gen_options(self, scenario): options = etree.Element("options") global_think_time = scenario.get_think_time() if global_think_time: think_time = int(dehumanize_time(global_think_time)) options.append( etree.Element("option", name="thinktime", value=str(think_time), random="false")) global_tcp_timeout = scenario.get("timeout") if global_tcp_timeout: timeout = int(dehumanize_time(global_tcp_timeout) * 1000) options.append( etree.Element("option", name="connect_timeout", value=str(timeout))) global_max_retries = scenario.get("max-retries", 1) options.append( etree.Element("option", name="max_retries", value=str(global_max_retries))) return options
def __gen_load(self, load): """ Generate Tsung load profile. Tsung load progression is scenario-based. Virtual users are erlang processes which are spawned according to load profile. Each user executes assigned session (requests + think-time + logic) and then dies. :param scenario: :param load: :return: """ concurrency = load.concurrency if load.concurrency is not None else 1 load_elem = etree.Element("load") if load.duration: duration, unit = self.__time_to_tsung_time(int(round(load.duration))) load_elem.set('duration', str(duration)) load_elem.set('unit', unit) phases = [] if load.hold: duration, unit = self.__time_to_tsung_time(int(round(load.hold))) users = etree.Element("users", arrivalrate=str(concurrency), unit="second") phase = etree.Element("arrivalphase", phase=str("1"), duration=str(duration), unit=unit) phase.append(users) phases.append(phase) else: raise TaurusConfigError("Tsung: you must specify test duration with 'hold-for'") for phase in phases: load_elem.append(phase) return load_elem
def __dump_xml(self, filename): self.log.info("Dumping final status as XML: %s", filename) root = etree.Element("FinalStatus") if self.first_ts < float("inf") and self.last_ts > 0: duration_elem = etree.Element("TestDuration") duration_elem.text = str( round(float(self.last_ts - self.first_ts), 3)) root.append(duration_elem) report_info = get_bza_report_info(self.engine, self.log) if report_info: link, _ = report_info[0] report_element = etree.Element("ReportURL") report_element.text = link root.append(report_element) if self.last_sec: for label, kpiset in iteritems( self.last_sec[DataPoint.CUMULATIVE]): root.append(self.__get_xml_summary(label, kpiset)) with open(get_full_path(filename), 'wb') as fhd: tree = etree.ElementTree(root) tree.write(fhd, pretty_print=True, encoding="UTF-8", xml_declaration=True)
def process_sample_labels(self, xunit): """ :type xunit: XUnitFileWriter """ xunit.report_test_suite('sample_labels') 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]: rc = str(er_dict["rc"]) msg = str(er_dict["msg"]) cnt = str(er_dict["cnt"]) if er_dict["type"] == KPISet.ERRTYPE_ASSERT: err_element = etree.Element("failure", message=msg, type="Assertion Failure") else: err_element = etree.Element("error", message=msg, type="Error") err_desc = "%s\n(status code is %s)\n(total errors of this type: %s)" % ( msg, rc, cnt) err_element.text = err_desc errors.append(err_element) xunit.report_test_case('sample_labels', key, errors)
def process_functional(self, xunit): for suite_name, samples in iteritems(self.cumulative_results): duration = max(s.start_time for s in samples) - min(s.start_time for s in samples) duration += max(samples, key=lambda s: s.start_time).duration attrs = { "name": suite_name, "tests": str(len(samples)), "errors": str(len([sample for sample in samples if sample.status == "BROKEN"])), "skipped": str(len([sample for sample in samples if sample.status == "SKIPPED"])), "failures": str(len([sample for sample in samples if sample.status == "FAILED"])), "time": str(round(duration, 3)), # TODO: "timestamp" attribute } xunit.add_test_suite(suite_name, attributes=attrs) for sample in samples: attrs = { "classname": sample.test_suite, "name": sample.test_case, "time": str(round(sample.duration, 3)) } children = [] if sample.status == "BROKEN": error = etree.Element("error", type=sample.error_msg) if sample.error_trace: error.text = sample.error_trace children.append(error) elif sample.status == "FAILED": failure = etree.Element("failure", message=sample.error_msg) if sample.error_trace: failure.text = sample.error_trace children.append(failure) elif sample.status == "SKIPPED": skipped = etree.Element("skipped") children.append(skipped) xunit.add_test_case(suite_name, attributes=attrs, children=children)
def __gen_clients(self): # TODO: distributed clients? clients = etree.Element("clients") client = etree.Element("client", host="localhost", use_controller_vm="true") clients.append(client) return clients
def __gen_servers(self, scenario): default_address = scenario.get("default-address") if default_address: base_addr = parse.urlparse(default_address) else: first_request = self.__first_http_request(scenario) if not first_request: raise TaurusConfigError("Tsung: you must specify requests in scenario") base_addr = parse.urlparse(first_request.url) self.log.debug("default-address was not specified, using %s instead", base_addr.hostname) servers = etree.Element("servers") port = base_addr.port if base_addr.port is not None else 80 server = etree.Element("server", host=base_addr.hostname, port=str(port), type="tcp") servers.append(server) return servers
def add_test_case(self, suite_name, attributes=None, children=()): attributes = attributes or {} case = etree.Element("testcase", **attributes) for child in children: case.append(child)
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 __get_kpi_xml(self, kpi_name, kpi_val, param=None): kpi = etree.Element(kpi_name) kpi.attrib['value'] = self.__val_to_str(kpi_val) elm_name = etree.Element("name") elm_name.text = kpi_name if param is not None: kpi.attrib['param'] = self.__val_to_str(param) elm_name.text += "/" + param kpi.append(elm_name) elm_value = etree.Element("value") elm_value.text = self.__val_to_str(kpi_val) kpi.append(elm_value) return kpi
def process_pass_fail(self, xunit): """ :type xunit: XUnitFileWriter """ xunit.report_test_suite('bzt_pass_fail') 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.report_test_case('bzt_pass_fail', disp_name, errors)
def __init__(self, tsung_tool): self.log = logging.getLogger(self.__class__.__name__) self.root = etree.Element("tsung", loglevel="notice", version="1.0", dumptraffic="protocol", backend="text") self.tree = etree.ElementTree(self.root) self.tool = tsung_tool
def add_test_suite(self, suite_name, attributes=None, children=()): attributes = attributes or {} suite = etree.Element("testsuite", **attributes) for child in children: suite.append(child) if not suite_name in self.test_suites: self.test_suites[suite_name] = suite
def report_test_case(self, suite_name, case_name, children=None): """ :type suite_name: str :type case_name: str :type children: list[lxml.etree.Element] """ children = children or [] if self.report_urls: system_out = etree.Element("system-out") system_out.text = "".join(self.report_urls) children.insert(0, system_out) self.add_test_case(suite_name, attributes={"classname": self.class_name, "name": case_name}, children=children)
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.get_think_time(): think_time = int(dehumanize_time(request.get_think_time())) session.append(etree.Element("thinktime", value=str(think_time), random="false")) sessions.append(session) return sessions
def __get_xml_summary(self, label, kpiset): elem = etree.Element("Group", label=label) for kpi_name, kpi_val in iteritems(kpiset): if kpi_name in (KPISet.ERRORS, KPISet.RESP_TIMES): continue if isinstance(kpi_val, dict): for param_name, param_val in iteritems(kpi_val): elem.append(self.__get_kpi_xml(kpi_name, param_val, param_name)) else: elem.append(self.__get_kpi_xml(kpi_name, kpi_val)) return elem