Revision: 4731f2d43ba0
Author:   Mikko Korpela <[email protected]>
Date:     Wed Nov 16 12:04:48 2011
Log:      stash
http://code.google.com/p/robotframework/source/detail?r=4731f2d43ba0

Modified:
 /src/robot/result/datamodel.py
 /src/robot/result/jsondatamodelhandlers.py
 /utest/result/test_jsoning.py
 /utest/result/test_resultserializer.py

=======================================
--- /src/robot/result/datamodel.py      Wed Nov 16 03:27:58 2011
+++ /src/robot/result/datamodel.py      Wed Nov 16 12:04:48 2011
@@ -21,49 +21,63 @@

     def __init__(self, result, log_path='NONE', split_log=False):
         self._context = Context(log_path=log_path, split_log=split_log)
-        self._elements = [ExecutionResultHandler(self._context, result)]
+        self._handlers = [ExecutionResultHandler(self._context, result)]
+        self._datamodel = None

     @property
     def datamodel(self):
-        #TODO: End element should not require argument in this case
-        return self._top.end_element(None)
+        if self._datamodel is None:
+            self._datamodel = self._build()
+        return self._datamodel
+
+    @property
+    def split_results(self):
+        return self._context.split_results

     @property
     def _top(self):
-        return self._elements[-1]
-
-    def _push(self, element):
-        self._elements.append(element)
-
-    def _pop(self):
-        return self._elements.pop()
-
-    @property
-    def split_results(self):
-        return self._context.split_results
+        return self._handlers[-1]
+
+    def _push(self, handler):
+        self._handlers.append(handler)
+
+    def _build(self, item=None):
+        return self._handlers.pop().build(item)

     def start_suite(self, suite):
-        self._push(self._top.start_suite(suite))
-
-    def start_keyword(self, keyword):
-        self._push(self._top.start_keyword(keyword))
+        self._push(self._top.suite_handler())
+
+    def end_suite(self, suite):
+        model = self._build(suite)
+        self._top.add_suite(model)

     def start_test(self, test):
-        self._push(self._top.start_test(test))
-
-    def start_errors(self, errors):
-        self._push(self._top.start_errors(errors))
-
-    def visit_statistics(self, stats):
-        self._push(self._top.visit_statistics(stats))
-        self._end(stats)
-
-    #TODO: end_elements should also work in similar as starts
-    def _end(self, item):
-        submodel = self._pop().end_element(item)
-        self._top.add_child_data(submodel)
-
-    end_suite = end_keyword = end_test = end_errors = _end
+        self._push(self._top.test_handler())
+
+    def end_test(self, test):
+        model = self._build(test)
+        self._top.add_test(model)
+
+    def start_keyword(self, kw):
+        self._push(self._top.keyword_handler())
+
+    def end_keyword(self, kw):
+        model = self._build(kw)
+        self._top.add_keyword(model)
+
+    def start_message(self, msg):
+        self._push(self._top.message_handler())

     def end_message(self, msg):
-        self._top.message(msg)
+        model = self._build(msg)
+        self._top.add_message(model)
+
+    def start_errors(self, errors):
+        self._push(self._top.errors_handler())
+
+    def end_errors(self, errors):
+        model = self._build(errors)
+        self._top.add_errors(model)
+
+    def visit_statistics(self, stats):
+        self._top.visit_statistics(stats)
=======================================
--- /src/robot/result/jsondatamodelhandlers.py  Wed Nov 16 02:03:43 2011
+++ /src/robot/result/jsondatamodelhandlers.py  Wed Nov 16 12:04:48 2011
@@ -21,49 +21,60 @@

     def __init__(self, context):
         self._context = context
-        self._current_children = None
         self._suites = []
-        self._keywords = []
         self._tests = []
