3 new revisions:

Revision: 97729dbc11e8
Branch:   default
Author:   Robot Framework Developers (robotframew...@gmail.com)
Date:     Wed Jan 29 11:24:27 2014 UTC
Log:      ItemList: added __setitem__
http://code.google.com/p/robotframework/source/detail?r=97729dbc11e8

Revision: 94832c7c8fb6
Branch:   default
Author:   Robot Framework Developers (robotframew...@gmail.com)
Date:     Wed Jan 29 15:30:44 2014 UTC
Log:      --rerunmerge option to Rebot...
http://code.google.com/p/robotframework/source/detail?r=94832c7c8fb6

Revision: db8dbe61aa26
Branch:   default
Author:   Robot Framework Developers (robotframew...@gmail.com)
Date:     Wed Jan 29 15:30:52 2014 UTC
Log:      Automated merge with https://robotframework.googlecode.com/hg/
http://code.google.com/p/robotframework/source/detail?r=db8dbe61aa26

==============================================================================
Revision: 97729dbc11e8
Branch:   default
Author:   Robot Framework Developers (robotframew...@gmail.com)
Date:     Wed Jan 29 11:24:27 2014 UTC
Log:      ItemList: added __setitem__
http://code.google.com/p/robotframework/source/detail?r=97729dbc11e8

Modified:
 /src/robot/model/itemlist.py
 /utest/model/test_itemlist.py

=======================================
--- /src/robot/model/itemlist.py        Thu Jan 23 14:00:53 2014 UTC
+++ /src/robot/model/itemlist.py        Wed Jan 29 11:24:27 2014 UTC
@@ -67,6 +67,15 @@
                             % type(self).__name__)
         return self._items[index]

+    def __setitem__(self, index, item):
+        if isinstance(index, slice):
+            raise TypeError("'%s' objects do not support slicing."
+                            % type(self).__name__)
+        self._check_type_and_set_attrs(item)
+        items = list(self._items)
+        items[index] = item
+        self._items = tuple(items)
+
     def __len__(self):
         return len(self._items)

=======================================
--- /utest/model/test_itemlist.py       Tue Aug 27 19:34:18 2013 UTC
+++ /utest/model/test_itemlist.py       Wed Jan 29 11:24:27 2014 UTC
@@ -66,6 +66,20 @@
         assert_equal(items.index('first'), 0)
         assert_equal(items.index('second'), 1)

+    def test_setitem(self):
+        orig1, orig2 = Object(), Object()
+        new1, new2 = Object(), Object()
+        items = ItemList(Object, {'attr': 2}, [orig1, orig2])
+        items[0] = new1
+        assert_equal(list(items), [new1, orig2])
+        assert_equal(new1.attr, 2)
+        items[-1] = new2
+        assert_equal(list(items), [new1, new2])
+        assert_equal(new2.attr, 2)
+
+    def test_setitem_slice_is_not_supported(self):
+        assert_raises(TypeError, ItemList(int).__setitem__, slice(0))
+
     def test_len(self):
         items = ItemList(object)
         assert_equal(len(items), 0)

==============================================================================
Revision: 94832c7c8fb6
Branch:   default
Author:   Robot Framework Developers (robotframew...@gmail.com)
Date:     Wed Jan 29 15:30:44 2014 UTC
Log:      --rerunmerge option to Rebot

Update issue 1615
Status: Started
Owner: pekka.klarck
Implementation and tests done. Could still add some tests for handling other
options with --ReRunMerge, especially options that are passed to underlying
ExecutionResultBuilder.

Documentation needed:
1) --help text (TODO added)
2) doc string update for ExecutionResult (TODO added)
3) User Guide
http://code.google.com/p/robotframework/source/detail?r=94832c7c8fb6

Added:
 /atest/robot/rebot/rerun_merge.txt
 /src/robot/result/rerunmerger.py
Modified:
 /atest/resources/TestCheckerLibrary.py
 /src/robot/conf/settings.py
 /src/robot/rebot.py
 /src/robot/reporting/resultwriter.py
 /src/robot/result/resultbuilder.py

