def __init__(self, source, destination, network, timeout, debug=False): self.src_host, self.src_port = source self.dst_host, self.dst_port = destination self.socket = network self.stat = Stat() self.timeout = timeout self.debug = debug
def analyze(lang, text_file_name): global dwords global model if model is None: load_model(lang) text_path = os.path.join('texts', lang, text_file_name) stat = Stat(model, False, model.forms) print "Loading %s..." % text_path, tfile = codecs.open(text_path, 'rb', ENCODING) print 'True' lines = tfile.readlines() tfile.close() dwords = {} for line in lines: stat.add(line, dwords, True, model.forms) words = dwords.keys() words.sort(freq_cmp) show(">> There is %i known words:", stat.fwords, True) show(">> Found %i new words:", words, False, True) print
def _set_stats(self): self.critical_stats = Stat() self.all_stats = Stat() for suite in self.suites: suite.set_status() self._add_suite_to_stats(suite) for test in self.tests: self._add_test_to_stats(test)
def __init__(self, name, source=None, parent=None): _TestAndSuiteHelper.__init__(self, name, parent) self.source = source is not None and utils.normpath(source) or None self.metadata = utils.NormalizedDict() self.suites = [] self.tests = [] self.critical = _Critical() self.critical_stats = Stat() self.all_stats = Stat() if parent: parent.suites.append(self)
class DataHandler: # composition calculator = Stat() @classmethod def get_raw_data(filename): """ get_raw_data(filname) -> dict """ workbook = op.load_workbook(filename) ac = workbook.active g = ac.rows student = dict() for name, score in g: student[name.value] = score.value return student def __init__(self): # 아직 인스턴스가 만들어지지 않았는데 생성자가 인스턴스 메소드를 호출하는게 논리적으로 맞지 않으므로 수정함 # 물론 self.으로해도 잘 작동함 self.year_class = filename.split('_')[1] self.raw_data = DataHandler.get_raw_data(filename) self.scores = list(self.raw_data.values()) self.cache = {} def get_average(self): self.calculator.get_average() return avg def get_std_dev(self): pass
def __init__(self): # publishing as training data self.pub_teleop_vel = rospy.Publisher('train/cmd_vel', Twist, queue_size=1) self.pub_image = rospy.Publisher('train/image_raw', Image, queue_size=1) self.pub_intention = rospy.Publisher('train/intention', String, queue_size=1) self.name = "TeleController" # used for quatitive results self.stat = Stat(self.name)
class DataHandler(): #compostion calculater = Stat() @classmethod def get_raw_data(cls, filename): raw_data = {} wb = load_workbook(filename) ws = wb.active g = ws.rows for name_cell, scroll_cell in g: raw_data[name_cell.value] = scroll_cell.value return raw_data def __init__(self, filename): self.year_class = filename.split('_')[1] self.raw_data = DataHandler.get_raw_data(filename) self.scores = list(self.raw_data.values()) self.cache = {}
class DataHandler: evaluator = Stat() @classmethod def get_data_from_excel(cls, filename): """ get_data_from_excel(filename)->{'name1' : 'score1', 'name2' : 'score2', ...} 엑셀파일에서 데이터를 가져옵니다. 반환값은 key가 학생 이름이고 value가 점수인 딕셔너리입니다. """ raw_data = {} wb = load_workbook(filename) ws = wb.active g = ws.rows for name_cell, score_cell in g: raw_data[name_cell.value] = score_cell.value return raw_data def __init__(self, filename, year_class): self.rawdata = DataHandler.get_data_from_excel(filename) self.year_class = year_class self.cache = {} def get_scores(self): if 'scores' not in self.cache: self.cache['scores'] = list(self.rawdata.values()) return self.cache.get('scores') def get_average(self): if 'average' not in self.cache: self.cache['average'] = self.evaluator.get_average( self.get_scores()) return self.cache.get('average') def get_variance(self): if 'variance' not in self.cache: self.cache['variance'] = self.evaluator.get_variance( self.get_scores(), self.get_average()) return self.cache.get('variance') def get_standard_deviation(self): if 'standard_deviation' not in self.cache: self.cache['standard_deviation'] = self.evaluator.get_std_dev( self.get_variance()) return self.cache.get('standard_deviation') def evaluate_class(self, total_avrg, sd): """ evaluate_class(total_avrg, sd)->None total_avrg : 학년 전체 성적 평균 sd : 원하는 표준편차 기준 """ avrg = self.get_average() std_dev = self.get_standard_deviation() if avrg < 50 and std_dev > 20: print('성적이 너무 저조하고 학생들의 실력 차이가 너무 크다.') elif avrg > 50 and std_dev > 20: print('성적은 평균 이상이지만 학생들의 실력 차이가 크다. 주의 요망!') elif avrg < 50 and std_dev < 20: print('학생들의 실력 차이는 크지 않지만 성적이 너무 저조하다. 주의 요망!') elif avrg > 50 and std_dev < 20: print('성적도 평균 이상이고 학생들의 실력 차이도 크지 않다.') def get_evaluation(self, total_avrg, sd=20): print('*' * 50) print('{} 반 성적 분석 결과'.format(self.year_class)) print('{} 반의 평균은 {}점이고 분산은 {}이며 표준편차는 {}이다.'.format( self.year_class, self.get_average(), self.get_variance(), self.get_standard_deviation())) print('*' * 50) print('{}반 종합 평가'.format(self.year_class)) print('*' * 50) self.evaluate_class(total_avrg, sd)
class Ping: def __init__(self, source, destination, network, timeout, debug=False): self.src_host, self.src_port = source self.dst_host, self.dst_port = destination self.socket = network self.stat = Stat() self.timeout = timeout self.debug = debug def start(self, count, interval): counter = itertools.count(1) while count: code, resp_time = self.ping(next(counter)) self.stat.add(code, resp_time) res = (f'Ping {self.dst_host}:{self.dst_port} ' f'- {code} - time={round(resp_time * 1000, 3)}ms') print(res) count -= 1 if interval - resp_time > 0: time.sleep(interval - resp_time) self.stat.get() print(self.stat.sumup()) def ping(self, seq): self.socket.settimeout(self.timeout) tcppacket = self.build(seq, 2) start_time = time.time() self.socket.sendto(tcppacket, (self.dst_host, self.dst_port)) result, time_, recv_pack = self.parse_packages(start_time, seq) if self.debug: sniff(tcppacket, recv_pack) return result, time_ def parse_packages(self, start_time, seq): new_timeout = self.timeout while True: sock = self.socket.poll(new_timeout * 1000) if not sock: return Answer.TIMEOUT, 0, None else: resp_time = time.time() - start_time data = sock.recv(16384) # icmp check type_, code = struct.unpack('!BB', data[20:22]) if type_ == 3 and code == 1: src_port, dst_port, dst_seq = struct.unpack('!HHL', data[48:56]) if (self.src_port == src_port and self.dst_port == dst_port and seq == dst_seq): return Answer.HOST_UNREACHABLE, 0, data # tcp check answ = struct.unpack('!BBBBIIBB', data[20:34]) if answ[5] == seq + 1: if answ[7] == 18: # rst pack self.socket.sendto(self.build(seq, 4), (self.dst_host, self.dst_port)) return Answer.PORT_OPEN, resp_time, data return Answer.PORT_CLOSED, resp_time, data new_timeout = self.timeout - resp_time if new_timeout < 0: return Answer.TIMEOUT, 0, None continue def build(self, seq, flags): package = struct.pack( '!HHIIBBHHH', self.src_port, # Source Port self.dst_port, # Destination Port seq, # SEQ 0, # ACK 5 << 4, # Data Offset flags, # Flags 1024, # Window 0, # Checksum 0 # Urgent pointer ) pseudo_hdr = struct.pack( '!4s4sHH', socket.inet_aton(self.src_host), socket.inet_aton(self.dst_host), socket.IPPROTO_TCP, len(package) ) checksum = chksum(pseudo_hdr + package) package = package[:16] + struct.pack('H', checksum) + package[18:] return package
class BaseTestSuite(_TestAndSuiteHelper): """Base class for TestSuite used in runtime and by rebot.""" def __init__(self, name, source=None, parent=None): _TestAndSuiteHelper.__init__(self, name, parent) self.source = utils.abspath(source) if source else None self._id = None self.metadata = utils.NormalizedDict() self.suites = [] self.tests = [] self.critical = _Critical() self.critical_stats = Stat() self.all_stats = Stat() if parent: parent.suites.append(self) def set_name(self, name): if name: self.name = name elif self._is_multi_source_suite(): self.name = ' & '.join(suite.name for suite in self.suites) def _is_multi_source_suite(self): return self.parent is None and self.name == '' @property def id(self): if not self._id: self._find_root()._set_id() return self._id def _find_root(self): if self.parent: return self.parent._find_root() return self def _set_id(self): if not self._id: self._id = 's1' for index, suite in enumerate(self.suites): suite._id = '%s-s%s' % (self._id, index+1) suite._set_id() def set_critical_tags(self, critical, non_critical): if critical is not None or non_critical is not None: self.critical.set(critical, non_critical) self._set_critical_tags(self.critical) def _set_critical_tags(self, critical): self.critical = critical for suite in self.suites: suite._set_critical_tags(critical) for test in self.tests: test.set_criticality(critical) def set_doc(self, doc): if doc: self.doc = doc def set_metadata(self, metalist): for name, value in metalist: self.metadata[name] = value def get_metadata(self): return self.metadata.items() def get_test_count(self): count = len(self.tests) for suite in self.suites: count += suite.get_test_count() return count def get_full_message(self): """Returns suite's message including statistics message""" stat_msg = self.get_stat_message() if not self.message: return stat_msg return '%s\n\n%s' % (self.message, stat_msg) def get_stat_message(self): ctotal, cend, cpass, cfail = self._get_counts(self.critical_stats) atotal, aend, apass, afail = self._get_counts(self.all_stats) return ('%d critical test%s, %d passed, %d failed\n' '%d test%s total, %d passed, %d failed' % (ctotal, cend, cpass, cfail, atotal, aend, apass, afail)) def _get_counts(self, stat): ending = utils.plural_or_not(stat.total) return stat.total, ending, stat.passed, stat.failed def set_status(self): """Sets status and statistics based on subsuite and test statuses. Can/should be used when statuses have been changed somehow. """ self.status = self._set_stats() def _set_stats(self): self.critical_stats = Stat() self.all_stats = Stat() for suite in self.suites: suite.set_status() self._add_suite_to_stats(suite) for test in self.tests: self._add_test_to_stats(test) return self._get_status() def _get_status(self): return 'PASS' if not self.critical_stats.failed else 'FAIL' def _add_test_to_stats(self, test): self.all_stats.add_test(test) if test.critical == 'yes': self.critical_stats.add_test(test) def _add_suite_to_stats(self, suite): self.critical_stats.add_stat(suite.critical_stats) self.all_stats.add_stat(suite.all_stats) def suite_teardown_failed(self, message=None): if message: self._set_teardown_fail_msg(message) self.critical_stats.fail_all() self.all_stats.fail_all() self.status = self._get_status() sub_message = 'Teardown of the parent suite failed.' for suite in self.suites: suite.suite_teardown_failed(sub_message) for test in self.tests: test.suite_teardown_failed(sub_message) def set_tags(self, tags): if tags: for test in self.tests: test.tags = utils.normalize_tags(test.tags + tags) for suite in self.suites: suite.set_tags(tags) def filter(self, suites=None, tests=None, includes=None, excludes=None, zero_tests_ok=False): if suites or tests: self.filter_by_names(suites, tests, zero_tests_ok) if includes or excludes: self.filter_by_tags(includes, excludes, zero_tests_ok) def filter_by_names(self, suites=None, tests=None, zero_tests_ok=False): suites = [([], name.split('.')) for name in suites or []] tests = tests or [] if not self._filter_by_names(suites, tests) and not zero_tests_ok: self._raise_no_tests_filtered_by_names(suites, tests) def _filter_by_names(self, suites, tests): suites = self._filter_suite_names(suites) self.suites = [suite for suite in self.suites if suite._filter_by_names(suites, tests)] if not suites: self.tests = [test for test in self.tests if tests == [] or any(utils.matches_any(name, tests, ignore=['_']) for name in [test.name, test.longname])] else: self.tests = [] return bool(self.suites or self.tests) def _filter_suite_names(self, suites): try: return [self._filter_suite_name(p, s) for p, s in suites] except StopIteration: return [] def _filter_suite_name(self, parent, suite): if utils.matches(self.name, suite[0], ignore=['_']): if len(suite) == 1: raise StopIteration('Match found') return (parent + [suite[0]], suite[1:]) return ([], parent + suite) def _raise_no_tests_filtered_by_names(self, suites, tests): tests = utils.seq2str(tests, lastsep=' or ') suites = utils.seq2str(['.'.join(p + s) for p, s in suites], lastsep=' or ') if not suites: msg = 'test cases named %s.' % tests elif not tests: msg = 'test suites named %s.' % suites else: msg = 'test cases %s in suites %s.' % (tests, suites) raise DataError("Suite '%s' contains no %s" % (self.name, msg)) def filter_by_tags(self, includes=None, excludes=None, zero_tests_ok=False): includes = includes or [] excludes = excludes or [] if not self._filter_by_tags(includes, excludes) and not zero_tests_ok: self._raise_no_tests_filtered_by_tags(includes, excludes) def _filter_by_tags(self, incls, excls): self.suites = [suite for suite in self.suites if suite._filter_by_tags(incls, excls)] self.tests = [test for test in self.tests if test.is_included(incls, excls)] return bool(self.suites or self.tests) def _raise_no_tests_filtered_by_tags(self, incls, excls): incl = utils.seq2str(incls) excl = utils.seq2str(excls) msg = "Suite '%s' with " % self.name if incl: msg += 'includes %s ' % incl if excl: msg += 'and ' if excl: msg += 'excludes %s ' % excl raise DataError(msg + 'contains no test cases.') def set_runmode(self, runmode): runmode = runmode.upper() if runmode == 'EXITONFAILURE': self._run_mode_exit_on_failure = True elif runmode == 'SKIPTEARDOWNONEXIT': self._run_mode_skip_teardowns_on_exit = True elif runmode == 'DRYRUN': self._run_mode_dry_run = True elif runmode == 'RANDOM:TEST': random.shuffle(self.tests) elif runmode == 'RANDOM:SUITE': random.shuffle(self.suites) elif runmode == 'RANDOM:ALL': random.shuffle(self.suites) random.shuffle(self.tests) else: return for suite in self.suites: suite.set_runmode(runmode) def set_options(self, settings): self.set_tags(settings['SetTag']) self.filter(settings['SuiteNames'], settings['TestNames'], settings['Include'], settings['Exclude'], settings['RunEmptySuite']) self.set_name(settings['Name']) self.set_doc(settings['Doc']) self.set_metadata(settings['Metadata']) self.set_critical_tags(settings['Critical'], settings['NonCritical']) self._return_status_rc = not settings['NoStatusRC'] if 'RunMode' in settings: map(self.set_runmode, settings['RunMode']) if 'RemoveKeywords' in settings: self.remove_keywords(settings['RemoveKeywords']) def serialize(self, serializer): serializer.start_suite(self) if self.setup is not None: self.setup.serialize(serializer) if self.teardown is not None: self.teardown.serialize(serializer) for suite in self.suites: suite.serialize(serializer) for test in self.tests: test.serialize(serializer) serializer.end_suite(self) @property def return_code(self): rc = min(self.critical_stats.failed, 250) return rc if self._return_status_rc else 0
class BaseTestSuite(_TestAndSuiteHelper): """Base class for TestSuite used in runtime and by rebot.""" def __init__(self, name, source=None, parent=None): _TestAndSuiteHelper.__init__(self, name, parent) self.source = source is not None and utils.normpath(source) or None self.metadata = utils.NormalizedDict() self.suites = [] self.tests = [] self.critical = _Critical() self.critical_stats = Stat() self.all_stats = Stat() if parent: parent.suites.append(self) def set_name(self, name): if name: self.name = name elif not self.parent and self.name == '': # MultiSourceSuite self.name = ' & '.join([suite.name for suite in self.suites]) def set_critical_tags(self, critical, non_critical): if critical is not None or non_critical is not None: self.critical.set(critical, non_critical) self._set_critical_tags(self.critical) def _set_critical_tags(self, critical): self.critical = critical for suite in self.suites: suite._set_critical_tags(critical) for test in self.tests: test.set_criticality(critical) def set_doc(self, doc): if doc is not None: self.doc = doc def set_metadata(self, metalist): for metastr in metalist: try: name, value = metastr.split(':', 1) except ValueError: name, value = metastr, '' self.metadata[name] = value def get_metadata(self, html=False): names = sorted(self.metadata.keys()) values = [ self.metadata[n] for n in names ] if html: values = [ utils.html_escape(v, formatting=True) for v in values ] return zip(names, values) def get_test_count(self): count = len(self.tests) for suite in self.suites: count += suite.get_test_count() return count def get_full_message(self, html=False): """Returns suite's message including statistics message""" stat_msg = self.get_stat_message(html) if self.message == '': return stat_msg if not html: return '%s\n\n%s' % (self.message, stat_msg) return '%s<br /><br />%s' % (utils.html_escape(self.message), stat_msg) def get_stat_message(self, html=False): ctotal, cend, cpass, cfail = self._get_counts(self.critical_stats) atotal, aend, apass, afail = self._get_counts(self.all_stats) msg = ('%%d critical test%%s, %%d passed, %(cfail)s%%d failed%(end)s\n' '%%d test%%s total, %%d passed, %(afail)s%%d failed%(end)s') if html: msg = msg.replace(' ', ' ').replace('\n', '<br />') msg = msg % {'cfail': '<span%s>' % (cfail and ' class="fail"' or ''), 'afail': '<span%s>' % (afail and ' class="fail"' or ''), 'end': '</span>'} else: msg = msg % {'cfail': '', 'afail': '', 'end': ''} return msg % (ctotal, cend, cpass, cfail, atotal, aend, apass, afail) def _get_counts(self, stat): total = stat.passed + stat.failed ending = utils.plural_or_not(total) return total, ending, stat.passed, stat.failed def set_status(self): """Sets status and statistics based on subsuite and test statuses. Can/should be used when statuses have been changed somehow. """ self._set_stats() self.status = self.critical_stats.failed == 0 and 'PASS' or 'FAIL' def _set_stats(self): self.critical_stats = Stat() self.all_stats = Stat() for suite in self.suites: suite.set_status() self._add_suite_to_stats(suite) for test in self.tests: self._add_test_to_stats(test) def _add_test_to_stats(self, test): self.all_stats.add_test(test) if test.critical == 'yes': self.critical_stats.add_test(test) def _add_suite_to_stats(self, suite): self.critical_stats.add_stat(suite.critical_stats) self.all_stats.add_stat(suite.all_stats) def suite_teardown_failed(self, message=None): if message is not None: self._set_teardown_fail_msg(message) self.critical_stats.fail_all() self.all_stats.fail_all() self.status = self.critical_stats.failed == 0 and 'PASS' or 'FAIL' sub_message = 'Teardown of the parent suite failed.' for suite in self.suites: suite.suite_teardown_failed(sub_message) for test in self.tests: test.suite_teardown_failed(sub_message) def set_tags(self, tags): if tags: for test in self.tests: test.tags = utils.normalize_tags(test.tags + tags) for suite in self.suites: suite.set_tags(tags) def filter(self, suites=None, tests=None, includes=None, excludes=None): self.filter_by_names(suites, tests) self.filter_by_tags(includes, excludes) def filter_by_names(self, suites=None, tests=None): suites = [ ([], name.split('.')) for name in suites or [] ] tests = tests or [] if (suites or tests) and not self._filter_by_names(suites, tests): self._raise_no_tests_filtered_by_names(suites, tests) def _filter_by_names(self, suites, tests): suites = self._filter_suite_names(suites) self.suites = [ suite for suite in self.suites if suite._filter_by_names(suites, tests) ] if not suites: self.tests = [ test for test in self.tests if tests == [] or utils.matches_any(test.name, tests, ignore=['_']) ] else: self.tests = [] return self.suites or self.tests def _filter_suite_names(self, suites): try: return [ self._filter_suite_name(p, s) for p, s in suites ] except StopIteration: return [] def _filter_suite_name(self, parent, suite): if utils.matches(self.name, suite[0], ignore=['_']): if len(suite) == 1: raise StopIteration('Match found') return (parent + [suite[0]], suite[1:]) return ([], parent + suite) def _raise_no_tests_filtered_by_names(self, suites, tests): tests = utils.seq2str(tests, lastsep=' or ') suites = utils.seq2str([ '.'.join(p + s) for p, s in suites ], lastsep=' or ') if not suites: msg = 'test cases named %s.' % tests elif not tests: msg = 'test suites named %s.' % suites else: msg = 'test cases %s in suites %s.' % (tests, suites) raise DataError("Suite '%s' contains no %s" % (self.name, msg)) def filter_by_tags(self, includes=None, excludes=None): if not (includes or excludes): return if not includes: includes = [] if not excludes: excludes = [] if not self._filter_by_tags(includes, excludes): self._raise_no_tests_filtered_by_tags(includes, excludes) def _filter_by_tags(self, incls, excls): self.suites = [ suite for suite in self.suites if suite._filter_by_tags(incls, excls) ] self.tests = [ test for test in self.tests if test.is_included(incls, excls) ] return len(self.suites) + len(self.tests) > 0 def _raise_no_tests_filtered_by_tags(self, incls, excls): incl = utils.seq2str(incls) excl = utils.seq2str(excls) msg = "Suite '%s' with " % self.name if incl: msg += 'includes %s ' % incl if excl: msg += 'and ' if excl: msg += 'excludes %s ' % excl raise DataError(msg + 'contains no test cases.') def set_runmode(self, runmode): runmode = runmode.upper() if runmode == 'EXITONFAILURE': self._run_mode_exit_on_failure = True elif runmode == 'SKIPTEARDOWNONEXIT': self._run_mode_skip_teardowns_on_exit = True elif runmode == 'DRYRUN': self._run_mode_dry_run = True elif runmode == 'RANDOM:TEST': random.shuffle(self.tests) elif runmode == 'RANDOM:SUITE': random.shuffle(self.suites) elif runmode == 'RANDOM:ALL': random.shuffle(self.suites) random.shuffle(self.tests) else: return for suite in self.suites: suite.set_runmode(runmode) def set_options(self, settings): self.set_tags(settings['SetTag']) self.filter(settings['SuiteNames'], settings['TestNames'], settings['Include'], settings['Exclude']) self.set_name(settings['Name']) self.set_doc(settings['Doc']) self.set_metadata(settings['Metadata']) self.set_critical_tags(settings['Critical'], settings['NonCritical']) try: for runmode in settings['RunMode']: self.set_runmode(runmode) except (KeyError, AttributeError) : # Only applicable when running tcs pass if not self.suites: settings['SplitOutputs'] = -2 try: self.remove_keywords(settings['RemoveKeywords']) except (KeyError, AttributeError): # Only applicable with Rebot pass def serialize(self, serializer): serializer.start_suite(self) if self.setup is not None: self.setup.serialize(serializer) if self.teardown is not None: self.teardown.serialize(serializer) for suite in self.suites: suite.serialize(serializer) for test in self.tests: test.serialize(serializer) serializer.end_suite(self)
class BaseTestSuite(_TestAndSuiteHelper): """Base class for TestSuite used in runtime and by rebot.""" def __init__(self, name, source=None, parent=None): _TestAndSuiteHelper.__init__(self, name, parent) self.source = source is not None and utils.normpath(source) or None self.metadata = utils.NormalizedDict() self.suites = [] self.tests = [] self.critical = _Critical() self.critical_stats = Stat() self.all_stats = Stat() if parent: parent.suites.append(self) def set_name(self, name): if name: self.name = name elif not self.parent and self.name == '': # MultiSourceSuite self.name = ' & '.join([suite.name for suite in self.suites]) def set_critical_tags(self, critical, non_critical): if critical is not None or non_critical is not None: self.critical.set(critical, non_critical) self._set_critical_tags(self.critical) def _set_critical_tags(self, critical): self.critical = critical for suite in self.suites: suite._set_critical_tags(critical) for test in self.tests: test.set_criticality(critical) def set_doc(self, doc): if doc is not None: self.doc = doc def set_metadata(self, metalist): for metastr in metalist: try: name, value = metastr.split(':', 1) except ValueError: name, value = metastr, '' self.metadata[name] = value def get_metadata(self, html=False): names = sorted(self.metadata.keys()) values = [self.metadata[n] for n in names] if html: values = [utils.html_escape(v, formatting=True) for v in values] return zip(names, values) def get_test_count(self): count = len(self.tests) for suite in self.suites: count += suite.get_test_count() return count def get_full_message(self, html=False): """Returns suite's message including statistics message""" stat_msg = self.get_stat_message(html) if self.message == '': return stat_msg if not html: return '%s\n\n%s' % (self.message, stat_msg) return '%s<br /><br />%s' % (utils.html_escape(self.message), stat_msg) def get_stat_message(self, html=False): ctotal, cend, cpass, cfail = self._get_counts(self.critical_stats) atotal, aend, apass, afail = self._get_counts(self.all_stats) msg = ('%%d critical test%%s, %%d passed, %(cfail)s%%d failed%(end)s\n' '%%d test%%s total, %%d passed, %(afail)s%%d failed%(end)s') if html: msg = msg.replace(' ', ' ').replace('\n', '<br />') msg = msg % { 'cfail': '<span%s>' % (cfail and ' class="fail"' or ''), 'afail': '<span%s>' % (afail and ' class="fail"' or ''), 'end': '</span>' } else: msg = msg % {'cfail': '', 'afail': '', 'end': ''} return msg % (ctotal, cend, cpass, cfail, atotal, aend, apass, afail) def _get_counts(self, stat): total = stat.passed + stat.failed ending = utils.plural_or_not(total) return total, ending, stat.passed, stat.failed def set_status(self): """Sets status and statistics based on subsuite and test statuses. Can/should be used when statuses have been changed somehow. """ self._set_stats() self.status = self.critical_stats.failed == 0 and 'PASS' or 'FAIL' def _set_stats(self): self.critical_stats = Stat() self.all_stats = Stat() for suite in self.suites: suite.set_status() self._add_suite_to_stats(suite) for test in self.tests: self._add_test_to_stats(test) def _add_test_to_stats(self, test): self.all_stats.add_test(test) if test.critical == 'yes': self.critical_stats.add_test(test) def _add_suite_to_stats(self, suite): self.critical_stats.add_stat(suite.critical_stats) self.all_stats.add_stat(suite.all_stats) def suite_teardown_failed(self, message=None): if message is not None: self._set_teardown_fail_msg(message) self.critical_stats.fail_all() self.all_stats.fail_all() self.status = self.critical_stats.failed == 0 and 'PASS' or 'FAIL' sub_message = 'Teardown of the parent suite failed.' for suite in self.suites: suite.suite_teardown_failed(sub_message) for test in self.tests: test.suite_teardown_failed(sub_message) def set_tags(self, tags): if tags: for test in self.tests: test.tags = utils.normalize_tags(test.tags + tags) for suite in self.suites: suite.set_tags(tags) def filter(self, suites=None, tests=None, includes=None, excludes=None): self.filter_by_names(suites, tests) self.filter_by_tags(includes, excludes) def filter_by_names(self, suites=None, tests=None): suites = [([], name.split('.')) for name in suites or []] tests = tests or [] if (suites or tests) and not self._filter_by_names(suites, tests): self._raise_no_tests_filtered_by_names(suites, tests) def _filter_by_names(self, suites, tests): suites = self._filter_suite_names(suites) self.suites = [ suite for suite in self.suites if suite._filter_by_names(suites, tests) ] if not suites: self.tests = [ test for test in self.tests if tests == [] or utils.matches_any(test.name, tests, ignore=['_']) ] else: self.tests = [] return self.suites or self.tests def _filter_suite_names(self, suites): try: return [self._filter_suite_name(p, s) for p, s in suites] except StopIteration: return [] def _filter_suite_name(self, parent, suite): if utils.matches(self.name, suite[0], ignore=['_']): if len(suite) == 1: raise StopIteration('Match found') return (parent + [suite[0]], suite[1:]) return ([], parent + suite) def _raise_no_tests_filtered_by_names(self, suites, tests): tests = utils.seq2str(tests, lastsep=' or ') suites = utils.seq2str(['.'.join(p + s) for p, s in suites], lastsep=' or ') if not suites: msg = 'test cases named %s.' % tests elif not tests: msg = 'test suites named %s.' % suites else: msg = 'test cases %s in suites %s.' % (tests, suites) raise DataError("Suite '%s' contains no %s" % (self.name, msg)) def filter_by_tags(self, includes=None, excludes=None): if not (includes or excludes): return if not includes: includes = [] if not excludes: excludes = [] if not self._filter_by_tags(includes, excludes): self._raise_no_tests_filtered_by_tags(includes, excludes) def _filter_by_tags(self, incls, excls): self.suites = [ suite for suite in self.suites if suite._filter_by_tags(incls, excls) ] self.tests = [ test for test in self.tests if test.is_included(incls, excls) ] return len(self.suites) + len(self.tests) > 0 def _raise_no_tests_filtered_by_tags(self, incls, excls): incl = utils.seq2str(incls) excl = utils.seq2str(excls) msg = "Suite '%s' with " % self.name if incl: msg += 'includes %s ' % incl if excl: msg += 'and ' if excl: msg += 'excludes %s ' % excl raise DataError(msg + 'contains no test cases.') def set_runmode(self, runmode): runmode = runmode.upper() if runmode == 'EXITONFAILURE': self._run_mode_exit_on_failure = True elif runmode == 'SKIPTEARDOWNONEXIT': self._run_mode_skip_teardowns_on_exit = True elif runmode == 'DRYRUN': self._run_mode_dry_run = True elif runmode == 'RANDOM:TEST': random.shuffle(self.tests) elif runmode == 'RANDOM:SUITE': random.shuffle(self.suites) elif runmode == 'RANDOM:ALL': random.shuffle(self.suites) random.shuffle(self.tests) else: return for suite in self.suites: suite.set_runmode(runmode) def set_options(self, settings): self.set_tags(settings['SetTag']) self.filter(settings['SuiteNames'], settings['TestNames'], settings['Include'], settings['Exclude']) self.set_name(settings['Name']) self.set_doc(settings['Doc']) self.set_metadata(settings['Metadata']) self.set_critical_tags(settings['Critical'], settings['NonCritical']) try: for runmode in settings['RunMode']: self.set_runmode(runmode) except (KeyError, AttributeError): # Only applicable when running tcs pass if not self.suites: settings['SplitOutputs'] = -2 try: self.remove_keywords(settings['RemoveKeywords']) except (KeyError, AttributeError): # Only applicable with Rebot pass def serialize(self, serializer): serializer.start_suite(self) if self.setup is not None: self.setup.serialize(serializer) if self.teardown is not None: self.teardown.serialize(serializer) for suite in self.suites: suite.serialize(serializer) for test in self.tests: test.serialize(serializer) serializer.end_suite(self)