diff --git a/atest/resources/TestCheckerLibrary.py b/atest/resources/TestCheckerLibrary.py index 3ec3df4d0cf..7fe1333119f 100644 --- a/atest/resources/TestCheckerLibrary.py +++ b/atest/resources/TestCheckerLibrary.py @@ -136,7 +136,7 @@ def _check_test_status(self, test, status=None, message=None): test.exp_status = status if message is not None: test.exp_message = message - if test.exp_status != test.status: + if test.exp_status != test.status and test.status in ['PASS', 'FAIL', 'SKIP']: if test.exp_status == 'PASS': if test.status == 'FAIL': msg = ("Test '%s' was expected to PASS but it FAILED.\n\n" diff --git a/atest/robot/output/custom_statuses.robot b/atest/robot/output/custom_statuses.robot new file mode 100644 index 00000000000..44cd57eeecd --- /dev/null +++ b/atest/robot/output/custom_statuses.robot @@ -0,0 +1,37 @@ +*** Settings *** +Suite Setup Run With Custom Statuses +Resource atest_resource.robot + +*** Variables *** +${ADDSTATUS} --AddStatus WIP:PASS:wip:blue --addstatus KNOWN-ISSUE:FAIL:known-*:purple --ADDSTATUS NON-CRITICAL:SKIP:non-criticalNOTwip:pink --log log.html +${ERROR} [ ERROR ] Invalid format for option '--addstatus'. Expected 'NEWSTATUS:OLDSTATUS:TAGPATTERN:COLOR' but got 'invalid'.${USAGE TIP}\n + +*** Test Cases *** +Check statuses + Should Be Equal ${TC1.status} WIP + Log should have correct custom status color WIP blue + Should Be Equal ${TC2.status} KNOWN-ISSUE + Log should have correct custom status color KNOWN-ISSUE purple + Should Be Equal ${TC3.status} NON-CRITICAL + Log should have correct custom status color NON-CRITICAL pink + +Invalid usage + Run Tests Without Processing Output --AddStatus invalid output/custom_statuses.robot + Stderr Should Be Equal To ${ERROR} + +*** Keywords *** +Run With Custom Statuses + Run Tests ${ADDSTATUS} output/custom_statuses.robot + ${LOG} = Get File ${OUTDIR}/log.html + Set Suite Variable $LOG + ${TC1} = Check Test Case Pass message=Pass + Set Suite Variable $TC1 + ${TC2} = Check Test Case Fail message=Fail + Set Suite Variable $TC2 + ${TC3} = Check Test Case Skip message=Skip + Set Suite Variable $TC3 + +Log should have correct custom status color + [Arguments] ${status} ${color} + Log ${LOG} + Should Contain ${LOG} "${status}":"${color}" diff --git a/atest/testdata/output/custom_statuses.robot b/atest/testdata/output/custom_statuses.robot new file mode 100644 index 00000000000..03f1aa0ac49 --- /dev/null +++ b/atest/testdata/output/custom_statuses.robot @@ -0,0 +1,12 @@ +*** Test Cases *** +Pass + [Tags] wip + Pass Execution Pass + +Fail + [Tags] known-issue + Fail Fail + +Skip + [Tags] non-critical + Skip Skip diff --git a/doc/userguide/src/ExecutingTestCases/log_failed.html b/doc/userguide/src/ExecutingTestCases/log_failed.html index 2b4d2ec992f..158abaa0169 100644 --- a/doc/userguide/src/ExecutingTestCases/log_failed.html +++ b/doc/userguide/src/ExecutingTestCases/log_failed.html @@ -1322,7 +1322,6 @@ var idCounter = 0; var _statistics = null; var LEVELS = ['TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FAIL', 'SKIP']; - var STATUSES = ['FAIL', 'PASS', 'NOT_RUN', 'SKIP']; var KEYWORDS = ['KEYWORD', 'SETUP', 'TEARDOWN', 'FOR', 'VAR', 'IF', 'ELSE IF', 'ELSE']; function addElement(elem) { if (!elem.id) @@ -1350,7 +1349,7 @@ strings.get(element[3]))); } function parseStatus(stats) { - return STATUSES[stats[0]]; + return stats[0]; } function childCreator(parent, childType) { return function (elem, strings, index) { diff --git a/doc/userguide/src/ExecutingTestCases/log_passed.html b/doc/userguide/src/ExecutingTestCases/log_passed.html index 0ecd8b9c9be..0b0a099b991 100644 --- a/doc/userguide/src/ExecutingTestCases/log_passed.html +++ b/doc/userguide/src/ExecutingTestCases/log_passed.html @@ -1322,7 +1322,6 @@ var idCounter = 0; var _statistics = null; var LEVELS = ['TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FAIL', 'SKIP']; - var STATUSES = ['FAIL', 'PASS', 'NOT_RUN', 'SKIP']; var KEYWORDS = ['KEYWORD', 'SETUP', 'TEARDOWN', 'FOR', 'VAR', 'IF', 'ELSE IF', 'ELSE']; function addElement(elem) { if (!elem.id) @@ -1350,7 +1349,7 @@ strings.get(element[3]))); } function parseStatus(stats) { - return STATUSES[stats[0]]; + return stats[0]; } function childCreator(parent, childType) { return function (elem, strings, index) { diff --git a/doc/userguide/src/ExecutingTestCases/log_skipped.html b/doc/userguide/src/ExecutingTestCases/log_skipped.html index 176675f8617..2e4f8a5364c 100644 --- a/doc/userguide/src/ExecutingTestCases/log_skipped.html +++ b/doc/userguide/src/ExecutingTestCases/log_skipped.html @@ -1322,7 +1322,6 @@ var idCounter = 0; var _statistics = null; var LEVELS = ['TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FAIL', 'SKIP']; - var STATUSES = ['FAIL', 'PASS', 'NOT_RUN', 'SKIP']; var KEYWORDS = ['KEYWORD', 'SETUP', 'TEARDOWN', 'FOR', 'VAR', 'IF', 'ELSE IF', 'ELSE']; function addElement(elem) { if (!elem.id) @@ -1350,7 +1349,7 @@ strings.get(element[3]))); } function parseStatus(stats) { - return STATUSES[stats[0]]; + return stats[0]; } function childCreator(parent, childType) { return function (elem, strings, index) { diff --git a/doc/userguide/src/ExecutingTestCases/report_failed.html b/doc/userguide/src/ExecutingTestCases/report_failed.html index d403704f74b..0576fe52e25 100644 --- a/doc/userguide/src/ExecutingTestCases/report_failed.html +++ b/doc/userguide/src/ExecutingTestCases/report_failed.html @@ -917,7 +917,6 @@ var idCounter = 0; var _statistics = null; var LEVELS = ['TRACE', 'DEBUG', 'INFO', 'WARN', 'FAIL', 'ERROR']; - var STATUSES = ['FAIL', 'PASS', 'NOT_RUN']; var KEYWORDS = ['KEYWORD', 'SETUP', 'TEARDOWN', 'FOR', 'VAR']; function addElement(elem) { @@ -954,7 +953,7 @@ function parseStatus(stats, strings, parentSuiteTeardownFailed) { if (parentSuiteTeardownFailed) return 'FAIL'; - return STATUSES[stats[0]]; + return stats[0]; } function last(items) { diff --git a/doc/userguide/src/ExecutingTestCases/report_passed.html b/doc/userguide/src/ExecutingTestCases/report_passed.html index b5dcf39a60a..7f1592ee401 100644 --- a/doc/userguide/src/ExecutingTestCases/report_passed.html +++ b/doc/userguide/src/ExecutingTestCases/report_passed.html @@ -1126,7 +1126,6 @@ var idCounter = 0; var _statistics = null; var LEVELS = ['TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FAIL', 'SKIP']; - var STATUSES = ['FAIL', 'PASS', 'NOT_RUN', 'SKIP']; var KEYWORDS = ['KEYWORD', 'SETUP', 'TEARDOWN', 'FOR', 'VAR', 'IF', 'ELSE IF', 'ELSE']; function addElement(elem) { if (!elem.id) @@ -1154,7 +1153,7 @@ strings.get(element[3]))); } function parseStatus(stats) { - return STATUSES[stats[0]]; + return stats[0]; } function childCreator(parent, childType) { return function (elem, strings, index) { diff --git a/doc/userguide/src/ExecutingTestCases/visible_log_level.html b/doc/userguide/src/ExecutingTestCases/visible_log_level.html index 0141f65163e..9f12e39669b 100644 --- a/doc/userguide/src/ExecutingTestCases/visible_log_level.html +++ b/doc/userguide/src/ExecutingTestCases/visible_log_level.html @@ -1073,7 +1073,6 @@ var idCounter = 0; var _statistics = null; var LEVELS = ['TRACE', 'DEBUG', 'INFO', 'WARN', 'FAIL', 'ERROR']; - var STATUSES = ['FAIL', 'PASS', 'NOT_RUN']; var KEYWORDS = ['KEYWORD', 'SETUP', 'TEARDOWN', 'FOR', 'VAR']; function addElement(elem) { @@ -1108,7 +1107,7 @@ } function parseStatus(stats) { - return STATUSES[stats[0]]; + return stats[0]; } function last(items) { diff --git a/src/robot/conf/settings.py b/src/robot/conf/settings.py index 97caeebe0d2..0021bdfa76a 100644 --- a/src/robot/conf/settings.py +++ b/src/robot/conf/settings.py @@ -69,7 +69,8 @@ class _BaseSettings(object): 'ConsoleColors' : ('consolecolors', 'AUTO'), 'StdOut' : ('stdout', None), 'StdErr' : ('stderr', None), - 'XUnitSkipNonCritical' : ('xunitskipnoncritical', False)} + 'XUnitSkipNonCritical' : ('xunitskipnoncritical', False), + 'AddStatus' : ('addstatus', [])} _output_opts = ['Output', 'Log', 'Report', 'XUnit', 'DebugFile'] def __init__(self, options=None, **extra_options): @@ -137,8 +138,16 @@ def _process_value(self, name, value): self._validate_expandkeywords(value) if name == 'Extension': return tuple(ext.lower().lstrip('.') for ext in value.split(':')) + if name == 'AddStatus': + return self._validate_custom_statuses(value) return value + def _validate_custom_statuses(self, values): + custom_statuses = [] + for value in values: + custom_statuses.append(self._process_custom_statuses(value)) + return custom_statuses + def _escape_as_data(self, value): return value @@ -273,6 +282,13 @@ def _process_tag_stat_link(self, value): raise DataError("Invalid format for option '--tagstatlink'. " "Expected 'tag:link:title' but got '%s'." % value) + def _process_custom_statuses(self, value): + tokens = value.split(':') + if len(tokens) == 4 and tokens[1] in ['PASS', 'FAIL', 'SKIP']: + return tokens + raise DataError("Invalid format for option '--addstatus'. " + "Expected 'NEWSTATUS:OLDSTATUS:TAGPATTERN:COLOR' but got '%s'." % value) + def _convert_to_positive_integer_or_default(self, name, value): value = self._convert_to_integer(name, value) return value if value > 0 else self._get_default_value(name) @@ -385,6 +401,10 @@ def rpa(self): def rpa(self, value): self['RPA'] = value + @property + def add_status(self): + return self['AddStatus'] + class RobotSettings(_BaseSettings): _extra_cli_opts = {'Extension' : ('extension', ('robot',)), @@ -583,7 +603,8 @@ def log_config(self): 'title': html_escape(self['LogTitle'] or ''), 'reportURL': self._url_from_path(self.log, self.report), 'splitLogBase': os.path.basename(os.path.splitext(self.log)[0]), - 'defaultLevel': self['VisibleLogLevel'] + 'defaultLevel': self['VisibleLogLevel'], + 'customStatusColor': self._resolve_custom_status_colors() } @property @@ -606,6 +627,13 @@ def _resolve_background_colors(self): colors = self['ReportBackground'] return {'pass': colors[0], 'fail': colors[1], 'skip': colors[2]} + def _resolve_custom_status_colors(self): + statuses = self['AddStatus'] + status_colors = dict() + for item in statuses: + status_colors[item[0]] = item[3] + return status_colors + @property def merge(self): return self['Merge'] diff --git a/src/robot/htmldata/rebot/log.html b/src/robot/htmldata/rebot/log.html index 0acc1f44fa0..d374a71bbc9 100644 --- a/src/robot/htmldata/rebot/log.html +++ b/src/robot/htmldata/rebot/log.html @@ -50,6 +50,7 @@

Opening Robot Framework log failed

initLayout(topsuite.name, 'Log'); addStatistics(); addErrors(); + setCustomStatusColors(); addExecutionLog(topsuite); addLogLevelSelector(window.settings['minLevel'], window.settings['defaultLevel']); if (window.location.hash) { @@ -60,6 +61,14 @@

Opening Robot Framework log failed

setTimeout(function () { loadAndExpandElementIds(window.output['expand_keywords']); }, 100); }); +function setCustomStatusColors() { + let statuses = window.settings['customStatusColor'] + let css = $("").appendTo($('body')); + for (let status of Object.keys(statuses)) { + css.append(".label.".concat(status.toLowerCase()).concat("{ background-color:").concat(statuses[status]).concat("}")); + } +} + function addLogLevelSelector(minLevel, defaultLevel) { var controller = LogLevelController(minLevel, defaultLevel); if (controller.showLogLevelSelector()) { diff --git a/src/robot/htmldata/rebot/testdata.js b/src/robot/htmldata/rebot/testdata.js index 1fcfc93d8d9..4eb371571e7 100644 --- a/src/robot/htmldata/rebot/testdata.js +++ b/src/robot/htmldata/rebot/testdata.js @@ -4,7 +4,6 @@ window.testdata = function () { var idCounter = 0; var _statistics = null; var LEVELS = ['TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FAIL', 'SKIP']; - var STATUSES = ['FAIL', 'PASS', 'SKIP', 'NOT RUN']; var KEYWORD_TYPES = ['KEYWORD', 'SETUP', 'TEARDOWN', 'FOR', 'VAR', 'IF', 'ELSE IF', 'ELSE']; var MESSAGE_TYPE = 8; @@ -38,7 +37,7 @@ window.testdata = function () { } function parseStatus(stats) { - return STATUSES[stats[0]]; + return stats[0]; } function childCreator(parent, childType) { diff --git a/src/robot/output/console/highlighting.py b/src/robot/output/console/highlighting.py index 91ab5902544..2890e9181ea 100644 --- a/src/robot/output/console/highlighting.py +++ b/src/robot/output/console/highlighting.py @@ -27,6 +27,7 @@ windll = None from robot.errors import DataError +from robot.result.model import StatusMixin from robot.utils import console_encode, isatty, WINDOWS @@ -98,16 +99,20 @@ def error(self, message, level): @contextmanager def _highlighting(self, status): highlighter = self._highlighter - start = {'PASS': highlighter.green, - 'FAIL': highlighter.red, + start = {StatusMixin.PASS: highlighter.green, + StatusMixin.FAIL: highlighter.red, 'ERROR': highlighter.red, 'WARN': highlighter.yellow, - 'SKIP': highlighter.yellow}[status] + StatusMixin.SKIP: highlighter.yellow}[status] start() try: yield finally: highlighter.reset() + # reset custom statuses + StatusMixin.PASS = 'PASS' + StatusMixin.FAIL = 'FAIL' + StatusMixin.SKIP = 'SKIP' def Highlighter(stream): diff --git a/src/robot/reporting/jsmodelbuilders.py b/src/robot/reporting/jsmodelbuilders.py index a24e43ea613..5ccc1de03e5 100644 --- a/src/robot/reporting/jsmodelbuilders.py +++ b/src/robot/reporting/jsmodelbuilders.py @@ -21,7 +21,6 @@ IF_ELSE_ROOT = BodyItem.IF_ELSE_ROOT -STATUSES = {'FAIL': 0, 'PASS': 1, 'SKIP': 2, 'NOT RUN': 3} KEYWORD_TYPES = {'KEYWORD': 0, 'SETUP': 1, 'TEARDOWN': 2, 'FOR': 3, 'FOR ITERATION': 4, 'IF': 5, 'ELSE IF': 6, 'ELSE': 7} @@ -60,7 +59,7 @@ def __init__(self, context): def _get_status(self, item): # Branch status with IF/ELSE, "normal" status with others. status = getattr(item, 'branch_status', item.status) - model = (STATUSES[status], + model = (status, self._timestamp(item.starttime), item.elapsedtime) msg = getattr(item, 'message', '') diff --git a/src/robot/run.py b/src/robot/run.py index 041e8c1e887..dcae7c59490 100755 --- a/src/robot/run.py +++ b/src/robot/run.py @@ -283,6 +283,13 @@ tag:: flatten matched keywords using same matching rules as with `--removekeywords tag:` + --addstatus for|foritem| * + Allows the possibility to create custom statuses + based on existing statues and tags. + Examples: + --addstatus KNOWN_ISSUE:FAIL:bug-id-*:purple + --addstatus NON-CRITICAL:SKIP:non-critical:pink + New in RF 4.x --listener class * A class for monitoring test execution. Gets notifications e.g. when tests start and end. Arguments to the listener class can be given after diff --git a/src/robot/running/status.py b/src/robot/running/status.py index ec0caca0434..9b3441e107b 100644 --- a/src/robot/running/status.py +++ b/src/robot/running/status.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +from robot.result.model import StatusMixin from robot.errors import ExecutionFailed, PassExecution from robot.model import TagPatterns from robot.utils import html_escape, py3to2, unic, test_or_task @@ -76,6 +77,7 @@ def __init__(self, parent=None, *exit_modes): self.skipped = False self._teardown_allowed = False self._rpa = False + self._custom_statuses = None if parent: parent.children.append(self) @@ -127,11 +129,21 @@ def failed(self): @property def status(self): + if self._custom_statuses and isinstance(self, TestStatus): + for custom_status in self._custom_statuses: + if TagPatterns(custom_status[2]).match(self._test.tags): + if custom_status[1] == 'PASS': + StatusMixin.PASS = custom_status[0] + elif custom_status[1] == 'FAIL': + StatusMixin.FAIL = custom_status[0] + else: + StatusMixin.SKIP = custom_status[0] + break if self.skipped or (self.parent and self.parent.skipped): - return 'SKIP' + return StatusMixin.SKIP if self.failed: - return 'FAIL' - return 'PASS' + return StatusMixin.FAIL + return StatusMixin.PASS def _skip_on_failure(self): return False @@ -172,13 +184,14 @@ def _my_message(self): class TestStatus(_ExecutionStatus): def __init__(self, parent, test, skip_on_failure=None, critical_tags=None, - rpa=False): + rpa=False, custom_statuses=None): _ExecutionStatus.__init__(self, parent) self.exit = parent.exit self._test = test self._skip_on_failure_tags = skip_on_failure self._critical_tags = critical_tags self._rpa = rpa + self._custom_statuses = custom_statuses def test_failed(self, failure): if hasattr(failure, 'skip') and failure.skip: diff --git a/src/robot/running/statusreporter.py b/src/robot/running/statusreporter.py index a10dcd1bda8..6dd151ea926 100644 --- a/src/robot/running/statusreporter.py +++ b/src/robot/running/statusreporter.py @@ -16,6 +16,7 @@ from robot.errors import (ExecutionFailed, ExecutionStatus, DataError, HandlerExecutionFailed, KeywordError, VariableError) from robot.utils import ErrorDetails, get_timestamp +from robot.result.model import StatusMixin from .modelcombiner import ModelCombiner @@ -65,11 +66,11 @@ def __exit__(self, exc_type, exc_val, exc_tb): raise failure def _get_status(self, result): - if result.status == 'SKIP': - return 'SKIP' + if result.status == StatusMixin.SKIP: + return StatusMixin.SKIP if self.test_passed and result.passed: - return 'PASS' - return 'FAIL' + return StatusMixin.PASS + return StatusMixin.FAIL def _get_failure(self, exc_type, exc_value, exc_tb, context): if exc_value is None: diff --git a/src/robot/running/suiterunner.py b/src/robot/running/suiterunner.py index c256cb39f1b..a12492975fb 100644 --- a/src/robot/running/suiterunner.py +++ b/src/robot/running/suiterunner.py @@ -122,7 +122,8 @@ def visit_test(self, test): status = TestStatus(self._suite_status, result, self._settings.skip_on_failure, self._settings.critical_tags, - self._settings.rpa) + self._settings.rpa, + self._settings.add_status) if status.exit: self._add_exit_combine() result.tags.add('robot:exit') diff --git a/utest/reporting/test_jsmodelbuilders.py b/utest/reporting/test_jsmodelbuilders.py index a7cf312fea5..18f7ae1330d 100644 --- a/utest/reporting/test_jsmodelbuilders.py +++ b/utest/reporting/test_jsmodelbuilders.py @@ -35,6 +35,8 @@ def remap(model, strings): return model elif isinstance(model, tuple): return tuple(remap(item, strings) for item in model) + elif isinstance(model, str): + return model else: raise AssertionError("Item '%s' has invalid type '%s'" % (model, type(model))) @@ -73,7 +75,7 @@ def test_test_with_values(self): k1 = self._verify_keyword(test.setup, type=1, kwname='setup') k2 = self._verify_keyword(test.teardown, type=2, kwname='td') self._verify_test(test, 'Name', 'Doc', ('t1', 't2'), - '1 minute', 1, 'Msg', 0, 111, (k1, k2)) + '1 minute', 'PASS', 'Msg', 0, 111, (k1, k2)) def test_name_escaping(self): kw = Keyword('quote:"', 'and *url* https://url.com', '*"Doc"*',) @@ -93,7 +95,7 @@ def test_keyword_with_values(self): self._verify_keyword(kw, 1, 'KW Name', 'libname', 'http://doc', 'arg1, arg2', '${v1}, ${v2}', 'tag1, tag2', - '1 second', 1, 0, 42) + '1 second', 'PASS', 0, 42) def test_default_message(self): self._verify_message(Message()) @@ -137,7 +139,7 @@ def test_nested_structure(self): t = self._verify_test(suite.suites[0].tests[0], tags=('crit', 'xxx')) suite.tests = [TestCase(), TestCase(status='PASS')] S1 = self._verify_suite(suite.suites[0], - status=0, tests=(t,), stats=(1, 0, 1, 0)) + status='FAIL', tests=(t,), stats=(1, 0, 1, 0)) suite.tests[0].body = [Keyword(type=Keyword.FOR), Keyword()] suite.tests[0].body[0].body = [Keyword(type=Keyword.FOR_ITERATION), Message()] k = self._verify_keyword(suite.tests[0].body[0].body[0], type=4) @@ -148,8 +150,8 @@ def test_nested_structure(self): m2 = self._verify_message(suite.tests[0].body[1].messages[1], 'msg', level=0) k2 = self._verify_keyword(suite.tests[0].body[1], body=(m1, m2)) T1 = self._verify_test(suite.tests[0], body=(k1, k2)) - T2 = self._verify_test(suite.tests[1], status=1) - self._verify_suite(suite, status=0, keywords=(K1, K2), suites=(S1,), + T2 = self._verify_test(suite.tests[1], status='PASS') + self._verify_suite(suite, status='FAIL', keywords=(K1, K2), suites=(S1,), tests=(T1, T2), stats=(3, 1, 2, 0)) self._verify_min_message_level('TRACE') @@ -175,14 +177,14 @@ def test_if(self): test.body[0].body.create_branch(BodyItem.ELSE, status='NOT RUN') test.body[0].body[-1].body.create_keyword('z') exp_if = ( - 5, '$x > 0', '', '', '', '', '', '', (3, None, 0), () + 5, '$x > 0', '', '', '', '', '', '', ('NOT RUN', None, 0), () ) exp_else_if = ( - 6, '$x < 0', '', '', '', '', '', '', (1, None, 0), () + 6, '$x < 0', '', '', '', '', '', '', ('PASS', None, 0), () ) exp_else = ( - 7, '', '', '', '', '', '', '', (3, None, 0), - ((0, 'z', '', '', '', '', '', '', (0, None, 0), ()),) + 7, '', '', '', '', '', '', '', ('NOT RUN', None, 0), + ((0, 'z', '', '', '', '', '', '', ('FAIL', None, 0), ()),) ) self._verify_test(test, body=(exp_if, exp_else_if, exp_else)) @@ -192,16 +194,16 @@ def test_message_directly_under_test(self): test.body.create_keyword().body.create_message('Hi from keyword') test.body.create_message('Hi from test again', 'WARN') exp_m1 = (8, None, 2, 'Hi from test') - exp_kw = (0, '', '', '', '', '', '', '', (0, None, 0), + exp_kw = (0, '', '', '', '', '', '', '', ('FAIL', None, 0), ((8, None, 2, 'Hi from keyword'),)) exp_m3 = (8, None, 3, 'Hi from test again') self._verify_test(test, body=(exp_m1, exp_kw, exp_m3)) - def _verify_status(self, model, status=0, start=None, elapsed=0): + def _verify_status(self, model, status='FAIL', start=None, elapsed=0): assert_equal(model, (status, start, elapsed)) def _verify_suite(self, suite, name='', doc='', metadata=(), source='', - relsource='', status=2, message='', start=None, elapsed=0, + relsource='', status='SKIP', message='', start=None, elapsed=0, suites=(), tests=(), keywords=(), stats=(0, 0, 0, 0)): status = (status, start, elapsed, message) \ if message else (status, start, elapsed) @@ -214,7 +216,7 @@ def _get_status(self, *elements): return elements if elements[-1] else elements[:-1] def _verify_test(self, test, name='', doc='', tags=(), timeout='', - status=0, message='', start=None, elapsed=0, body=()): + status='FAIL', message='', start=None, elapsed=0, body=()): status = (status, start, elapsed, message) \ if message else (status, start, elapsed) doc = '

%s

' % doc if doc else '' @@ -222,7 +224,7 @@ def _verify_test(self, test, name='', doc='', tags=(), timeout='', doc, tags, status, body) def _verify_keyword(self, keyword, type=0, kwname='', libname='', doc='', - args='', assign='', tags='', timeout='', status=0, + args='', assign='', tags='', timeout='', status='FAIL', start=None, elapsed=0, body=()): status = (status, start, elapsed) doc = '

%s

' % doc if doc else ''