26 html_escape, is_list_like, py2to3,
27 split_args_from_name_or_path)
29 from .gatherfailed
import gather_failed_tests, gather_failed_suites
37 _cli_opts = {
'RPA' : (
'rpa',
None),
38 'Name' : (
'name',
None),
39 'Doc' : (
'doc',
None),
40 'Metadata' : (
'metadata', []),
41 'TestNames' : (
'test', []),
42 'TaskNames' : (
'task', []),
43 'ReRunFailed' : (
'rerunfailed',
'NONE'),
44 'ReRunFailedSuites': (
'rerunfailedsuites',
'NONE'),
45 'SuiteNames' : (
'suite', []),
46 'SetTag' : (
'settag', []),
47 'Include' : (
'include', []),
48 'Exclude' : (
'exclude', []),
49 'Critical' : (
'critical',
None),
50 'NonCritical' : (
'noncritical',
None),
51 'OutputDir' : (
'outputdir',
abspath(
'.')),
52 'Log' : (
'log',
'log.html'),
53 'Report' : (
'report',
'report.html'),
54 'XUnit' : (
'xunit',
None),
55 'SplitLog' : (
'splitlog',
False),
56 'TimestampOutputs' : (
'timestampoutputs',
False),
57 'LogTitle' : (
'logtitle',
None),
58 'ReportTitle' : (
'reporttitle',
None),
59 'ReportBackground' : (
'reportbackground',
60 (
'#9e9',
'#9e9',
'#f66')),
61 'SuiteStatLevel' : (
'suitestatlevel', -1),
62 'TagStatInclude' : (
'tagstatinclude', []),
63 'TagStatExclude' : (
'tagstatexclude', []),
64 'TagStatCombine' : (
'tagstatcombine', []),
65 'TagDoc' : (
'tagdoc', []),
66 'TagStatLink' : (
'tagstatlink', []),
67 'RemoveKeywords' : (
'removekeywords', []),
68 'FlattenKeywords' : (
'flattenkeywords', []),
69 'PreRebotModifiers': (
'prerebotmodifier', []),
70 'StatusRC' : (
'statusrc',
True),
71 'ConsoleColors' : (
'consolecolors',
'AUTO'),
72 'StdOut' : (
'stdout',
None),
73 'StdErr' : (
'stderr',
None),
74 'XUnitSkipNonCritical' : (
'xunitskipnoncritical',
False)}
78 _output_opts = [
'Output',
'Log',
'Report',
'XUnit',
'DebugFile']
80 def __init__(self, options=None, **extra_options):
89 value = opts[cli_name]
if cli_name
in opts
else default
90 if isinstance(default, list):
94 self[
'TestNames'] += self[
'ReRunFailed'] + self[
'TaskNames']
95 self[
'SuiteNames'] += self[
'ReRunFailedSuites']
99 raise KeyError(
"Non-existing option '%s'." % name)
100 self.
_opts_opts[name] = value
103 if name ==
'ReRunFailed':
105 if name ==
'ReRunFailedSuites':
107 if name ==
'LogLevel':
113 if name
in [
'Metadata',
'TagDoc']:
114 if name ==
'Metadata':
117 if name
in [
'Include',
'Exclude']:
119 if name
in self.
_output_opts_output_opts
and (
not value
or value.upper() ==
'NONE'):
121 if name ==
'OutputDir':
123 if name
in [
'SuiteStatLevel',
'ConsoleWidth']:
125 if name ==
'VariableFiles':
127 if name ==
'ReportBackground':
129 if name ==
'TagStatCombine':
131 if name ==
'TagStatLink':
133 if name ==
'Randomize':
135 if name ==
'MaxErrorLines':
137 if name ==
'RemoveKeywords':
139 if name ==
'FlattenKeywords':
141 if name ==
'WarnOnSkipped':
142 with LOGGER.cache_only:
143 LOGGER.warn(
"Option '--warnonskippedfiles' is deprecated and "
144 "has no effect. Nowadays all skipped files are "
153 self.
_opts_opts[
'VisibleLogLevel'] = visible_level
158 level, visible_level = level.split(
':', 1)
160 visible_level = level
162 return level, visible_level
165 if log_level
not in loggerhelper.LEVELS:
166 raise DataError(
"Invalid log level '%s'" % log_level)
167 if default
not in loggerhelper.LEVELS:
168 raise DataError(
"Invalid log level '%s'" % default)
169 if not loggerhelper.IsLogged(log_level)(default):
170 raise DataError(
"Default visible log level '%s' is lower than "
171 "log level '%s'" % (default, log_level))
174 if not value
or value.upper() ==
'NONE':
178 raise DataError(
"Option '--maxerrorlines' expected an integer "
179 "value greater that 10 but got '%s'." % value)
183 value = original.lower()
185 value, seed = value.split(
':', 1)
187 seed = random.randint(0, sys.maxsize)
188 if value
in (
'test',
'suite'):
190 if value
not in (
'tests',
'suites',
'none',
'all'):
199 raise DataError(
"Option '%s' does not support value '%s'."
200 % (option_name, given_value))
203 if name
not in self.
_opts_opts:
204 raise KeyError(
"Non-existing option '%s'." % name)
207 return self.
_opts_opts[name]
216 name = self.
_opts_opts[option]
219 if option ==
'Log' and self._output_disabled():
221 LOGGER.error(
'Log file is not created if output.xml is disabled.')
224 path =
abspath(os.path.join(self[
'OutputDir'], name))
229 base, ext = os.path.splitext(name)
230 if self[
'TimestampOutputs']:
238 if type_
in [
'Output',
'XUnit']:
240 if type_
in [
'Log',
'Report']:
242 if type_ ==
'DebugFile':
248 if not os.path.exists(path):
250 except EnvironmentError
as err:
251 raise DataError(
"Creating %s file directory '%s' failed: %s"
252 % (type_.lower(), path, err.strerror))
256 return value.split(
':', 1)
260 if colors.count(
':')
not in [1, 2]:
261 raise DataError(
"Invalid report background colors '%s'." % colors)
262 colors = colors.split(
':')
264 return colors[0], colors[0], colors[1]
269 pattern, title = pattern.rsplit(
':', 1)
275 for search, replace
in [(
'&',
'AND'), (
'AND',
' AND '), (
'OR',
' OR '),
276 (
'NOT',
' NOT '), (
'_',
' ')]:
277 if search
in pattern:
278 pattern = pattern.replace(search, replace)
279 while ' ' in pattern:
280 pattern = pattern.replace(
' ',
' ')
281 if pattern.startswith(
' NOT'):
282 pattern = pattern[1:]
286 tokens = value.split(
':')
288 return tokens[0],
':'.join(tokens[1:-1]), tokens[-1]
289 raise DataError(
"Invalid format for option '--tagstatlink'. "
290 "Expected 'tag:link:title' but got '%s'." % value)
300 raise DataError(
"Option '--%s' expected integer value but got '%s'."
301 % (name.lower(), value))
310 except DataError
as err:
311 raise DataError(
"Invalid value for option '--removekeywords'. %s" % err)
316 except DataError
as err:
317 raise DataError(
"Invalid value for option '--flattenkeywords'. %s" % err)
323 return '\n'.join(
'%s: %s' % (name, self.
_opts_opts[name])
324 for name
in sorted(self.
_opts_opts))
327 output_directory = property
330 return self[
'OutputDir']
336 return self[
'Output']
348 return self[
'Report']
360 return self[
'LogLevel']
366 return self[
'SplitLog']
372 return self[
'StatusRC']
375 xunit_skip_noncritical = property
378 return self[
'XUnitSkipNonCritical']
381 statistics_config = property
385 'suite_stat_level': self[
'SuiteStatLevel'],
386 'tag_stat_include': self[
'TagStatInclude'],
387 'tag_stat_exclude': self[
'TagStatExclude'],
388 'tag_stat_combine': self[
'TagStatCombine'],
389 'tag_stat_link': self[
'TagStatLink'],
390 'tag_doc': self[
'TagDoc'],
394 critical_tags = property
397 return self[
'Critical']
400 non_critical_tags = property
403 return self[
'NonCritical']
406 remove_keywords = property
409 return self[
'RemoveKeywords']
412 flatten_keywords = property
415 return self[
'FlattenKeywords']
418 pre_rebot_modifiers = property
421 return self[
'PreRebotModifiers']
424 console_colors = property
427 return self[
'ConsoleColors']
445 _extra_cli_opts = {
'Extension' : (
'extension',
None),
446 'Output' : (
'output',
'output.xml'),
447 'LogLevel' : (
'loglevel',
'INFO'),
448 'MaxErrorLines' : (
'maxerrorlines', 40),
449 'DryRun' : (
'dryrun',
False),
450 'ExitOnFailure' : (
'exitonfailure',
False),
451 'ExitOnError' : (
'exitonerror',
False),
452 'SkipTeardownOnExit' : (
'skipteardownonexit',
False),
453 'Randomize' : (
'randomize',
'NONE'),
454 'RunEmptySuite' : (
'runemptysuite',
False),
455 'WarnOnSkipped' : (
'warnonskippedfiles',
None),
456 'Variables' : (
'variable', []),
457 'VariableFiles' : (
'variablefile', []),
458 'PreRunModifiers' : (
'prerunmodifier', []),
459 'Listeners' : (
'listener', []),
460 'ConsoleType' : (
'console',
'verbose'),
461 'ConsoleTypeDotted' : (
'dotted',
False),
462 'ConsoleTypeQuiet' : (
'quiet',
False),
463 'ConsoleWidth' : (
'consolewidth', 78),
464 'ConsoleMarkers' : (
'consolemarkers',
'AUTO'),
465 'DebugFile' : (
'debugfile',
None)}
470 settings._opts.update(self.
_opts_opts)
471 for name
in [
'Variables',
'VariableFiles',
'Listeners']:
472 del(settings._opts[name])
473 for name
in [
'Include',
'Exclude',
'TestNames',
'SuiteNames',
'Metadata']:
474 settings._opts[name] = []
475 for name
in [
'Name',
'Doc']:
476 settings._opts[name] =
None
477 settings._opts[
'Output'] =
None
478 settings._opts[
'LogLevel'] =
'TRACE'
479 settings._opts[
'ProcessEmptySuite'] = self[
'RunEmptySuite']
492 return self[
'Listeners']
495 debug_file = property
498 return self[
'DebugFile']
501 suite_config = property
505 'name': self[
'Name'],
507 'metadata':
dict(self[
'Metadata']),
508 'set_tags': self[
'SetTag'],
509 'include_tags': self[
'Include'],
510 'exclude_tags': self[
'Exclude'],
511 'include_suites': self[
'SuiteNames'],
512 'include_tests': self[
'TestNames'],
520 randomize_seed = property
523 return self[
'Randomize'][1]
526 randomize_suites = property
529 return self[
'Randomize'][0]
in (
'suites',
'all')
532 randomize_tests = property
535 return self[
'Randomize'][0]
in (
'tests',
'all')
541 return self[
'DryRun']
543 exit_on_failure = property
546 return self[
'ExitOnFailure']
549 exit_on_error = property
552 return self[
'ExitOnError']
555 skip_teardown_on_exit = property
558 return self[
'SkipTeardownOnExit']
561 console_output_config = property
569 'stdout': self[
'StdOut'],
570 'stderr': self[
'StdErr']
574 console_type = property
577 if self[
'ConsoleTypeQuiet']:
579 if self[
'ConsoleTypeDotted']:
581 return self[
'ConsoleType']
584 console_width = property
587 return self[
'ConsoleWidth']
590 console_markers = property
593 return self[
'ConsoleMarkers']
596 max_error_lines = property
599 return self[
'MaxErrorLines']
602 pre_run_modifiers = property
605 return self[
'PreRunModifiers']
608 run_empty_suite = property
611 return self[
'RunEmptySuite']
617 return self[
'Variables']
620 variable_files = property
623 return self[
'VariableFiles']
629 return self[
'Extension']
636 _extra_cli_opts = {
'Output' : (
'output',
None),
637 'LogLevel' : (
'loglevel',
'TRACE'),
638 'ProcessEmptySuite' : (
'processemptysuite',
False),
639 'StartTime' : (
'starttime',
None),
640 'EndTime' : (
'endtime',
None),
641 'Merge' : (
'merge',
False)}
647 suite_config = property
651 'name': self[
'Name'],
653 'metadata':
dict(self[
'Metadata']),
654 'set_tags': self[
'SetTag'],
655 'include_tags': self[
'Include'],
656 'exclude_tags': self[
'Exclude'],
657 'include_suites': self[
'SuiteNames'],
658 'include_tests': self[
'TestNames'],
661 'log_level': self[
'LogLevel'],
664 'start_time': self[
'StartTime'],
665 'end_time': self[
'EndTime']
669 log_config = property
678 'splitLogBase': os.path.basename(os.path.splitext(self.
logloglog)[0]),
679 'defaultLevel': self[
'VisibleLogLevel']
683 report_config = property
701 colors = self[
'ReportBackground']
702 return {
'pass': colors[0],
'nonCriticalFail': colors[1],
'fail': colors[2]}
711 console_output_config = property
716 'stdout': self[
'StdOut'],
717 'stderr': self[
'StdErr']
721 process_empty_suite = property
724 return self[
'ProcessEmptySuite']
def _url_from_path(self, source, destination)
def _output_disabled(self)
def _resolve_background_colors(self)
def process_empty_suite(self)
def run_empty_suite(self)
def randomize_suites(self)
def randomize_tests(self)
def get_rebot_settings(self)
def _output_disabled(self)
def console_markers(self)
def _escape_as_data(self, value)
def _get_output_file(self, option)
Returns path of the requested output file and creates needed dirs.
def _process_randomize_value(self, original)
def _split_log_level(self, level)
def _convert_to_integer(self, name, value)
def _convert_to_positive_integer_or_default(self, name, value)
def _format_tag_patterns(self, pattern)
def __getitem__(self, name)
def _validate_flatten_keywords(self, values)
def _process_max_error_lines(self, value)
def __setitem__(self, name, value)
def _process_cli_opts(self, opts)
def _validate_remove_keywords(self, values)
def _process_report_background(self, colors)
def __contains__(self, setting)
def _raise_invalid_option_value(self, option_name, given_value)
def _validate_log_level_and_default(self, log_level, default)
def _process_output_name(self, option, name)
def _get_default_value(self, name)
def _escape_as_data(self, value)
def __init__(self, options=None, **extra_options)
def _create_output_dir(self, path, type_)
def non_critical_tags(self)
def remove_keywords(self)
def _process_tag_stat_combine(self, pattern)
def _process_metadata_or_tagdoc(self, value)
def _process_log_level(self, level)
def _process_value(self, name, value)
def _get_output_extension(self, ext, type_)
def _process_tag_stat_link(self, value)
Used when variable does not exist.
Can be used when the core framework goes to unexpected state.
def gather_failed_suites(output)
def gather_failed_tests(output)
def validate_flatten_keyword(options)
def html_escape(text, linkify=True)
def abspath(path, case_normalize=False)
Replacement for os.path.abspath with some enhancements and bug fixes.
def get_link_path(target, base)
Returns a relative path to target from base.
def format_time(timetuple_or_epochsecs, daysep='', daytimesep=' ', timesep=':', millissep=None)
Returns a timestamp formatted from given time using separators.
def split_args_from_name_or_path(name)