Revision: 595ef62880a7
Branch: default
Author: Pekka Klärck
Date: Fri Sep 27 07:31:44 2013 UTC
Log: Support plain text (code blocks) in reST parser.
This is a patch by Asko Soukka <asko.sou...@iki.fi> and Vivek Kumar Verma
<1990vivekkumarve...@gmail.com> implemented as part of GSOC 2013. Thanks
guys!
Update issue 1495
Status: Started
Patch applied. I'll refactor it later to match our coding conventions a bit
better. It's nevertheless certain that RF 2.8.2 will contain plain text
reST support!
http://code.google.com/p/robotframework/source/detail?r=595ef62880a7
Added:
/atest/robot/parsing/data_formats/rest_directives.txt
/atest/testdata/parsing/data_formats/rest_directives/sample.rst
Modified:
/doc/userguide/src/CreatingTestData/TestDataSyntax.rst
/src/robot/parsing/restreader.py
=======================================
--- /dev/null
+++ /atest/robot/parsing/data_formats/rest_directives.txt Fri Sep 27
07:31:44 2013 UTC
@@ -0,0 +1,21 @@
+*** Settings ***
+Suite Setup Run keywords
+... Check is docutils installed
+Test Setup Run keywords
+... Make test non-critical and fail it if docutils is not
installed
+Force Tags regression jybot pybot
+Resource formats_resource.txt
+
+*** Test Cases ***
+
+One ReST using code-directive
+ [Setup]
+ ${status} ${msg} = Run Keyword And Ignore Error Run sample file and
check tests parsing${/}data_formats${/}rest_directives${/}sample.rst
+ Run Keyword If "${DOCUTILS INSTALLED}" == "YES" and "${status}"
== "FAIL" FAIL ${msg}
+ Run Keyword Unless "${DOCUTILS INSTALLED}" == "YES" Clear error
should be given when docutils is not installed
+
+*** Keywords ***
+
+Clear Error Should Be Given When Docutils Is Not Installed
+ ${stderr} = Get Stderr
+ Should Match RegExp ${stderr} \\[ ERROR \\]
Parsing '.*[/\\\\]sample.rst' failed: Using reStructuredText test data
requires having 'docutils' module installed.\n \n Try --help for usage
information.\n
=======================================
--- /dev/null
+++ /atest/testdata/parsing/data_formats/rest_directives/sample.rst Fri Sep
27 07:31:44 2013 UTC
@@ -0,0 +1,104 @@
+ReST Test Data Example
+======================
+
+This text should be ignored, even though it's no a comment.
+We have a devious plan to rule the world with robots.
+
+.. code:: robotframework
+
+ *Setting* *Value*
+
+ Document A complex testdata file in rst format.
+ Default Tags default1
+ Force Tags force1 force2
+
+ Suite Setup Log Setup
+ Test Teardown Log Test Teardown
+ Resource ../resources/rest_resource.rst
+ Variables ../resources/variables.py
+ Library OperatingSystem
+
+.. code:: robotframework
+
+ * Variable
+
+ ${table_var} foo
+ @{table_listvar} bar ${table_var}
+ ${quoted} """this has """"many "" quotes """""
+ ${single_quoted} s'ingle'qu'ot'es''
+
+.. code:: robotframework
+
+ ***Test Case***
+
+ Passing Log Passing test case.
+
+ Failing [Document] FAIL Failing test case.
+ Fail Failing test case.
+ User Keyword [Document] FAIL A cunning argument. != something
+ My Keyword With Arg A cunning argument.
+
+ Own Tags [Tags] own1 own2
+ Log tags test
+
+ Default Tags No Operation
+
+ Variable Table Equals ${table_var} foo
+ Equals @{table_listvar}[0] bar
+ Equals @{table_listvar}[1] foo
+
+ Resource File Keyword from ReST resource
+ Keyword from ReST resource 2
+ Equals ${rest_resource_var} ReST Resource Variable
+ Equals ${rest_resource_var2} ReST Resource Variable From
Recursive Resource
+
+ Variable File Equals @{file_listvar}[0] ${True}
+ Equals @{file_listvar}[1] ${3.14}
+ Equals @{file_listvar}[2] Hello, world!!
+ Equals ${file_var1} ${-314}
+ Equals ${file_var2} file variable 2
+
+ Library Import Fail If Dir Empty ${CURDIR}
+
+ Test Timeout [Timeout] 1second
+ [Document] FAIL Test timeout 1 second exceeded.
+ Sleep 2
+
+ Keyword Timeout [Document] FAIL Keyword timeout 1 second exceeded.
+ Timeouted Keyword
+
+ Empty Rows
+ [Document] Testing that empty rows are ignored. FAIL Expected
failure.
+
+ Noop
+
+ Fail Expected failure.
+
+ Document [Document] Testing the metadata parsing.
+ noop
+
+ Default Fixture Noop
+
+ Overridden Fixture [Teardown] Fail Failing Teardown
+ [Setup] Log Own Setup
+ [Document] FAIL Teardown failed:\n Failing Teardown
+ NOOP
+
+ Quotes Equals ${quoted} """this has """"many "" quotes """""
+ Equals ${single_quoted} s'ingle'qu'ot'es''
+
+.. code:: robotframework
+
+ *User Keywords* *Action* *Argument* *Argument* *Argument*
+
+ My Keyword With Arg [Arguments] ${arg1}
+ Keyword with no arguments
+ Another Keyword ${arg1}
+
+ Another Keyword [Arguments] ${arg1} ${arg2}=something
+ Equals ${arg1} ${arg2}
+
+ Timeouted Keyword [Timeout] 1second
+ Sleep 2
+
+ Keyword With No Arguments Log Hello world!
=======================================
--- /doc/userguide/src/CreatingTestData/TestDataSyntax.rst Sun Jun 9
11:28:05 2013 UTC
+++ /doc/userguide/src/CreatingTestData/TestDataSyntax.rst Fri Sep 27
07:31:44 2013 UTC
@@ -404,6 +404,51 @@
\ Directory Should Exist ${path}
============ ====================== ============ ==========
+.. note:: In reST files, also Space separated format is
+ supported starting from Robot Framework 2.8.2.
+
+Apart from writing the test cases in reStructuredText documents using table
+format, user can write the test cases in space separated format also. For
+writing test case in space separated format, ``.. code::
+robotframework``-directive should be used to indicate that test suite in
space
+separated text syntax is starting. The actual test suite would start from
the
+next line with proper indentation.
+
+The actual test suite can be written in a manner similar to shown earlier
(in
+`space separated format`_). Also same escaping rule needs to be followed.
For
+example::
+
+ .. code:: robotframework
+
+ *** Settings ***
+
+ Library OperatingSystem
+
+ *** Variables ***
+
+ ${MESSAGE} Hello, world!
+
+ *** Test Cases ***
+
+ My Test
+ [Documentation] Example test
+ Log ${MESSAGE}
+ My Keyword /tmp
+
+ Another Test
+ Should Be Equal ${MESSAGE} Hello, world!
+
+ *** Keywords ***
+
+ My Keyword
+ [Arguments] ${path}
+ Directory Should Exist ${path}
+
+.. note:: If a single reST document contains multiple
+ ``.. code:: robotframework``-directives, their contents are
+ concatenated into a text file before parsing with space separated
+ format parser.
+
Editing test data
`````````````````
=======================================
--- /src/robot/parsing/restreader.py Thu Jun 6 14:00:44 2013 UTC
+++ /src/robot/parsing/restreader.py Fri Sep 27 07:31:44 2013 UTC
@@ -12,18 +12,18 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import tempfile
import os
-
+import tempfile
from robot.errors import DataError
-
from .htmlreader import HtmlReader
+from .txtreader import TxtReader
def RestReader():
try:
- from docutils.core import publish_cmdline
- from docutils.parsers.rst import directives
+ import docutils.core
+ from docutils.parsers.rst.directives import register_directive
+ from docutils.parsers.rst.directives import body
except ImportError:
raise DataError("Using reStructuredText test data requires having "
"'docutils' module installed.")
@@ -32,25 +32,75 @@
# See e.g. ug2html.py for an example how custom directives are created.
ignorer = lambda *args: []
ignorer.content = 1
- directives.register_directive('sourcecode', ignorer)
+ register_directive('sourcecode', ignorer)
- class RestReader(HtmlReader):
+ # Override default CodeBlock with a derived custom directive, which can
+ # capture Robot Framework test suite snippets and then discard the
content
+ # to speed up the parser.
+ class RobotAwareCodeBlock(body.CodeBlock):
+ def run(self):
+ if u'robotframework' in self.arguments:
+ document = self.state_machine.document
+ if RestReader.has_robotdata(document):
+ robotdata = RestReader.get_robotdata(document) + u'\n'
+ robotdata += u'\n'.join(self.content)
+ else:
+ robotdata = u'\n'.join(self.content)
+ RestReader.set_robotdata(document, robotdata)
+ return [] # Parsed content is not required for testing
purposes
+ register_directive('code', RobotAwareCodeBlock)
+ class RestReader:
def read(self, rstfile, rawdata):
- htmlpath = self._rest_to_html(rstfile.name)
- htmlfile = None
+ doctree = docutils.core.publish_doctree(rstfile.read())
+ if RestReader.has_robotdata(doctree):
+ delegate = RestReader.txtreader_read
+ else:
+ delegate = RestReader.htmlreader_read
+ return delegate(doctree, rawdata)
+
+ @staticmethod
+ def has_robotdata(doctree):
+ return hasattr(doctree, '_robotdata')
+
+ @staticmethod
+ def set_robotdata(doctree, robotdata):
+ setattr(doctree, '_robotdata', robotdata)
+
+ @staticmethod
+ def get_robotdata(doctree, default=u''):
+ return getattr(doctree, '_robotdata', default)
+
+ @staticmethod
+ def txtreader_read(doctree, rawdata):
+ txtfile = tempfile.NamedTemporaryFile(suffix='.robot')
+
txtfile.write(RestReader.get_robotdata(doctree).encode('utf-8'))
+ txtfile.seek(0)
+ txtreader = TxtReader()
try:
- htmlfile = open(htmlpath, 'rb')
- return HtmlReader.read(self, htmlfile, rawdata)
+ return txtreader.read(txtfile, rawdata)
finally:
+ # Ensure that the temp file gets closed and deleted:
+ if txtfile:
+ txtfile.close()
+ if os.path.isfile(txtfile.name):
+ os.remove(txtfile.name)
+
+ @staticmethod
+ def htmlreader_read(doctree, rawdata):
+ htmlfile = tempfile.NamedTemporaryFile(suffix='.html')
+ htmlfile.write(docutils.core.publish_from_doctree(
+ doctree, writer_name='html',
+ settings_overrides={'output_encoding': 'utf-8'}))
+ htmlfile.seek(0)
+ htmlreader = HtmlReader()
+ try:
+ return htmlreader.read(htmlfile, rawdata)
+ finally:
+ # Ensure that the temp file gets closed and deleted:
if htmlfile:
htmlfile.close()
- os.remove(htmlpath)
-
- def _rest_to_html(self, rstpath):
- filedesc, htmlpath = tempfile.mkstemp('.html')
- os.close(filedesc)
- publish_cmdline(writer_name='html', argv=[rstpath, htmlpath])
- return htmlpath
+ if os.path.isfile(htmlfile.name):
+ os.remove(htmlfile.name)
return RestReader()
--
---
You received this message because you are subscribed to the Google Groups "robotframework-commit" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to robotframework-commit+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.