-        self._stats = []
-        self._data_from_children = []
-
-    def add_child_data(self, data):
-        self._data_from_children.append(data)
-
-    def start_suite(self, suite):
-        self._current_children = self._suites
-        return SuiteHandler(self._context, suite)
-
-    def start_keyword(self, keyword):
-        self._current_children = self._keywords
-        return KeywordHandler(self._context, keyword)
-
-    def start_test(self, test):
-        self._current_children = self._tests
-        return TestHandler(self._context, test)
-
-    def start_errors(self, _):
-        return _Handler(self._context)
-
-    def message(self, message):
- self._data_from_children.append(_MsgHandler(self._context, message).end_element(message.message))
+        self._keywords = []
+        self._messages = []
+        self._errors = []
+
+    def build(self, item):
+        return None
+
+    def suite_handler(self):
+        return SuiteHandler(self._context)
+
+    def test_handler(self):
+        return TestHandler(self._context)
+
+    def keyword_handler(self):
+        return KeywordHandler(self._context)
+
+    def message_handler(self):
+        return MessageHandler(self._context)
+
+    def errors_handler(self):
+        return ErrorsHandler(self._context)
+
+    def add_suite(self, data):
+        self._suites.append(data)
+
+    def add_test(self, data):
+        self._tests.append(data)
+
+    def add_keyword(self, data):
+        self._keywords.append(data)
+
+    def add_message(self, data):
+        self._messages.append(data)
+
+    def add_errors(self, data):
+        self._errors = data
+
+    def _status(self, item):
+        return StatusHandler(self._context).build(item)

     def end_element(self, text):
         return self._data_from_children

-    def _get_id(self, item):
+    def _id(self, item):
         return self._context.get_id(item)

+    def _timestamp(self, time_string):
+        return self._context.timestamp(time_string)
+
     def _get_ids(self, *items):
         return [self._get_id(i) for i in items]

-    def _last_child_passed(self):
-        return self._last_child_status() == 1
-
-    def _last_child_status(self):
-        return self._data_from_children[-1][0]
-

 class ExecutionResultHandler(_Handler):

@@ -72,16 +83,22 @@
         self._generator = execution_result.generator

     def visit_statistics(self, stats):
-        self._current_children = self._stats
+        self._stats = []
         return StatisticsHandler(self._stats, stats)

-    def end_element(self, _):
+    def build(self, _):
         return {'generator': self._generator,
-                'suite': self._data_from_children[0],
+                'suite': self._suites[0],
                 'stats': self._stats,
-                'errors': self._data_from_children[2],
+                'errors': self._errors,
                 'baseMillis': self._context.basemillis,
                 'strings': self._context.dump_texts()}
+
+
+class ErrorsHandler(_Handler):
+
+    def build(self, errors):
+        return self._messages


 class SuiteStatVisitor(ResultVisitor):
@@ -131,147 +148,124 @@

 class SuiteHandler(_Handler):

-    def __init__(self, context, suite):
+    def __init__(self, context):
         _Handler.__init__(self, context)
-        self._current_children = None
         self._context.start_suite()
- self._data_from_children.append(self._get_id(utils.html_format(suite.doc)))
-        self._metadata = []
-        for i in [self._get_ids(key, utils.html_format(value))
-                  for key, value in suite.metadata.items()]:
-            self._metadata.extend(i)
-        self._data_from_children.append(self._metadata)
-
-    def _get_name_and_sources(self, suite):
-        return self._get_ids(suite.name, suite.source,
-                             self._context.get_rel_log_path(suite.source))
-
-    def add_child_data(self, data):
-        self._current_children.append(data)
-
-    def start_keyword(self, keyword):
-        self._current_children = self._keywords
-        return SuiteSetupAndTeardownHandler(self._context, keyword)
-
-    def end_element(self, suite):
-        stats = self._context.end_suite()
-        status = _StatusHandler(self._context, suite).end_element('')
-        if suite.message != '':
-            status.append(self._get_id(suite.message))
-        self._data_from_children.append(status)
-        # TODO: 0 is Teardown failure. It should be removed from JS
- return self._get_name_and_sources(suite) + self._data_from_children + \
-                 [self._suites, self._tests, self._keywords, 0, stats]
+
+    def keyword_handler(self):
+        return SuiteKeywordHandler(self._context)
+
+    def build(self, suite):
+        stats = self._context.end_suite()
+        return [self._id(suite.name),
+                self._id(suite.source),
+                self._id(self._context.get_rel_log_path(suite.source)),
+                self._id(utils.html_format(suite.doc)),
+                self._metadata(suite),
+                self._status(suite),
+                self._suites,
+                self._tests,
+                self._keywords,
+ 0, # TODO: 0 is Teardown failure. It should be removed from JS
+                stats]
+
+
+    def _metadata(self, suite):
+        metadata = []
+        for i in [[self._id(key),
+                   self._id(utils.html_format(value))]
+        for key, value in suite.metadata.items()]:
+            metadata.extend(i)
+        return metadata


 class TestHandler(_Handler):

