38 if 'robot' not in sys.modules
and __name__ ==
'__main__':
39 import pythonpathsetter
42 from robot.htmldata import HtmlFileWriter, ModelWriter, JsonWriter, TESTDOC
44 from robot.utils import (abspath, Application, file_writer, get_link_path,
45 html_escape, html_format, is_string, secs_to_timestr,
46 seq2str2, timestr_to_secs, unescape)
49 USAGE =
"""robot.testdoc -- Robot Framework test data documentation tool
53 Usage: python -m robot.testdoc [options] data_sources output_file
55 Testdoc generates a high level test documentation based on Robot Framework
56 test data. Generated documentation includes name, documentation and other
57 metadata of each test suite and test case, as well as the top-level keywords
63 -T --title title Set the title of the generated documentation.
64 Underscores in the title are converted to spaces.
65 The default title is the name of the top level suite.
66 -N --name name Override the name of the top level suite.
67 -D --doc document Override the documentation of the top level suite.
68 -M --metadata name:value * Set/override metadata of the top level suite.
69 -G --settag tag * Set given tag(s) to all test cases.
70 -t --test name * Include tests by name.
71 -s --suite name * Include suites by name.
72 -i --include tag * Include tests by tags.
73 -e --exclude tag * Exclude tests by tags.
74 -A --argumentfile path * Text file to read more arguments from. Use special
75 path `STDIN` to read contents from the standard input
76 stream. File can have both options and data sources
77 one per line. Contents do not need to be escaped but
78 spaces in the beginning and end of lines are removed.
79 Empty lines and lines starting with a hash character
83 | # This is a comment line
87 --argumentfile argfile.txt --argumentfile STDIN
88 -h -? --help Print this help.
90 All options except --title have exactly same semantics as same options have
91 when executing test cases.
96 Data can be given as a single file, directory, or as multiple files and
97 directories. In all these cases, the last argument must be the file where
98 to write the output. The output is always created in HTML format.
100 Testdoc works with all interpreters supported by Robot Framework.
101 It can be executed as an installed module like
102 `python -m robot.testdoc` or as a script like `python path/robot/testdoc.py`.
106 python -m robot.testdoc my_test.robot testdoc.html
107 python path/to/robot/testdoc.py first_suite.txt second_suite.txt output.html
109 For more information about Testdoc and other built-in tools, see
110 http://robotframework.org/robotframework/#built-in-tools.
117 Application.__init__(self, USAGE, arg_limits=(2,))
119 def main(self, datasources, title=None, **options):
120 outfile =
abspath(datasources.pop())
123 self.console(outfile)
126 with file_writer(outfile, usage=
'Testdoc output')
as output:
134 datasources = [datasources]
135 suite = TestSuiteBuilder(process_curdir=
False).build(*datasources)
136 suite.configure(**settings.suite_config)
146 self.
_title_title = title.replace(
'_',
' ')
if title
else suite.name
149 self.
_output_output.
write(
'<script type="text/javascript">\n')
156 'title': self.
_title_title,
157 'generated': int(time.time() * 1000)
172 'source': suite.source
or '',
175 'name': self.
_escape_escape(suite.name),
176 'fullName': self.
_escape_escape(suite.longname),
177 'doc': self.
_html_html(suite.doc),
178 'metadata': [(self.
_escape_escape(name), self.
_html_html(value))
179 for name, value
in suite.metadata.items()],
180 'numberOfTests': suite.test_count ,
183 'keywords': list(self.
_convert_keywords_convert_keywords((suite.setup, suite.teardown)))
198 return [self.
_convert_suite_convert_suite(s)
for s
in suite.suites]
201 return [self.
_convert_test_convert_test(t)
for t
in suite.tests]
205 test.body.insert(0, test.setup)
207 test.body.append(test.teardown)
209 'name': self.
_escape_escape(test.name),
210 'fullName': self.
_escape_escape(test.longname),
212 'doc': self.
_html_html(test.doc),
213 'tags': [self.
_escape_escape(t)
for t
in test.tags],
222 if kw.type == kw.SETUP:
224 elif kw.type == kw.TEARDOWN:
226 elif kw.type == kw.FOR:
228 elif kw.type == kw.WHILE:
230 elif kw.type == kw.IF_ELSE_ROOT:
232 elif kw.type == kw.TRY_EXCEPT_ROOT:
238 name =
'%s %s %s' % (
', '.join(data.variables), data.flavor,
240 return {
'type':
'FOR',
'name': self.
_escape_escape(name),
'arguments':
''}
243 return {
'type':
'WHILE',
'name': self.
_escape_escape(data.condition),
'arguments':
''}
246 for branch
in data.body:
247 yield {
'type': branch.type,
248 'name': self.
_escape_escape(branch.condition
or ''),
252 for branch
in data.body:
253 if branch.type == branch.EXCEPT:
254 patterns =
', '.join(branch.patterns)
255 as_var = f
'AS {branch.variable}' if branch.variable
else ''
256 name = f
'{patterns} {as_var}'.strip()
259 yield {
'type': branch.type,
'name': name,
'arguments':
''}
265 'arguments': self.
_escape_escape(
', '.join(kw.args))
270 return '%s = %s' % (
', '.join(a.rstrip(
'= ')
for a
in kw.assign), kw.name)
298 TestDoc().execute_cli(arguments)
313 TestDoc().execute(*arguments, **options)
316 if __name__ ==
'__main__':
def _convert_suites(self, suite)
def _convert_if(self, data)
def _convert_suite(self, suite)
def _get_relative_source(self, source)
def _convert_while(self, data)
def _get_timeout(self, timeout)
def _convert_try(self, data)
def __init__(self, output_path=None)
def _convert_test(self, test)
def _convert_tests(self, suite)
def _get_kw_name(self, kw)
def _convert_keyword(self, kw, kw_type)
def _convert_for(self, data)
def _convert_keywords(self, keywords)
def _write_test_doc(self, suite, outfile, title)
def main(self, datasources, title=None, **options)
def __init__(self, output, suite, title=None)
def write(msg, level='INFO', html=False)
Writes the message to the log file using the given level.
def testdoc_cli(arguments)
Executes Testdoc similarly as from the command line.
def testdoc(*arguments, **options)
Executes Testdoc programmatically.
def TestSuiteFactory(datasources, **options)
def html_escape(text, linkify=True)
def seq2str2(sequence)
Returns sequence in format [ item 1 | item 2 | ...
def file_writer(path=None, encoding='UTF-8', newline=None, usage=None)
def abspath(path, case_normalize=False)
Replacement for os.path.abspath with some enhancements and bug fixes.
def get_link_path(target, base)
Returns a relative path to target from base.
def secs_to_timestr(secs, compact=False)
Converts time in seconds to a string representation.
def timestr_to_secs(timestr, round_to=3, accept_plain_values=True)
Parses time strings like '1h 10s', '01:00:10' and '42' and returns seconds.