=======================================
--- /dev/null
+++ /atest/robot/rebot/rerun_merge.txt  Wed Jan 29 15:30:44 2014 UTC
@@ -0,0 +1,131 @@
+*** Settings ***
+Force Tags        regression    pybot    jybot
+Suite Setup       Run original tests
+Suite Teardown    Remove Files    ${ORIGINAL}    ${RERUN}    ${RERUN 2}
+Resource          rebot_resource.txt
+
+*** Variables ***
+${TEST CASES}     ${DATADIR}/misc/suites
+${ORIGINAL}       %{TEMPDIR}/merge-original.xml
+${RERUN}          %{TEMPDIR}/merge-rerun.xml
+${RERUN 2}        %{TEMPDIR}/merge-rerun-2.xml
+@{ALL TESTS} Suite4 First SubSuite1 First SubSuite2 First +... Test From Sub Suite 4 SubSuite3 First SubSuite3 Second +... Suite1 First Suite1 Second Third In Suite1
+...               Suite2 First             Suite3 First
+@{ALL SUITES}     Fourth                   Subsuites          Subsuites2
+...               Tsuite1                  Tsuite2            Tsuite3
+@{SUB SUITES 1}   Sub1                     Sub2
+@{SUB SUITES 2}   Sub.suite.4              Subsuite3
+@{RERUN TESTS}    Suite4 First             SubSuite1 First
+@{RERUN SUITES}   Fourth                   Subsuites
+
+*** Test Cases ***
+Successful merge
+    Rerun tests
+    Run merge
+    Merge should have been successful
+
+Successful multi-merge
+    Rerun tests
+    Rerun tests again
+    Run multi-merge
+    ${message} =    Create expected multi-merge message
+ Merge should have been successful status 2=FAIL message 2=${message}
+
+Non-matching root suite
+    Create output with incompatible root suite
+    Run merge
+    Stderr Should Be Equal To
+ ... [ ERROR ] Merged suite 'Incompatible' is ignored because it is not found from original result.\n
+    Verify original tests
+
+Non-matching child suite
+    Create output with incompatible child suite
+    Run merge
+    Stderr Should Be Equal To    SEPARATOR=
+ ... [ ERROR ] Merged suite 'Suites.Sub1' is ignored because it is not found from original result.\n + ... [ ERROR ] Merged suite 'Suites.Sub2' is ignored because it is not found from original result.\n
+    Verify original tests
+
+Non-matching test
+    Create output with incompatible test
+    Run merge
+    Stderr Should Be Equal To
+ ... [ ERROR ] Merged test 'Suites.Fourth.Non-existing' is ignored because it is not found from original result.\n
+    Merge should have been successful    message 1=Expected
+
+*** Keywords **
+Run original tests
+ Create Output With Robot ${ORIGINAL} --variable FAIL:YES ${TEST CASES}
+    Verify original tests
+
+Verify original tests
+    Should Be Equal    ${SUITE.name}    Suites
+    Should Contain Suites    ${SUITE}    @{ALL SUITES}
+    Should Contain Suites    ${SUITE.suites[1]}    @{SUB SUITES 1}
+    Should Contain Suites    ${SUITE.suites[2]}    @{SUB SUITES 2}
+    Check Suite Contains Tests    ${SUITE}    @{ALL TESTS}
+    ...    SubSuite1 First=FAIL:This test was doomed to fail: YES != NO
+
+Rerun tests
+ Create Output With Robot ${RERUN} --runfailed ${ORIGINAL} ${TEST CASES}
+    Should Be Equal    ${SUITE.name}    Suites
+    Should Contain Suites    ${SUITE}    @{RERUN SUITES}
+    Should Contain Suites    ${SUITE.suites[1]}    @{SUB SUITES 1}[0]
+    Check Suite Contains Tests    ${SUITE}    @{RERUN TESTS}
+
+Rerun tests again
+ Create Output With Robot ${RERUN 2} --test SubSuite1First --variable FAIL:again ${TEST CASES}
+
+Create output with incompatible root suite
+ Create Output With Robot ${RERUN} --name Incompatible --test SubSuite1First ${TEST CASES}
+
+Create output with incompatible child suite
+ Create Output With Robot ${RERUN} --name Suites ${TEST CASES}/subsuites
+
+Create output with incompatible test
+    Rerun tests
+    ${xml} =    Parse XML    ${RERUN}
+    Log Element    ${xml}
+ Set Element Attribute ${xml} name Non-existing xpath=suite/suite/test
+    Save XML    ${xml}    ${RERUN}
+
+Run merge
+    Run Rebot    --rerunmerge    ${ORIGINAL}    ${RERUN}
+
+Run multi-merge
+    Run Rebot    -R    ${ORIGINAL}    ${RERUN}    ${RERUN 2}
+
+Merge should have been successful
+ [Arguments] ${status 1}=FAIL ${message 1}= ${status 2}=PASS ${message 2}=
+    Should Be Equal    ${SUITE.name}    Suites
+    Should Contain Suites    ${SUITE}    @{ALL SUITES}
+    Should Contain Suites    ${SUITE.suites[1]}    @{SUB SUITES 1}
+    Should Contain Suites    ${SUITE.suites[2]}    @{SUB SUITES 2}
+    ${message 1} =    Create expected merge message    ${message 1}
+    ...    FAIL    Expected    FAIL    Expected
+    ${message 2} =    Create expected merge message    ${message 2}
+ ... PASS ${EMPTY} FAIL This test was doomed to fail: YES != NO
+    Check Suite Contains Tests    ${SUITE}    @{ALL TESTS}
+    ...    Suite4 First=${status 1}:${message 1}
+    ...    SubSuite1 First=${status 2}:${message 2}
+
+Create expected merge message
+ [Arguments] ${message} ${new status} ${new message} ${old status} ${old message}
+    Return From Keyword If    """${message}"""    ${message}
+    Run Keyword And Return    Catenate    SEPARATOR=\n
+    ...    Test has been re-run and results replaced.
+    ...    - \ - \ -
+    ...    New status: \ ${new status}
+    ...    New message: \ ${new message}
+    ...    - \ - \ -
+    ...    Old status: \ ${old status}
+    ...    Old message: \ ${old message}
+
+Create expected multi-merge message
+    ${message} =    Create expected merge message    ${EMPTY}
+ ... PASS ${EMPTY} FAIL This test was doomed to fail: YES != NO
+    ${message} =    Create expected merge message    ${EMPTY}
+ ... FAIL This test was doomed to fail: again != NO PASS ${message}
+    [Return]    ${message}
=======================================
--- /dev/null
+++ /src/robot/result/rerunmerger.py    Wed Jan 29 15:30:44 2014 UTC
@@ -0,0 +1,74 @@
+#  Copyright 2008-2014 Nokia Solutions and Networks
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+from robot.model import SuiteVisitor
+
+
+class ReRunMerger(SuiteVisitor):
+
+    def __init__(self, result):
+        self.root = result.suite
+        self.current = None
+
+    def merge(self, merged):
+        merged.suite.visit(self)
+
+    def start_suite(self, suite):
+        try:
+            if not self.current:
+                self.current = self._find_root(suite)
+            else:
+                self.current = self._find(self.current.suites, suite.name)
+        except ValueError:
+            self._report_ignored(suite)
+            return False
+
+    def _find_root(self, suite):
+        if self.root.name != suite.name:
+            raise ValueError
+        return self.root
+
+    def _find(self, items, name):
+        for item in items:
+            if item.name == name:
+                return item
+        raise ValueError
+
+    def _report_ignored(self, item, test=False):
+        from robot.output import LOGGER
+        type = 'suite' if not test else 'test'
+ LOGGER.error("Merged %s '%s' is ignored because it is not found from "
+                     "original result." % (type, item.longname))
+
+    def end_suite(self, suite):
+        self.current = self.current.parent
+
+    def visit_test(self, test):
+        try:
+            old = self._find(self.current.tests, test.name)
+        except ValueError:
+            self._report_ignored(test, test=True)
+        else:
+            test.message = self._create_merge_message(test, old)
+            index = self.current.tests.index(old)
+            self.current.tests[index] = test
+
+    def _create_merge_message(self, new, old):
+        return '\n'.join(['Test has been re-run and results replaced.',
+                          '-  -  -',
+                          'New status:  %s' % new.status,
+                          'New message:  %s' % new.message,
+                          '-  -  -',
+                          'Old status:  %s' % old.status,
+                          'Old message:  %s' % old.message])
=======================================
--- /atest/resources/TestCheckerLibrary.py      Wed Jun  5 20:01:38 2013 UTC
+++ /atest/resources/TestCheckerLibrary.py      Wed Jan 29 15:30:44 2014 UTC
@@ -106,19 +106,26 @@
                              "Expected:\n%s\n\nActual:\n%s\n"
                              % (test.exp_message, test.message))

