Skip to content

Commit 1fc79a1

Browse files
committed
Support reading --doc and --metadata from file.
Fixes robotframework#4008.
1 parent 70c11af commit 1fc79a1

7 files changed

Lines changed: 124 additions & 34 deletions

File tree

‎atest/robot/cli/rebot/argumentfile.robot‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ ${ARG FILE} %{TEMPDIR}/arguments.txt
99
Argument File
1010
${content} = Catenate SEPARATOR=\n
1111
... --name From Arg File
12-
... -D= Leading space
12+
... -D= Leading space is ignored
1313
... -M${SPACE*5}No:Spaces
1414
... \# comment line
1515
... ${EMPTY}
@@ -24,5 +24,5 @@ Argument File
2424
Should Be Empty ${result.stderr}
2525
Directory Should Contain ${CLI OUTDIR} myout.xml
2626
Should Be Equal ${SUITE.name} From Arg File
27-
Should Be Equal ${SUITE.doc} ${SPACE}Leading space
27+
Should Be Equal ${SUITE.doc} Leading space is ignored
2828
Should Be Equal ${SUITE.metadata['No']} Spaces

‎atest/robot/cli/rebot/suite_name_doc_and_metadata.robot‎

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,47 @@ Resource rebot_cli_resource.robot
55
Default Name, Doc & Metadata
66
[Documentation] Using default values (read from xml) for name, doc and metadata.
77
Run Rebot ${EMPTY} ${INPUT FILE}
8-
Check Names ${SUITE} Normal
9-
Check Names ${SUITE.tests[0]} First One Normal.
10-
Check Names ${SUITE.tests[1]} Second One Normal.
8+
Check All Names ${SUITE} Normal
119
Should Be Equal ${SUITE.doc} Normal test cases
1210
Should Be Equal ${SUITE.metadata['Something']} My Value
1311

1412
Overriding Name, Doc & Metadata And Escaping
1513
[Documentation] Overriding name, doc and metadata. Also tests escaping values.
1614
${options} = Catenate
1715
... -N this_is_overridden_next
18-
... --name "my COOL Name!!"
16+
... --name "my COOL Name.!!."
1917
... --doc "Even \\cooooler\\ doc!?"
2018
... --metadata something:New
2119
... --metadata "two parts:three parts here"
2220
... -M path:c:\\temp\\new.txt
2321
... -M esc:*?$&#!!
2422
Run Rebot ${options} ${INPUT FILE}
25-
Check Names ${SUITE} my COOL Name!!
26-
Check Names ${SUITE.tests[0]} First One my COOL Name!!.
27-
Check Names ${SUITE.tests[1]} Second One my COOL Name!!.
23+
Check All Names ${SUITE} my COOL Name.!!.
2824
Should Be Equal ${SUITE.doc} Even \\cooooler\\ doc!?
2925
Should Be Equal ${SUITE.metadata['Something']} New
3026
Should Be Equal ${SUITE.metadata['two parts']} three parts here
3127
Should Be Equal ${SUITE.metadata['path']} c:\\temp\\new.txt
3228
Should Be Equal ${SUITE.metadata['esc']} *?$&#!!
29+
30+
Documentation and metadata from external file
31+
${path} = Normalize Path ${DATADIR}/cli/runner/doc.txt
32+
${value} = Get File ${path}
33+
Run Rebot --doc ${path} --metadata name:${path} ${INPUT FILE}
34+
Check All Names ${SUITE} Normal
35+
Should Be Equal ${SUITE.doc} ${value.rstrip()}
36+
Should Be Equal ${SUITE.metadata['name']} ${value.rstrip()}
37+
Run Rebot --doc " ${path}" --metadata "name: ${path}" ${INPUT FILE}
38+
Check All Names ${SUITE} Normal
39+
Should Be Equal ${SUITE.doc} ${path}
40+
Should Be Equal ${SUITE.metadata['name']} ${path}
41+
42+
Invalid external file
43+
Run Rebot Without Processing Output --doc . ${INPUT FILE}
44+
Stderr Should Match [[] ERROR []] Reading documentation from an external file failed: *${USAGE TIP}\n
45+
46+
*** Keywords ***
47+
Check All Names
48+
[Arguments] ${suite} ${name}
49+
Check Names ${suite} ${name}
50+
Check Names ${suite.tests[0]} First One ${name}.
51+
Check Names ${suite.tests[1]} Second One ${name}.

‎atest/robot/cli/runner/suite_name_doc_and_metadata.robot‎

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@ Resource cli_resource.robot
33

44
*** Test Cases ***
55
Default Name, Doc & Metadata
6-
Run tests ${EMPTY} ${TESTFILE}
7-
Check Names ${SUITE} Normal
8-
Check Names ${SUITE.tests[0]} First One Normal.
9-
Check Names ${SUITE.tests[1]} Second One Normal.
6+
Run Tests ${EMPTY} ${TESTFILE}
7+
Check All Names ${SUITE} Normal
108
Should Be Equal ${SUITE.doc} Normal test cases
119
Should Be Equal ${SUITE.metadata['Something']} My Value
1210