-    def __init__(self, context, test):
+    def __init__(self, context):
         _Handler.__init__(self, context)
-        self._current_children = None
         self._context.start_test()
- self._data_from_children.append(self._get_id(utils.html_format(test.doc)))
-        self._status = _StatusHandler(self._context, test).end_element('')
-        if test.message != '':
-            self._status.append(self._get_id(test.message))
-
-    def add_child_data(self, data):
-        self._current_children.append(data)
-
-    def end_element(self, test):
+
+    def build(self, test):
         critical = int(test.critical == 'yes')
- self._data_from_children.append([self._get_id(tag) for tag in test.tags])
-        self._data_from_children.append(self._status)
-        self._context.add_test(critical, self._last_child_passed())
-        kws = self._context.end_test(self._keywords)
-        return self._get_ids(test.name, test.timeout, critical) + \
-                self._data_from_children + [kws]
+        self._context.add_test(critical, test.status == 'PASS')
+        self._keywords = self._context.end_test(self._keywords)
+        return [self._id(test.name),
+                self._id(test.timeout),
+                critical,
+                self._id(utils.html_format(test.doc)),
+                [self._id(tag) for tag in test.tags],
+                self._status(test),
+                self._keywords]


 class KeywordHandler(_Handler):
     _types = {'kw': 0, 'setup': 1, 'teardown': 2, 'for': 3, 'foritem': 4}

-    def __init__(self, context, keyword):
+    def __init__(self, context):
         _Handler.__init__(self, context)
-        self._keywords = []
-        self._messages = []
-        self._current_children = None
-        self._start()
- self._data_from_children.append(self._get_id(utils.html_format(keyword.doc)))
-        self._args = self._get_id(', '.join(keyword.args))
-        self._data_from_children.append(self._args)
- self._status = _StatusHandler(self._context, keyword).end_element('')
-
-    def _start(self):
-        self._context.start_keyword()
-
-    def add_child_data(self, data):
-        self._current_children.append(data)
-
-    def message(self, message):
- self._messages.append(_MsgHandler(self._context, message).end_element(message.message))
-
-    def end_element(self, keyword):
-        self._data_from_children.append(self._status)
-        return self._get_ids(self._types[keyword.type],
-                             keyword.name,
-                             keyword.timeout) + \
- self._data_from_children + [self._get_keywords(), self._messages]
-
-    def _get_keywords(self):
+        context.start_keyword()
+
+    def build(self, keyword):
         self._context.end_keyword()
-        return self._keywords
+        return [self._types[keyword.type],
+                self._id(keyword.name),
+                self._id(keyword.timeout),
+                self._id(utils.html_format(keyword.doc)),
+                self._id(', '.join(keyword.args)),
+                self._status(keyword),
+                self._keywords,
+                self._messages]


-class SuiteSetupAndTeardownHandler(KeywordHandler):
-
-    def _start(self):
+class SuiteKeywordHandler(_Handler):
+
+    def __init__(self, context):
+        _Handler.__init__(self, context)
         self._context.start_suite_setup_or_teardown()

-    def _get_keywords(self):
+    def build(self, keyword):
         self._context.end_suite_setup_or_teardown(self._keywords)
-        return self._keywords
+        return [KeywordHandler._types[keyword.type],
+                self._id(keyword.name),
+                self._id(keyword.timeout),
+                self._id(utils.html_format(keyword.doc)),
+                self._id(', '.join(keyword.args)),
+                self._status(keyword),
+                self._keywords,
+                self._messages]


-class _StatusHandler(_Handler):
+class StatusHandler(_Handler):
     _statuses = {'FAIL': 0, 'PASS': 1, 'NOT_RUN': 2}