-    def check_suite_contains_tests(self, suite, *expected_names):
+ def check_suite_contains_tests(self, suite, *expected_names, **statuses):
         actual_tests = [test for test in self.get_tests_from_suite(suite)]
-        tests_msg  = """
+        tests_msg = """
 Expected tests : %s
-Actual tests   : %s"""  % (str(list(expected_names)), str(actual_tests))
+Actual tests   : %s""" % (str(list(expected_names)), str(actual_tests))
         expected_names = [utils.normalize(name) for name in expected_names]
+ statuses = dict((utils.normalize(k), v) for k, v in statuses.items())
         if len(actual_tests) != len(expected_names):
             raise AssertionError("Wrong number of tests." + tests_msg)
         for test in actual_tests:
+            norm_name = utils.normalize(test.name)
             if utils.MultiMatcher(expected_names).match(test.name):
                 print "Verifying test '%s'" % test.name
-                self.check_test_status(test)
-                expected_names.remove(utils.normalize(test.name))
+                status = statuses.get(norm_name)
+                if status and ':' in status:
+                    status, message = status.split(':', 1)
+                else:
+                    message = None
+                self.check_test_status(test, status, message)
+                expected_names.remove(norm_name)
             else:
raise AssertionError("Test '%s' was not expected to be run.%s"
                                      % (test.name, tests_msg))
