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

Reply via email to