4 new revisions:
Revision: 9e6b0a81f43e
Author: Janne Härkönen <[email protected]>
Date: Wed Jun 15 02:33:16 2011
Log: Fix test after API change
http://code.google.com/p/robotframework/source/detail?r=9e6b0a81f43e
Revision: 174034b21137
Author: Janne Härkönen <[email protected]>
Date: Wed Jun 15 03:39:31 2011
Log: Fixed comment syntax in CSS
http://code.google.com/p/robotframework/source/detail?r=174034b21137
Revision: 8447b3e58bce
Author: Janne Härkönen <[email protected]>
Date: Wed Jun 15 03:41:12 2011
Log: serializing: write settings as separate JSON object
http://code.google.com/p/robotframework/source/detail?r=8447b3e58bce
Revision: 65019c59d464
Author: Janne Härkönen <[email protected]>
Date: Wed Jun 15 03:41:24 2011
Log: merge
http://code.google.com/p/robotframework/source/detail?r=65019c59d464
==============================================================================
Revision: 9e6b0a81f43e
Author: Janne Härkönen <[email protected]>
Date: Wed Jun 15 02:33:16 2011
Log: Fix test after API change
http://code.google.com/p/robotframework/source/detail?r=9e6b0a81f43e
Modified:
/utest/serializing/test_reporting.py
=======================================
--- /utest/serializing/test_reporting.py Tue Jun 14 23:56:15 2011
+++ /utest/serializing/test_reporting.py Wed Jun 15 02:33:16 2011
@@ -17,10 +17,9 @@
def set_serialize_report_mock():
results = {'report_path':None}
- def serialize_report(test_output_datamodel, report_path, title=None,
background=None, logpath=None):
+ def serialize_report(test_output_datamodel, report_path, title=None,
logpath=None):
results['report_path'] = report_path
results['title'] = title
- results['background'] = background
results['logpath'] = logpath
robot.serializing.testoutput.serialize_report = serialize_report
return results
==============================================================================
Revision: 174034b21137
Author: Janne Härkönen <[email protected]>
Date: Wed Jun 15 03:39:31 2011
Log: Fixed comment syntax in CSS
http://code.google.com/p/robotframework/source/detail?r=174034b21137
Modified:
/src/robot/webcontent/common.css
=======================================
--- /src/robot/webcontent/common.css Tue Jun 14 23:23:59 2011
+++ /src/robot/webcontent/common.css Wed Jun 15 03:39:31 2011
@@ -138,7 +138,8 @@
}
#generated {
-/ / TODO : Add width when timestamp in correct format / / width : 29 %;
+ /* TODO : Add width when timestamp in correct format
+ width : 29 %; */
float: right;
text-align: right;
font-size: 0.9em;
==============================================================================
Revision: 8447b3e58bce
Author: Janne Härkönen <[email protected]>
Date: Wed Jun 15 03:41:12 2011
Log: serializing: write settings as separate JSON object
http://code.google.com/p/robotframework/source/detail?r=8447b3e58bce
Added:
/src/robot/serializing/json.py
Modified:
/src/robot/__init__.py
/src/robot/serializing/jsondatamodel.py
/src/robot/serializing/serialize_log.py
/src/robot/serializing/testoutput.py
/utest/serializing/test_js_serializer.py
/utest/serializing/test_reporting.py
=======================================
--- /dev/null
+++ /src/robot/serializing/json.py Wed Jun 15 03:41:12 2011
@@ -0,0 +1,59 @@
+# Copyright 2008-2011 Nokia Siemens Networks Oyj
+#
+# 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.
+
+def encode_basestring(string):
+ def get_matching_char(c):
+ val = ord(c)
+ if val < 127 and val > 31:
+ return c
+ return '\\u' + hex(val)[2:].rjust(4,'0')
+ string = string.replace('\\', '\\\\')
+ string = string.replace('"', '\\"')
+ string = string.replace('\b', '\\b')
+ string = string.replace('\f', '\\f')
+ string = string.replace('\n', '\\n')
+ string = string.replace('\r', '\\r')
+ string = string.replace('\t', '\\t')
+ result = []
+ for c in string:
+ result += [get_matching_char(c)]
+ return '"'+''.join(result)+'"'
+
+def json_dump(data, output):
+ if data is None:
+ output.write('null')
+ elif isinstance(data, int):
+ output.write(str(data))
+ elif isinstance(data, long):
+ output.write(str(data))
+ elif isinstance(data, basestring):
+ output.write(encode_basestring(data))
+ elif isinstance(data, list):
+ output.write('[')
+ for index, item in enumerate(data):
+ json_dump(item, output)
+ if index < len(data)-1:
+ output.write(',')
+ output.write(']')
+ elif type(data) == dict:
+ output.write('{')
+ for index, item in enumerate(data.items()):
+ json_dump(item[0], output)
+ output.write(':')
+ json_dump(item[1], output)
+ if index < len(data)-1:
+ output.write(',')
+ output.write('}')
+ else:
+ raise Exception('Data type (%s) serialization not supported' %
type(data))
=======================================
--- /src/robot/__init__.py Mon Jun 13 04:24:20 2011
+++ /src/robot/__init__.py Wed Jun 15 03:41:12 2011
@@ -132,7 +132,7 @@
_, settings = settings.get_rebot_datasources_and_settings()
if settings['SplitOutputs'] > 0:
raise Exception('Splitting? No way!')
- Reporter().execute(settings, output_src)
+ Reporter(settings).execute(output_src)
LOGGER.close()
return suite
@@ -155,7 +155,7 @@
settings = RebotSettings(options)
LOGGER.register_console_logger(colors=settings['MonitorColors'])
LOGGER.disable_message_cache()
- suite = Reporter().execute_rebot(settings, *datasources)
+ suite = Reporter(settings).execute_rebot(*datasources)
LOGGER.close()
return suite
=======================================
--- /src/robot/serializing/jsondatamodel.py Wed Jun 15 01:08:49 2011
+++ /src/robot/serializing/jsondatamodel.py Wed Jun 15 03:41:12 2011
@@ -15,19 +15,29 @@
from robot import utils
from elementhandlers import TextIndex
+import json
class DataModel(object):
def __init__(self, robot_data):
self._robot_data = robot_data
+ self._settings = None
def set_generated(self, timetuple):
self._robot_data['generatedMillis'] =
long(time.mktime(timetuple))*1000-self._robot_data['baseMillis']
self._robot_data['generatedTimestamp'] =
utils.format_time(timetuple, daytimesep=' ', gmtsep=' ')
+ def set_settings(self, settings):
+ self._settings = settings
+
def write_to(self, output):
- output.write('window.output = ')
- json_dump(self._robot_data, output)
+ self._dump_json('window.output = ', self._robot_data, output)
+ if self._settings:
+ self._dump_json('window.settings = ', self._settings, output)
+
+ def _dump_json(self, name, data, output):
+ output.write(name)
+ json.json_dump(data, output)
output.write(';\n')
def remove_keywords(self):
@@ -59,48 +69,4 @@
self._collect_used_text_indices(item.values(), result)
return result
-def encode_basestring(string):
- def get_matching_char(c):
- val = ord(c)
- if val < 127 and val > 31:
- return c
- return '\\u' + hex(val)[2:].rjust(4,'0')
- string = string.replace('\\', '\\\\')
- string = string.replace('"', '\\"')
- string = string.replace('\b', '\\b')
- string = string.replace('\f', '\\f')
- string = string.replace('\n', '\\n')
- string = string.replace('\r', '\\r')
- string = string.replace('\t', '\\t')
- result = []
- for c in string:
- result += [get_matching_char(c)]
- return '"'+''.join(result)+'"'
-
-def json_dump(data, output):
- if data is None:
- output.write('null')
- elif isinstance(data, int):
- output.write(str(data))
- elif isinstance(data, long):
- output.write(str(data))
- elif isinstance(data, basestring):
- output.write(encode_basestring(data))
- elif isinstance(data, list):
- output.write('[')
- for index, item in enumerate(data):
- json_dump(item, output)
- if index < len(data)-1:
- output.write(',')
- output.write(']')
- elif type(data) == dict:
- output.write('{')
- for index, item in enumerate(data.items()):
- json_dump(item[0], output)
- output.write(':')
- json_dump(item[1], output)
- if index < len(data)-1:
- output.write(',')
- output.write('}')
- else:
- raise Exception('Data type (%s) serialization not supported' %
type(data))
+
=======================================
--- /src/robot/serializing/serialize_log.py Wed Jun 15 01:09:45 2011
+++ /src/robot/serializing/serialize_log.py Wed Jun 15 03:41:12 2011
@@ -28,25 +28,24 @@
CSS_MEDIA_TYPE_REGEXP = re.compile('media=\"([^\"]+)\"')
-def serialize_log(output, log_path, title=None):
+def serialize_log(output, log_path):
if log_path is None:
return
- _build_file(log_path, output, title, LOG_TEMPLATE)
-
-def serialize_report(output, report_path, title=None, log_path=None):
+ _build_file(log_path, output, LOG_TEMPLATE)
+
+def serialize_report(output, report_path):
if report_path is None:
return
- _build_file(report_path, output, title, REPORT_TEMPLATE,
- _relative_log_path(report_path, log_path))
+ _build_file(report_path, output, REPORT_TEMPLATE)
def _relative_log_path(report, log):
if not log:
return None
return utils.get_link_path(log, os.path.dirname(report))
-def _build_file(outpath, output, title, template, log_path=None):
+def _build_file(outpath, output, template):
with codecs.open(outpath, 'w', encoding='UTF-8') as outfile:
- builder = OutputFileBuilder(outfile, output, title, log_path)
+ builder = OutputFileBuilder(outfile, output)
with open(template, 'r') as tmpl:
for line in tmpl:
builder.line(line)
@@ -54,18 +53,12 @@
class OutputFileBuilder(object):
- def __init__(self, outfile, output, title, log_path=None):
+ def __init__(self, outfile, output):
self._outfile = outfile
- self._log_path = log_path
self._output = output
- self._title = title
def line(self, line):
- if self._is_title_line_to_handle(line):
- self._write_title()
- elif self._is_log_path_line_to_handle(line):
- self._replace_log_path(line)
- elif self._is_output_js(line):
+ if self._is_output_js(line):
self._write_output_js()
elif self._is_css_line(line):
self._write_lines_css(line)
@@ -74,18 +67,6 @@
else:
self._outfile.write(line)
- def _is_title_line_to_handle(self, line):
- return self._title is not None and line.startswith('<title>')
-
- def _write_title(self):
- self._outfile.write('<title>%s</title>\n' % self._title)
-
- def _is_log_path_line_to_handle(self, line):
- return self._log_path and 'log.html' in line
-
- def _replace_log_path(self, line):
- self._outfile.write(line.replace('log.html', self._log_path))
-
def _is_output_js(self, line):
return line.startswith('<!-- OUTPUT JS -->')
=======================================
--- /src/robot/serializing/testoutput.py Wed Jun 15 01:12:19 2011
+++ /src/robot/serializing/testoutput.py Wed Jun 15 03:41:12 2011
@@ -36,61 +36,98 @@
class Reporter(object):
- def __init__(self):
+ def __init__(self, settings):
self._robot_test_output_cached = None
self._temp_file = None
self._suite = None
-
- def _make_report(self, report_path, log_path, data_model, settings):
+ self._settings = settings
+
+ def _make_report(self, report_path, data_model):
if report_path:
- serialize_report(data_model, report_path,
settings['ReportTitle'], log_path)
+ data_model.set_settings(self._get_report_settings())
+ serialize_report(data_model, report_path)
LOGGER.output_file('Report', report_path)
- def _make_log(self, log_path, data_model, settings):
+ def _get_report_settings(self):
+ return {
+ 'title': self._settings['ReportTitle'],
+ 'background' : self._resolve_background_colors(),
+ 'logURL': self._url_from_path(self._parse_file('Report'),
+ self._parse_file('Log'))
+ }
+
+ def _url_from_path(self, source, dest):
+ if not dest:
+ return None
+ return utils.get_link_path(dest, os.path.dirname(source))
+
+ def _resolve_background_colors(self):
+ color_str = self._settings['ReportBackground']
+ if color_str and color_str.count(':') not in [1, 2]:
+ color_str = None
+ if not color_str:
+ color_str = '#99FF66:#FF3333'
+ colors = color_str.split(':', 2)
+ if len(colors) == 2:
+ colors.insert(1, colors[0])
+ return {'pass': colors[0], 'nonCriticalFail': colors[1], 'fail':
colors[2]}
+
+ def _make_log(self, log_path, data_model):
if log_path:
- serialize_log(data_model, log_path, settings['LogTitle'])
+ data_model.set_settings(self._get_log_settings())
+ serialize_log(data_model, log_path)
LOGGER.output_file('Log', log_path)
- def _make_xunit(self, xunit_path, data_source, settings):
+
+ def _get_log_settings(self):
+ return {
+ 'title': self._settings['ReportTitle'],
+ 'reportURL': self._url_from_path(self._parse_file('Log'),
+ self._parse_file('Report'))
+ }
+
+ def _make_xunit(self, xunit_path, data_source):
if xunit_path:
- self._robot_test_output([data_source],
settings).serialize_xunit(xunit_path)
-
- def _robot_test_output(self, data_sources, settings):
+
self._robot_test_output([data_source]).serialize_xunit(xunit_path)
+
+ def _robot_test_output(self, data_sources):
if self._robot_test_output_cached is None:
- self._suite, exec_errors = process_outputs(data_sources,
settings)
- self._suite.set_options(settings)
- self._robot_test_output_cached = RobotTestOutput(self._suite,
exec_errors, settings)
+ self._suite, exec_errors = process_outputs(data_sources,
self._settings)
+ self._suite.set_options(self._settings)
+ self._robot_test_output_cached = RobotTestOutput(self._suite,
exec_errors, self._settings)
return self._robot_test_output_cached
- def _combine_outputs(self, data_sources, settings):
- output_file = self._parse_file(settings['Output'])
+ def _combine_outputs(self, data_sources):
+ output_file = self._parse_file('Output')
if output_file is None:
handle, output_file = tempfile.mkstemp(suffix='.xml',
prefix='rebot-')
os.close(handle)
self._temp_file = output_file
- self._robot_test_output(data_sources,
settings).serialize_output(output_file, log=not self._temp_file)
+
self._robot_test_output(data_sources).serialize_output(output_file, log=not
self._temp_file)
return output_file
- def execute_rebot(self, settings, *data_sources):
- combined = self._combine_outputs(data_sources, settings)
- self.execute(settings, combined)
+ def execute_rebot(self, *data_sources):
+ combined = self._combine_outputs(data_sources)
+ self.execute(combined)
if self._temp_file:
os.remove(self._temp_file)
return self._suite
- def execute(self, settings, data_source):
+ def execute(self, data_source):
data_model = jsparser.create_datamodel_from(data_source)
data_model.set_generated(time.localtime())
- log_path = self._parse_file(settings['Log'])
- report_path = self._parse_file(settings['Report'])
- self._make_log(log_path, data_model, settings)
+ log_path = self._parse_file('Log')
+ report_path = self._parse_file('Report')
+ self._make_log(log_path, data_model)
data_model.remove_keywords()
- self._make_report(report_path, log_path, data_model, settings)
- xunit_path = self._parse_file(settings['XUnitFile'])
- self._make_xunit(xunit_path, data_source, settings)
-
- def _parse_file(self, string):
- return string if string != 'NONE' else None
+ self._make_report(report_path, data_model)
+ xunit_path = self._parse_file('XUnitFile')
+ self._make_xunit(xunit_path, data_source)
+
+ def _parse_file(self, name):
+ value = self._settings[name]
+ return value if value != 'NONE' else None
+
# TODO: Most (all?) of this class is dead code
=======================================
--- /utest/serializing/test_js_serializer.py Wed Jun 15 01:08:49 2011
+++ /utest/serializing/test_js_serializer.py Wed Jun 15 03:41:12 2011
@@ -13,7 +13,7 @@
import xml.sax as sax
from robot.serializing.jsparser import _RobotOutputHandler
-from robot.serializing.jsondatamodel import json_dump
+from robot.serializing.json import json_dump
from robot.serializing.elementhandlers import Context
from robot.utils.asserts import assert_equals, assert_true
=======================================
--- /utest/serializing/test_reporting.py Wed Jun 15 02:33:16 2011
+++ /utest/serializing/test_reporting.py Wed Jun 15 03:41:12 2011
@@ -39,7 +39,6 @@
class TestReporting(unittest.TestCase):
def setUp(self):
- self._reporter = Reporter()
self._settings = {
'Report': 'NONE',
'Log': 'NONE',
@@ -70,12 +69,12 @@
'EndTime': 0,
'LogLevel': 'INFO'
}
+ self._reporter = Reporter(self._settings)
self._original_logger = robot.serializing.testoutput.LOGGER
robot.serializing.testoutput.LOGGER = Logger()
robot.serializing.testoutput.LOGGER.disable_automatic_console_logger()
self._log_results = set_serialize_log_mock()
self._report_results = set_serialize_report_mock()
- #self._process_outputs_results = set_process_outputs_mock()
def tearDown(self):
robot.serializing.testoutput.LOGGER = self._original_logger
@@ -83,33 +82,31 @@
def test_generate_report_and_log(self):
self._settings['Log'] = 'log.html'
self._settings['Report'] = 'report.html'
- self._reporter.execute(self._settings, resources.GOLDEN_OUTPUT)
+ self._reporter.execute(resources.GOLDEN_OUTPUT)
self._assert_expected_log('log.html')
self._assert_expected_report('report.html')
- self._assert_log_link_in_report('log.html')
def test_no_generation(self):
- self._reporter.execute(self._settings, resources.GOLDEN_OUTPUT)
+ self._reporter.execute(resources.GOLDEN_OUTPUT)
self._assert_no_log()
self._assert_no_report()
def test_only_log(self):
self._settings['Log'] = 'only-log.html'
- self._reporter.execute(self._settings, resources.GOLDEN_OUTPUT)
+ self._reporter.execute(resources.GOLDEN_OUTPUT)
self._assert_expected_log('only-log.html')
self._assert_no_report()
def test_only_report(self):
self._settings['Report'] = 'reports-only.html'
- self._reporter.execute(self._settings, resources.GOLDEN_OUTPUT)
+ self._reporter.execute(resources.GOLDEN_OUTPUT)
self._assert_no_log()
self._assert_expected_report('reports-only.html')
- self._assert_no_log_links_in_report()
def test_multiple_outputs(self):
self._settings['Log'] = 'log.html'
self._settings['Report'] = 'report.html'
- self._reporter.execute_rebot(self._settings,
*[resources.GOLDEN_OUTPUT, resources.GOLDEN_OUTPUT2])
+ self._reporter.execute_rebot(*[resources.GOLDEN_OUTPUT,
resources.GOLDEN_OUTPUT2])
self._assert_expected_log('log.html')
self._assert_expected_report('report.html')
@@ -119,12 +116,6 @@
def _assert_expected_report(self, expected_file_name):
self.assertEquals(self._report_results['report_path'],
expected_file_name)
- def _assert_log_link_in_report(self, expected_log_link):
- self.assertEquals(self._report_results['logpath'],
expected_log_link)
-
- def _assert_no_log_links_in_report(self):
- self._assert_log_link_in_report(None)
-
def _assert_no_log(self):
self._assert_expected_log(None)
==============================================================================
Revision: 65019c59d464
Author: Janne Härkönen <[email protected]>
Date: Wed Jun 15 03:41:24 2011
Log: merge
http://code.google.com/p/robotframework/source/detail?r=65019c59d464