=======================================
--- /src/robot/conf/settings.py Wed Jan 29 10:52:58 2014 UTC
+++ /src/robot/conf/settings.py Wed Jan 29 15:30:44 2014 UTC
@@ -458,7 +458,8 @@
                        'LogLevel'          : ('loglevel', 'TRACE'),
                        'ProcessEmptySuite' : ('processemptysuite', False),
                        'StartTime'         : ('starttime', None),
-                       'EndTime'           : ('endtime', None)}
+                       'EndTime'           : ('endtime', None),
+                       'ReRunMerge'        : ('rerunmerge', False)}

     def _output_disabled(self):
         return False
@@ -512,6 +513,10 @@
     def _resolve_background_colors(self):
         colors = self['ReportBackground']
return {'pass': colors[0], 'nonCriticalFail': colors[1], 'fail': colors[2]}
+
+    @property
+    def rerun_merge(self):
+        return self['ReRunMerge']

     @property
     def console_logger_config(self):
=======================================
--- /src/robot/rebot.py Sat Jan 25 23:51:09 2014 UTC
+++ /src/robot/rebot.py Wed Jan 29 15:30:44 2014 UTC
@@ -93,6 +93,7 @@
                           tests are not selected even if included with
--include. Tags are matched using the rules explained
                           with --include.
+ -R --rerunmerge          *** TODO ***
--processemptysuite Processes output also if the top level test suite is empty. Useful e.g. with --include/--exclude when it is not an error that no test matches the condition.
=======================================
--- /src/robot/reporting/resultwriter.py        Thu Jan 23 14:00:53 2014 UTC
+++ /src/robot/reporting/resultwriter.py        Wed Jan 29 15:30:44 2014 UTC
@@ -114,8 +114,10 @@
         if self._result is None:
include_keywords = bool(self._settings.log or self._settings.output)
             flattened = self._settings.flatten_keywords
+            rerun_merge = self._settings.rerun_merge
self._result = ExecutionResult(include_keywords=include_keywords,
                                            flattened_keywords=flattened,
+                                           rerun_merge=rerun_merge,
                                            *self._sources)
             self._result.configure(self._settings.status_rc,
                                    self._settings.suite_config,
=======================================
--- /src/robot/result/resultbuilder.py  Thu Jan 23 14:00:53 2014 UTC
+++ /src/robot/result/resultbuilder.py  Wed Jan 29 15:30:44 2014 UTC
@@ -19,6 +19,7 @@

 from .executionresult import Result, CombinedResult
 from .flattenkeywordmatcher import FlattenKeywordMatcher
+from .rerunmerger import ReRunMerger
 from .xmlelementhandlers import XmlElementHandler


@@ -28,18 +29,30 @@
     :param sources: Path(s) to output XML file(s).
     :param options: Configuration options passed to
:py:class:`~ExecutionResultBuilder` as keyword arguments.
+                    ***  TODO ***
     :returns: :class:`~.executionresult.Result` instance.

     See :mod:`~robot.result` package for a usage example.
     """
     if not sources:
         raise DataError('One or more data source needed.')
+    if options.pop('rerun_merge', False):
+        return _rerun_merge_results(sources[0], sources[1:], options)
     if len(sources) > 1:
-        return _combined_result(sources, options)
+        return _combine_results(sources, options)
     return _single_result(sources[0], options)


-def _combined_result(sources, options):
+def _rerun_merge_results(original, merged, options):
+    result = ExecutionResult(original, **options)
+    merger = ReRunMerger(result)
+    for path in merged:
+        merged = ExecutionResult(path, **options)
+        merger.merge(merged)
+    return result
+
+
+def _combine_results(sources, options):
return CombinedResult(ExecutionResult(src, **options) for src in sources)



==============================================================================
Revision: db8dbe61aa26
Branch:   default
Author:   Robot Framework Developers (robotframew...@gmail.com)
Date:     Wed Jan 29 15:30:52 2014 UTC
Log:      Automated merge with https://robotframework.googlecode.com/hg/
http://code.google.com/p/robotframework/source/detail?r=db8dbe61aa26


--

--- You received this message because you are subscribed to the Google Groups "robotframework-commit" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to robotframework-commit+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to