-    def __init__(self, context, item):
-        self._context = context
-        self._status = self._statuses[item.status]
-        self._starttime = self._context.timestamp(item.starttime)
-        self._elapsed = self._calculate_elapsed(item)
-
-    def _calculate_elapsed(self, item):
-        endtime = self._context.timestamp(item.endtime)
-        # Must compare against None because either start and end may be 0.
-        if self._starttime is not None or endtime is not None:
-            return endtime - self._starttime
-        # Only RF 2.6+ outputs have elapsedtime when start or end is N/A.
-        return int(item.elapsedtime)
-
-    def end_element(self, text):
-        result = [self._status, self._starttime, self._elapsed]
-        if text:
-            result.append(text)
-        return self._get_ids(*result)
-
-
-class _MsgHandler(_Handler):
-
-    def __init__(self, context, message):
-        _Handler.__init__(self, context)
-        self._msg = [self._context.timestamp(message.timestamp),
-                     LEVELS[message.level]]
-        self._message = message
-
-    def end_element(self, text):
- self._msg.append(text if self._message.html else utils.html_escape(text))
-        self._handle_warning_linking()
-        return self._get_ids(*self._msg)
-
-    def _handle_warning_linking(self):
-        if self._message.linkable:
-            self._msg.append(self._context.link_to(self._msg))
-        elif self._message.level == 'WARN':
-            self._context.create_link_to_current_location(self._msg)
+    def build(self, item):
+        model = [self._statuses[item.status],
+                 self._timestamp(item.starttime),
+                 int(item.elapsedtime)]
+        msg = getattr(item, 'message', '')
+        if msg:
+            model.append(self._id(msg))
+        return model
+
+
+class MessageHandler(_Handler):
+
+    def build(self, message):
+        msg = [self._timestamp(message.timestamp),
+               LEVELS[message.level],
+               self._format_message_text(message)]
+        self._handle_warning_linking(msg, message)
+        # FIXME: WTF? linking doesn't work without this late _id thing in
+        # test_reporting . test_split_tests
+        msg[2] = self._id(msg[2])
+        return msg
+
+    def _format_message_text(self, message):
+        return message.message if message.html else \
+                    utils.html_escape(message.message)
+
+    def _handle_warning_linking(self, msg, message):
+        if message.linkable:
+            msg.append(self._id(self._context.link_to(msg)))
+        elif message.level == 'WARN':
+            self._context.create_link_to_current_location(msg)
=======================================
--- /utest/result/test_jsoning.py       Wed Nov 16 02:04:47 2011
+++ /utest/result/test_jsoning.py       Wed Nov 16 12:04:48 2011
@@ -6,18 +6,34 @@
 from robot.output.loggerhelper import LEVELS
 from robot.reporting.parsingcontext import Context
 from robot.result.datamodel import JSModelCreator
-from robot.result.jsondatamodelhandlers import _Handler, KeywordHandler, _StatusHandler +from robot.result.jsondatamodelhandlers import _Handler, KeywordHandler, StatusHandler
 from robot.result.testcase import TestCase
 from robot.result.testsuite import TestSuite
 from robot.utils.asserts import assert_equals


+class Handler(_Handler):
+
+    def __init__(self, context):
+        _Handler.__init__(self, context)
+        self._all = []
+
+    def _add(self, data):
+        self._all.append(data)
+
+    add_keyword = add_test = add_suite = add_errors = add_message = _add
+
+    def build(self, item):
+        return self._all
+
+
 class _PartialJSModelCreator(JSModelCreator):

     def __init__(self):
-        self._elements = []
+        self._datamodel = None
+        self._handlers = []
         self._context = Context()
-        self._elements.append(_Handler(self._context))
+        self._handlers.append(Handler(self._context))


 class TestJsoning(unittest.TestCase):
@@ -87,7 +103,7 @@
                                           2:keyword.timeout,
                                           4: ', '.join(keyword.args)})
         self._assert_html_text(keyword_json[3], keyword.doc)
