Revision: 2472
Author: janne.t.harkonen
Date: Thu Feb 18 04:04:54 2010
Log: Test material and initial implementation of a tool for fixing broken
xml, issue 99
http://code.google.com/p/robotframework/source/detail?r=2472
Added:
/trunk/tools/fixml
/trunk/tools/fixml/fixml.py
/trunk/tools/fixml/test
/trunk/tools/fixml/test/cut_inside_kw.xml
/trunk/tools/fixml/test/cut_inside_msg.xml
/trunk/tools/fixml/test/failing_kw_missing_end_tag.xml
/trunk/tools/fixml/test/orig-output.xml
/trunk/tools/fixml/test/passing_kw_missing_end_tag.xml
/trunk/tools/fixml/test/suite
/trunk/tools/fixml/test/suite/tests.txt
/trunk/tools/fixml/test_fixml.py
=======================================
--- /dev/null
+++ /trunk/tools/fixml/fixml.py Thu Feb 18 04:04:54 2010
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+
+import sys
+from BeautifulSoup import BeautifulStoneSoup
+
+
+class Fixml(BeautifulStoneSoup):
+ close_on_open = None
+ NESTABLE_TAGS = {
+ 'suite': ['robot','suite', 'statistics'],
+ 'doc': ['suite', 'test', 'kw'],
+ 'metadata': ['suite'],
+ 'item': ['metadata'],
+ 'status': ['suite', 'test', 'kw'],
+ 'test': ['suite'],
+ 'tags': ['test'],
+ 'tag': ['tags'],
+ 'kw': ['suite', 'test', 'kw'],
+ 'msg': ['kw', 'errors'],
+ 'arguments': ['kw'],
+ 'arg': ['arguments'],
+ 'statistics': ['robot'],
+ 'errors': ['robot'],
+ }
+
+ def unknown_starttag(self, name, *args):
+ if self.close_on_open:
+ self._popToTag(self.close_on_open)
+ self.close_on_open = None
+ BeautifulStoneSoup.unknown_starttag(self, name, *args)
+
+ def unknown_endtag(self, name):
+ BeautifulStoneSoup.unknown_endtag(self, name)
+ if name == 'status':
+ self.close_on_open = self.tagStack[-1].name
+ else:
+ self.close_on_open = None
+
+if __name__ == '__main__':
+ args = sys.argv[1:]
+ if len(args) != 2:
+ print __doc__
+ sys.exit(1)
+ outfile = open(args[1], 'w')
+ outfile.write(str(Fixml(open(args[0]))))
+ outfile.close()
=======================================
--- /dev/null
+++ /trunk/tools/fixml/test/cut_inside_kw.xml Thu Feb 18 04:04:54 2010
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<robot generated="20100218 10:42:52.363" generator="Robot trunk 20091023
(Python 2.6.4 on linux2)">
+<suite source="/home/jth/workspace/robotframework/tools/fixml/test/suite"
name="Suite">
+<doc></doc>
+<metadata>
+</metadata>
+<suite
source="/home/jth/workspace/robotframework/tools/fixml/test/suite/tests.txt"
name="Tests">
+<doc></doc>
+<metadata>
+</metadata>
+<test critical="yes" name="Test" timeout="">
+<doc></doc>
+<kw type="kw" name="My Keyword" timeout="">
+<doc></doc>
+<arguments>
+<arg>fixml</arg>
+</arguments>
+<kw type="kw" name="BuiltIn.Log" timeout="">
+<doc>Logs the given message with the given level.</doc>
+<arguments>
+<arg>${arg}</arg>
+</arguments>
+<msg timestamp="20100218 10:42:52.401" html="no" level="INFO">fixml</msg>
+<status status="PASS" endtime="20100218 10:42:52.401" starttime="20100218
10:42:52.400"></status>
+</kw>
+<kw type="kw" name="BuiltIn.Log" timeout="">
+<doc>Logs the given message with the given level.</doc>
+<arguments>
+<arg>${arg*10}</arg>
+</arguments>
+<msg timestamp="20100218 10:42:52.402" html="no"
level="INFO">fixmlfixmlfixmlfixmlfixmlfixmlfixmlfixmlfixmlfixml</msg>
=======================================
--- /dev/null
+++ /trunk/tools/fixml/test/cut_inside_msg.xml Thu Feb 18 04:04:54 2010
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<robot generated="20100218 10:42:52.363" generator="Robot trunk 20091023
(Python 2.6.4 on linux2)">
+<suite source="/home/jth/workspace/robotframework/tools/fixml/test/suite"
name="Suite">
+<doc></doc>
+<metadata>
+</metadata>
+<suite
source="/home/jth/workspace/robotframework/tools/fixml/test/suite/tests.txt"
name="Tests">
+<doc></doc>
+<metadata>
+</metadata>
+<test critical="yes" name="Test" timeout="">
+<doc></doc>
+<kw type="kw" name="My Keyword" timeout="">
+<doc></doc>
+<arguments>
+<arg>fixml</arg>
+</arguments>
+<kw type="kw" name="BuiltIn.Log" timeout="">
+<doc>Logs the given message with the given level.</doc>
+<arguments>
+<arg>${arg}</arg>
+</arguments>
+<msg timestamp="20100218 10:42:52.401" html="no" level="INFO">fixml</msg>
+<status status="PASS" endtime="20100218 10:42:52.401" starttime="20100218
10:42:52.400"></status>
+</kw>
+<kw type="kw" name="BuiltIn.Log" timeout="">
+<doc>Logs the given message with the given level.</doc>
+<arguments>
+<arg>${arg*10}</arg>
+</arguments>
+<msg timestamp="20100218 10:42:52.402" html="no"
level="INFO">fixmlfixmlfixmlfixmlfixmlfixmlfixmlfixmlfixmlfixml</msg>
+<status status="PASS" endtime="20100218 10:42:52.402" starttime="20100218
10:42:52.401"></status>
+</kw>
+<status status="PASS" endtime="20100218 10:42:52.402" starttime="20100218
10:42:52.399"></status>
+</kw>
+<tags>
+</tags>
+<status status="PASS" endtime="20100218 10:42:52.403" starttime="20100218
10:42:52.399"></status>
+</test>
+<test critical="yes" name="Failing Test" timeout="">
+<doc></doc>
+<kw type="kw" name="Fail Spectacularly" timeout="">
+<doc></doc>
+<arguments>
+</arguments>
+<kw type="kw" name="BuiltIn.Fail" timeout="">
+<doc>Fails the test immediately with the given (optional) message.</doc>
+<arguments>
+<arg>Spectacular Failure</arg>
+</arguments>
+<msg timestamp="20100218 10:42:52.406"
=======================================
--- /dev/null
+++ /trunk/tools/fixml/test/failing_kw_missing_end_tag.xml Thu Feb 18
04:04:54 2010
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<robot generated="20100218 10:42:52.363" generator="Robot trunk 20091023
(Python 2.6.4 on linux2)">
+<suite source="/home/jth/workspace/robotframework/tools/fixml/test/suite"
name="Suite">
+<doc></doc>
+<metadata>
+</metadata>
+<suite
source="/home/jth/workspace/robotframework/tools/fixml/test/suite/tests.txt"
name="Tests">
+<doc></doc>
+<metadata>
+</metadata>
+<test critical="yes" name="Test" timeout="">
+<doc></doc>
+<kw type="kw" name="My Keyword" timeout="">
+<doc></doc>
+<arguments>
+<arg>fixml</arg>
+</arguments>
+<kw type="kw" name="BuiltIn.Log" timeout="">
+<doc>Logs the given message with the given level.</doc>
+<arguments>
+<arg>${arg}</arg>
+</arguments>
+<msg timestamp="20100218 10:42:52.401" html="no" level="INFO">fixml</msg>
+<status status="PASS" endtime="20100218 10:42:52.401" starttime="20100218
10:42:52.400"></status>
+</kw>
+<kw type="kw" name="BuiltIn.Log" timeout="">
+<doc>Logs the given message with the given level.</doc>
+<arguments>
+<arg>${arg*10}</arg>
+</arguments>
+<msg timestamp="20100218 10:42:52.402" html="no"
level="INFO">fixmlfixmlfixmlfixmlfixmlfixmlfixmlfixmlfixmlfixml</msg>
+<status status="PASS" endtime="20100218 10:42:52.402" starttime="20100218
10:42:52.401"></status>
+</kw>
+<status status="PASS" endtime="20100218 10:42:52.402" starttime="20100218
10:42:52.399"></status>
+</kw>
+<tags>
+</tags>
+<status status="PASS" endtime="20100218 10:42:52.403" starttime="20100218
10:42:52.399"></status>
+</test>
+<test critical="yes" name="Failing Test" timeout="">
+<doc></doc>
+<kw type="kw" name="Fail Spectacularly" timeout="">
+<doc></doc>
+<arguments>
+</arguments>
+<kw type="kw" name="BuiltIn.Fail" timeout="">
+<doc>Fails the test immediately with the given (optional) message.</doc>
+<arguments>
+<arg>Spectacular Failure</arg>
+</arguments>
+<msg timestamp="20100218 10:42:52.406" html="no" level="FAIL">Spectacular
Failure</msg>
+<status status="FAIL" endtime="20100218 10:42:52.406" starttime="20100218
10:42:52.404"></status>
+</kw>
+<status status="FAIL" endtime="20100218 10:42:52.407" starttime="20100218
10:42:52.404"></status>
+<!-- kw end tag removed here -->
+<tags>
+</tags>
+<status status="FAIL" endtime="20100218 10:42:52.407" starttime="20100218
10:42:52.403">Spectacular Failure</status>
+</test>
+<status status="FAIL" endtime="20100218 10:42:52.407" starttime="20100218
10:42:52.398"></status>
+</suite>
+<status status="FAIL" endtime="20100218 10:42:52.408" starttime="20100218
10:42:52.369"></status>
+</suite>
+<statistics>
+<total>
+<stat fail="1" pass="1">Critical Tests</stat>
+<stat fail="1" pass="1">All Tests</stat>
+</total>
+<tag>
+</tag>
+<suite>
+<stat fail="1" doc="Suite" pass="1">Suite</stat>
+<stat fail="1" doc="Suite.Tests" pass="1">Suite.Tests</stat>
+</suite>
+</statistics>
+<errors>
+</errors>
+</robot>
=======================================
--- /dev/null
+++ /trunk/tools/fixml/test/orig-output.xml Thu Feb 18 04:04:54 2010
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<robot generated="20100218 10:42:52.363" generator="Robot trunk 20091023
(Python 2.6.4 on linux2)">
+<suite source="/home/jth/workspace/robotframework/tools/fixml/test/suite"
name="Suite">
+<doc></doc>
+<metadata>
+</metadata>
+<suite
source="/home/jth/workspace/robotframework/tools/fixml/test/suite/tests.txt"
name="Tests">
+<doc></doc>
+<metadata>
+</metadata>
+<test critical="yes" name="Test" timeout="">
+<doc></doc>
+<kw type="kw" name="My Keyword" timeout="">
+<doc></doc>
+<arguments>
+<arg>fixml</arg>
+</arguments>
+<kw type="kw" name="BuiltIn.Log" timeout="">
+<doc>Logs the given message with the given level.</doc>
+<arguments>
+<arg>${arg}</arg>
+</arguments>
+<msg timestamp="20100218 10:42:52.401" html="no" level="INFO">fixml</msg>
+<status status="PASS" endtime="20100218 10:42:52.401" starttime="20100218
10:42:52.400"></status>
+</kw>
+<kw type="kw" name="BuiltIn.Log" timeout="">
+<doc>Logs the given message with the given level.</doc>
+<arguments>
+<arg>${arg*10}</arg>
+</arguments>
+<msg timestamp="20100218 10:42:52.402" html="no"
level="INFO">fixmlfixmlfixmlfixmlfixmlfixmlfixmlfixmlfixmlfixml</msg>
+<status status="PASS" endtime="20100218 10:42:52.402" starttime="20100218
10:42:52.401"></status>
+</kw>
+<status status="PASS" endtime="20100218 10:42:52.402" starttime="20100218
10:42:52.399"></status>
+</kw>
+<tags>
+</tags>
+<status status="PASS" endtime="20100218 10:42:52.403" starttime="20100218
10:42:52.399"></status>
+</test>
+<test critical="yes" name="Failing Test" timeout="">
+<doc></doc>
+<kw type="kw" name="Fail Spectacularly" timeout="">
+<doc></doc>
+<arguments>
+</arguments>
+<kw type="kw" name="BuiltIn.Fail" timeout="">
+<doc>Fails the test immediately with the given (optional) message.</doc>
+<arguments>
+<arg>Spectacular Failure</arg>
+</arguments>
+<msg timestamp="20100218 10:42:52.406" html="no" level="FAIL">Spectacular
Failure</msg>
+<status status="FAIL" endtime="20100218 10:42:52.406" starttime="20100218
10:42:52.404"></status>
+</kw>
+<status status="FAIL" endtime="20100218 10:42:52.407" starttime="20100218
10:42:52.404"></status>
+</kw>
+<tags>
+</tags>
+<status status="FAIL" endtime="20100218 10:42:52.407" starttime="20100218
10:42:52.403">Spectacular Failure</status>
+</test>
+<status status="FAIL" endtime="20100218 10:42:52.407" starttime="20100218
10:42:52.398"></status>
+</suite>
+<status status="FAIL" endtime="20100218 10:42:52.408" starttime="20100218
10:42:52.369"></status>
+</suite>
+<statistics>
+<total>
+<stat fail="1" pass="1">Critical Tests</stat>
+<stat fail="1" pass="1">All Tests</stat>
+</total>
+<tag>
+</tag>
+<suite>
+<stat fail="1" doc="Suite" pass="1">Suite</stat>
+<stat fail="1" doc="Suite.Tests" pass="1">Suite.Tests</stat>
+</suite>
+</statistics>
+<errors>
+</errors>
+</robot>
=======================================
--- /dev/null
+++ /trunk/tools/fixml/test/passing_kw_missing_end_tag.xml Thu Feb 18
04:04:54 2010
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<robot generated="20100218 10:42:52.363" generator="Robot trunk 20091023
(Python 2.6.4 on linux2)">
+<suite source="/home/jth/workspace/robotframework/tools/fixml/test/suite"
name="Suite">
+<doc></doc>
+<metadata>
+</metadata>
+<suite
source="/home/jth/workspace/robotframework/tools/fixml/test/suite/tests.txt"
name="Tests">
+<doc></doc>
+<metadata>
+</metadata>
+<test critical="yes" name="Test" timeout="">
+<doc></doc>
+<kw type="kw" name="My Keyword" timeout="">
+<doc></doc>
+<arguments>
+<arg>fixml</arg>
+</arguments>
+<kw type="kw" name="BuiltIn.Log" timeout="">
+<doc>Logs the given message with the given level.</doc>
+<arguments>
+<arg>${arg}</arg>
+</arguments>
+<msg timestamp="20100218 10:42:52.401" html="no" level="INFO">fixml</msg>
+<status status="PASS" endtime="20100218 10:42:52.401" starttime="20100218
10:42:52.400"></status>
+</kw>
+<kw type="kw" name="BuiltIn.Log" timeout="">
+<doc>Logs the given message with the given level.</doc>
+<arguments>
+<arg>${arg*10}</arg>
+</arguments>
+<msg timestamp="20100218 10:42:52.402" html="no"
level="INFO">fixmlfixmlfixmlfixmlfixmlfixmlfixmlfixmlfixmlfixml</msg>
+<status status="PASS" endtime="20100218 10:42:52.402" starttime="20100218
10:42:52.401"></status>
+<!-- ending kw removed here -->
+<status status="PASS" endtime="20100218 10:42:52.402" starttime="20100218
10:42:52.399"></status>
+</kw>
+<tags>
+</tags>
+<status status="PASS" endtime="20100218 10:42:52.403" starttime="20100218
10:42:52.399"></status>
+</test>
+<test critical="yes" name="Failing Test" timeout="">
+<doc></doc>
+<kw type="kw" name="Fail Spectacularly" timeout="">
+<doc></doc>
+<arguments>
+</arguments>
+<kw type="kw" name="BuiltIn.Fail" timeout="">
+<doc>Fails the test immediately with the given (optional) message.</doc>
+<arguments>
+<arg>Spectacular Failure</arg>
+</arguments>
+<msg timestamp="20100218 10:42:52.406" html="no" level="FAIL">Spectacular
Failure</msg>
+<status status="FAIL" endtime="20100218 10:42:52.406" starttime="20100218
10:42:52.404"></status>
+</kw>
+<status status="FAIL" endtime="20100218 10:42:52.407" starttime="20100218
10:42:52.404"></status>
+</kw>
+<tags>
+</tags>
+<status status="FAIL" endtime="20100218 10:42:52.407" starttime="20100218
10:42:52.403">Spectacular Failure</status>
+</test>
+<status status="FAIL" endtime="20100218 10:42:52.407" starttime="20100218
10:42:52.398"></status>
+</suite>
+<status status="FAIL" endtime="20100218 10:42:52.408" starttime="20100218
10:42:52.369"></status>
+</suite>
+<statistics>
+<total>
+<stat fail="1" pass="1">Critical Tests</stat>
+<stat fail="1" pass="1">All Tests</stat>
+</total>
+<tag>
+</tag>
+<suite>
+<stat fail="1" doc="Suite" pass="1">Suite</stat>
+<stat fail="1" doc="Suite.Tests" pass="1">Suite.Tests</stat>
+</suite>
+</statistics>
+<errors>
+</errors>
+</robot>
=======================================
--- /dev/null
+++ /trunk/tools/fixml/test/suite/tests.txt Thu Feb 18 04:04:54 2010
@@ -0,0 +1,16 @@
+* Test Cases *
+Test
+ My Keyword fixml
+
+Failing Test
+ Fail Spectacularly
+
+* Keywords *
+My Keyword
+ [Arguments] ${arg}
+ Log ${arg}
+ Log ${arg*10}
+
+Fail Spectacularly
+ Fail Spectacular Failure
+
=======================================
--- /dev/null
+++ /trunk/tools/fixml/test_fixml.py Thu Feb 18 04:04:54 2010
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+
+import os
+import sys
+import subprocess
+import unittest
+
+BASEDIR = os.path.dirname(os.path.abspath(__file__))
+# Ensure robot found in PYTHONPATH
+sys.path.insert(0, os.path.join(BASEDIR, '..', '..', 'src'))
+
+from robot.output import TestSuite
+from robot.utils.asserts import assert_equals, assert_true
+
+OUTDIR = os.path.join(BASEDIR, 'test', 'output')
+if not os.path.exists(OUTDIR):
+ os.mkdir(OUTDIR)
+
+
+class TestFixml(unittest.TestCase):
+
+ def test_missing_kw_in_passing_test(self):
+ suite = self._fix_xml_and_parse('passing_kw_missing_end_tag')
+ assert_equals(len(suite.tests), 2)
+ self._assert_statistics(suite, 1, 1)
+ assert_equals(len(suite.tests[0].keywords[0].keywords), 2)
+
+ def test_missing_kw_in_failing_test(self):
+ suite = self._fix_xml_and_parse('failing_kw_missing_end_tag')
+ assert_equals(len(suite.tests), 2)
+ self._assert_statistics(suite, 1, 1)
+ assert_equals(len(suite.tests[1].keywords[0].keywords), 1)
+
+ def test_xml_cut_inside_keyword(self):
+ suite = self._fix_xml_and_parse('cut_inside_kw')
+ assert_equals(len(suite.tests), 1)
+ self._assert_statistics(suite, 0, 1)
+ assert_equals(len(suite.tests[0].keywords[0].keywords), 2)
+
+ def test_xml_cut_inside_msg_tag(self):
+ suite = self._fix_xml_and_parse('cut_inside_msg')
+ assert_equals(len(suite.tests), 2)
+ self._assert_statistics(suite, 1, 1)
+ assert_equals(len(suite.tests[1].keywords[0].keywords), 1)
+
+ def _fix_xml_and_parse(self, base):
+ outfile = self._fix_xml(base)
+ return TestSuite(outfile).suites[0]
+
+ def _fix_xml(self, base):
+ infile = os.path.join('test', '%s.xml' % base)
+ outfile = os.path.join(OUTDIR, '%s-fixed.xml' % base)
+ subprocess.call(['python', 'fixml.py', infile, outfile])
+ return outfile
+
+ def _assert_statistics(self, suite, passed, failed):
+ assert_equals(suite.critical_stats.passed, passed)
+ assert_equals(suite.critical_stats.failed, failed)
+
+
+if __name__ == '__main__':
+ unittest.main()