@@ -21,13 +19,34 @@ Overriding Name, Doc & Metadata And Escaping
2119
... -M path:c:\\temp\\new.txt
2220
... -M esc:*?$&#!!
2321
Run Tests ${options} ${TESTFILE}
24-
Check Names ${SUITE} my COOL Name.!!.
25-
Check Names ${SUITE.tests[0]} First One my COOL Name.!!..
26-
Check Names ${SUITE.tests[1]} Second One my COOL Name.!!..
22+
Check All Names ${SUITE} my COOL Name.!!.
2723
Should Be Equal ${SUITE.doc} Even \\cooooler\\ doc!?
2824
Should Be Equal ${SUITE.metadata['Something']} new
2925
Should Be Equal ${SUITE.metadata['Two Parts']} three part VALUE
3026
Should Be Equal ${SUITE.metadata['path']} c:\\temp\\new.txt
3127
Should Be Equal ${SUITE.metadata['esc']} *?$&#!!
3228
File Should Contain ${OUTDIR}/log.html Something
3329
File Should Not Contain ${OUTDIR}/log.html something
30+
31+
Documentation and metadata from external file
32+
${path} = Normalize Path ${DATADIR}/cli/runner/doc.txt
33+
${value} = Get File ${path}
34+
Run Tests --doc ${path} --metadata name:${path} ${TEST FILE}
35+
Check All Names ${SUITE} Normal
36+
Should Be Equal ${SUITE.doc} ${value.rstrip()}
37+
Should Be Equal ${SUITE.metadata['name']} ${value.rstrip()}
38+
Run Tests --doc " ${path}" --metadata "name: ${path}" ${TEST FILE}
39+
Check All Names ${SUITE} Normal
40+
Should Be Equal ${SUITE.doc} ${path}
41+
Should Be Equal ${SUITE.metadata['name']} ${path}
42+
43+
Invalid external file
44+
Run Tests Without Processing Output --doc . ${TEST FILE}
45+
Stderr Should Match [[] ERROR []] Reading documentation from an external file failed: *${USAGE TIP}\n
46+
47+
*** Keywords ***
48+
Check All Names
49+
[Arguments] ${suite} ${name}
50+
Check Names ${suite} ${name}
51+
Check Names ${suite.tests[0]} First One ${name}.
52+
Check Names ${suite.tests[1]} Second One ${name}.

‎doc/userguide/src/ExecutingTestCases/ConfiguringExecution.rst‎

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,22 @@ Setting the documentation
235235

236236
In addition to `defining documentation in the test data`__, documentation
237237
of the top-level suite can be given from the command line with the
238-
option :option:`--doc (-D)` The value can contain simple `HTML formatting`_.
238+
option :option:`--doc (-D)`. The value can contain simple `HTML formatting`_
239+
and must be quoted if it contains spaces.
239240

240-
.. note:: Prior to Robot Framework 3.1, underscores in the value were
241+
If the given documentation is a relative or absolute path pointing to an existing
242+
file, the actual documentation will be read from that file. This is especially
243+
convenient if the externally specified documentation is long or contains multiple
244+
lines.
245+
246+
Examples::
247+
248+
robot --doc "Example documentation" tests.robot
249+
robot --doc doc.txt tests.robot # Documentation read from doc.txt if it exits.
250+
251+
.. note:: Reading documentation from an external file is new in Robot Framework 4.1.
252+
253+
Prior to Robot Framework 3.1, underscores in documentation were
241254
converted to spaces same way as with the :option:`--name` option.
242255

243256
__ `Test suite name and documentation`_
@@ -248,10 +261,26 @@ Setting free metadata
248261
`Free test suite metadata`_ may also be given from the command line with the
249262
option :option:`--metadata (-M)`. The argument must be in the format
250263
`name:value`, where `name` the name of the metadata to set and
251-
`value` is its value. The value can contain simple `HTML formatting`_.
264+
`value` is its value. The value can contain simple `HTML formatting`_ and
265+
the whole argument must be quoted if it contains spaces.
252266
This option may be used several times to set multiple metadata values.
253267

254-
.. note:: Prior to Robot Framework 3.1, underscores in the value were
268+
If the given value is a relative or absolute path pointing to an existing
269+
file, the actual value will be read from that file. This is especially
270+
convenient if the value is long or contains multiple lines.
271+
If the value should be a path to an existing file, not read from that file,
272+
the value must be separated with a space from the `name:` part.
273+
274+
Examples::
275+
276+
robot --metadata Name:Value tests.robot
277+
robot --metadata "Another Name:Another value, now with spaces" tests.robot
278+
robot --metadata "Read From File:meta.txt" tests.robot # Value read from meta.txt if it exists.
279+
robot --metadata "Path As Value: meta.txt" tests.robot # Value always used as-is.
280+
281+
.. note:: Reading metadata value from an external file is new in Robot Framework 4.1.
282+
283+
Prior to Robot Framework 3.1, underscores in the value were
255284
converted to spaces same way as with the :option:`--name` option.
256285