- assert_equals(keyword_json[-3][0], _StatusHandler._statuses[keyword.status]) + assert_equals(keyword_json[-3][0], StatusHandler._statuses[keyword.status])
         assert_equals(keyword_json[-3][1], self._millis(keyword.starttime))
         self._verify_elapsed(keyword_json[-3][2], keyword)
         for index, message in enumerate(keyword.messages):
@@ -132,7 +148,7 @@
         self._assert_html_text(test_json[3], test.doc)
         assert_equals(test_json[2], int(test.critical == 'yes'))
         self._verify_tags(test_json[4], test.tags)
- self._assert_text(test_json[5][0], _StatusHandler._statuses[test.status]) + self._assert_text(test_json[5][0], StatusHandler._statuses[test.status])
         assert_equals(test_json[5][1], self._millis(test.starttime))
         self._verify_elapsed(test_json[5][2], test)
         if test.message != '':
@@ -170,7 +186,7 @@
         self._assert_text(suite_json[2], '')
         self._assert_html_text(suite_json[3], suite.doc)
         self._verify_metadata(suite_json[4], suite.metadata)
- assert_equals(suite_json[5][0], _StatusHandler._statuses[suite.status]) + assert_equals(suite_json[5][0], StatusHandler._statuses[suite.status])
         assert_equals(suite_json[5][1], self._millis(suite.starttime))
         self._verify_elapsed(suite_json[5][2], suite)
         if suite.message != '':
@@ -208,7 +224,8 @@
         self._visitor = JSModelCreator(result)
         self._context = self._visitor._context
         result.visit(self._visitor)
- self._verify_message(self.datamodel['errors'][0], result.errors.messages[0])
+        self._verify_message(self.datamodel['errors'][0],
+                             result.errors.messages[0])
assert_equals(self._context.dump_texts()[self.datamodel['errors'][0][3]], '*s1-s1-t1-k1')
         self._verify_suite(self.datamodel['suite'], result.suite)
         assert_equals(self.datamodel['generator'], result.generator)
=======================================
--- /utest/result/test_resultserializer.py      Wed Nov 16 02:04:47 2011
+++ /utest/result/test_resultserializer.py      Wed Nov 16 12:04:48 2011
@@ -2,12 +2,9 @@
 from StringIO import StringIO
 from xml.etree.ElementTree import XML
 from xml.etree.ElementTree import tostring
-from robot.reporting.outputparser import OutputParser

 from robot.result.builders import ResultFromXML
-from robot.result.combiningvisitor import KeywordRemovingVisitor, CombiningVisitor
 from robot.result.serializer import RebotXMLWriter
-from robot.result.datamodel import JSModelCreator
 from robot.utils.asserts import assert_equals

 from test_resultbuilder import GOLDEN_XML, GOLDEN_XML_TWICE
@@ -36,41 +33,5 @@
         self._assert_xml_content(self._xml_lines(output.getvalue()),
                                  self._xml_lines(GOLDEN_XML_TWICE))

-class TestResultJSONSerializer(unittest.TestCase):
-
-    def setUp(self):
-        output_parser = OutputParser()
-        output_parser._parse_fileobj(StringIO(GOLDEN_XML))
-        self._expected = output_parser._get_data_model()._robot_data
-        result = ResultFromXML(StringIO(GOLDEN_XML))
-        visitor = JSModelCreator(result)
-        result.visit(CombiningVisitor(visitor,
-                                      KeywordRemovingVisitor()))
-        self._datamodel = visitor.datamodel
-
-    def test_datamodel_suite(self):
-        self._equals('suite')
-
-    def test_datamodel_basemillis(self):
-        self._equals('baseMillis')
-
-    def test_datamodel_strings(self):
-        self._equals('strings')
-
-    def test_datamodel_statistics(self):
-        self._equals('stats')
-
-    def test_datamodel_errors(self):
-        self._equals('errors')
-
-    def _equals(self, key):
-        if isinstance(self._expected[key], list):
- assert_equals(len(self._expected[key]), len(self._datamodel[key]))
-            for exp, act in zip(self._expected[key], self._datamodel[key]):
-                assert_equals(exp, act)
-        else:
-            assert_equals(self._expected[key], self._datamodel[key])
-
-
 if __name__ == '__main__':
     unittest.main()

Reply via email to