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()