257286
Setting tags

‎src/robot/conf/settings.py‎

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,11 @@ def _process_value(self, name, value):
104104
if value == self._get_default_value(name):
105105
return value
106106
if name == 'Doc':
107-
return self._escape_as_data(value)
108-
if name in ['Metadata', 'TagDoc']:
109-
if name == 'Metadata':
110-
value = [self._escape_as_data(v) for v in value]
111-
return [self._process_metadata_or_tagdoc(v) for v in value]
107+
return self._process_doc(value)
108+
if name == 'Metadata':
109+
return [self._process_metadata(v) for v in value]
110+
if name == 'TagDoc':
111+
return [self._process_tagdoc(v) for v in value]
112112
if name in ['Include', 'Exclude']:
113113
return [self._format_tag_patterns(v) for v in value]
114114
if name in self._output_opts and (not value or value.upper() == 'NONE'):
@@ -139,7 +139,17 @@ def _process_value(self, name, value):
139139
return tuple(ext.lower().lstrip('.') for ext in value.split(':'))
140140
return value
141141

142-
def _escape_as_data(self, value):
142+
def _process_doc(self, value):
143+
if os.path.exists(value):
144+
try:
145+
with open(value) as f:
146+
value = f.read()
147+
except (OSError, IOError) as err:
148+
raise DataError('Reading documentation from an external file failed: %s'
149+
% err)
150+
return self._escape_doc(value).strip()
151+
152+
def _escape_doc(self, value):
143153
return value
144154

145155
def _process_log_level(self, level):
@@ -235,11 +245,18 @@ def _get_output_extension(self, ext, type_):
235245
return '.txt'
236246
raise FrameworkError("Invalid output file type: %s" % type_)
237247

238-
def _process_metadata_or_tagdoc(self, value):
248+
def _process_metadata(self, value):
249+
name, value = self._split_from_colon(value)
250+
return name, self._process_doc(value)
251+
252+
def _split_from_colon(self, value):
239253
if ':' in value:
240254
return value.split(':', 1)
241255
return value, ''
242256

257+
def _process_tagdoc(self, value):
258+
return self._split_from_colon(value)
259+
243260
def _process_report_background(self, colors):
244261
if colors.count(':') not in [1, 2]:
245262
raise DataError("Invalid report background colors '%s'." % colors)
@@ -429,7 +446,7 @@ def get_rebot_settings(self):
429446
def _output_disabled(self):
430447
return self.output is None
431448

432-
def _escape_as_data(self, value):
449+
def _escape_doc(self, value):
433450
return escape(value)
434451

435452
@property

‎src/robot/rebot.py‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,13 @@
9292
-D --doc documentation Set the documentation of the top level suite.
9393
Simple formatting is supported (e.g. *bold*). If
9494
the documentation contains spaces, it must be quoted.
95-
Example: --doc "Very *good* example"
95+
If the value is path to an existing file, actual
96+
documentation is read from that file.
97+
Examples: --doc "Very *good* example"
98+
--doc doc_from_file.txt
9699
-M --metadata name:value * Set metadata of the top level suite. Value can
97-
contain formatting similarly as --doc.
98-
Example: --metadata Version:1.2
100+
contain formatting and be read from a file similarly
101+
as --doc. Example: --metadata Version:1.2
99102
-G --settag tag * Sets given tag(s) to all tests.
100103
-t --test name * Select tests by name or by long name containing also
101104
parent suite name like `Parent.Test`. Name is case

‎src/robot/run.py‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,13 @@
105105
-D --doc documentation Set the documentation of the top level suite.
106106
Simple formatting is supported (e.g. *bold*). If the
107107
documentation contains spaces, it must be quoted.
108-
Example: --doc "Very *good* example"
108+
If the value is path to an existing file, actual
109+
documentation is read from that file.
110+
Examples: --doc "Very *good* example"
111+
--doc doc_from_file.txt
109112
-M --metadata name:value * Set metadata of the top level suite. Value can
110-
contain formatting similarly as --doc.
111-
Example: --metadata Version:1.2
113+
contain formatting and be read from a file similarly
114+
as --doc. Example: --metadata Version:1.2
112115
-G --settag tag * Sets given tag(s) to all executed tests.
113116
-t --test name * Select tests by name or by long name containing also
114117
parent suite name like `Parent.Test`. Name is case

0 commit comments

Comments
 (0)