5.1 Library documentation tool (libdoc)
- 5.1.1 General usage
- 5.1.2 Writing documentation
- 5.1.3 Documentation syntax
- 5.1.4 Internal linking
- 5.1.5 Representing arguments
- 5.1.6 Libdoc example
Libdoc is a tool for generating keyword documentation for test libraries and resource files in HTML and XML formats. The former format is suitable for humans and the latter for RIDE and other tools. Libdoc also has few special commands to show library or resource information on the console.
Documentation can be created for:
- test libraries implemented with Python or Java using the normal static library API,
- test libraries using the dynamic API, including remote libraries, and
- resource files.
Additionally it is possible to use XML spec created by Libdoc earlier as an input.
Libdoc is built-in into Robot Framework and automatically included in the installation starting from version 2.7. With earlier versions you need to download libdoc.py script separately. The command line usage has changed slightly between these versions but the documentation syntax is still the same.
5.1.1 General usage
Synopsis
python -m robot.libdoc [options] library_or_resource output_file
python -m robot.libdoc [options] library_or_resource list|show|version [names]
Options
-f, --format <html | xml> | ||
---|---|---|---|
Specifies whether to generate HTML or XML output. If this options is not used, the format is got from the extension of the output file. | |||
-F, --docformat <robot | html | text | rest> |
Specifies the source documentation format. Possible values are Robot Framework's documentation format, HTML, plain text, and reStructuredText. Default value can be specified in test library source code and the initial default value is robot. New in Robot Framework 2.7.5. | |||
-N, --name <newname> | |||
Sets the name of the documented library or resource. | |||
-V, --version <newversion> | |||
Sets the version of the documented library or resource. The default value for test libraries is got from the source code. | |||
-P, --pythonpath <path> | |||
Additional locations where to search for libraries and resources similarly as when running tests. | |||
-E, --escape <what:with> | |||
Escapes characters which are problematic in console. what is the name of the character to escape and with is the string to escape it with. Available escapes are listed in the --help output. | |||
-h,--help | Prints this help. |
Alternative execution
Although Libdoc is used only with Python in the synopsis above, it works also with Jython and IronPython. When documenting Java libraries, Jython is actually required.
In the synopsis Libdoc is executed as an installed module (python -m robot.libdoc). In addition to that, it can be run also as a script:
python path/robot/libdoc.py [options] arguments
Executing as a script can be useful if you have done manual installation or otherwise just have the robot directory with the source code somewhere in your system.
Specifying library or resource file
Python libraries and dynamic libraries with name or path
When documenting libraries implemented with Python or that use the dynamic library API, it is possible to specify the library either by using just the library name or path to the library source code. In the former case the library is searched using the library search path and its name must be in the same format as in Robot Framework test data.
If these libraries require arguments when they are imported, the arguments must be catenated with the library name or path using two colons like MyLibrary::arg1::arg2. If arguments change what keywords the library provides or otherwise alter its documentation, it might be a good idea to use--name option to also change the library name accordingly.
Java libraries with path
A Java test library implemented using the static library API can be specified by giving the path to the source code file containing the library implementation. Additionally, tools.jar, which is part of the Java JDK distribution, must be found from CLASSPATH when Libdoc is executed. Notice that generating documentation for Java libraries works only with Jython.
Resource files with path
Resource files must always be specified using a path. If the path does not exist, resource files are also searched from all directories in PYTHONPATH similarly as when executing test cases.
Generating documentation
When generating documentation in HTML or XML format, the output file must be specified as the second argument after the library/resource name or path. Output format is got automatically from the extension but can also be set using the --format option.
Examples:
python -m robot.libdoc OperatingSystem OperatingSystem.html
python -m robot.libdoc --name MyLibrary Remote::http://10.0.0.42:8270 MyLibrary.xml
python -m robot.libdoc test/resource.html doc/resource_doc.html
jython -m robot.libdoc --version 1.0 MyJavaLibrary.java MyJavaLibrary.html
jython -m robot.libdoc my.organization.DynamicJavaLibrary my.organization.DynamicJavaLibrary.xml
Viewing information on console
Libdoc has three special commands to show information on the console. These commands are used instead of the name of the output file, and they can also take additional arguments.
list
List names of the keywords the library/resource contains. Can be limited to show only certain keywords by passing optional patterns as arguments. Keyword is listed if its name contains given pattern.
show
Show library/resource documentation. Can be limited to show only certain keywords by passing names as arguments. Keyword is shown if its name matches any given name. Special argument intro will show only the library introduction and importing sections.
version
Show library version
Optional patterns given to list and show are case and space insensitive. Both also accept * and ? as wildcards.
Examples:
python -m robot.libdoc Dialogs list
python -m robot.libdoc Selenium2Library list browser
python -m robot.libdoc Remote::10.0.0.42:8270 show
python -m robot.libdoc Dialogs show PauseExecution execute*
python -m robot.libdoc Selenium2Library show intro
python -m robot.libdoc Selenium2Library version
5.1.2 Writing documentation
This section discusses writing documentation for Python and Java based test libraries that use the static library API as well as for dynamic libraries and resource files. Creating test libraries and resource files is described in more details elsewhere in the User Guide.
Python libraries
The documentation for Python libraries that use the static library API is written simply as doc strings for the library class or module and for methods implementing keywords. The first line of the method documentation is considered as a short documentation for the keyword (used, for example, as a tool tip in links in the generated HTML documentation), and it should thus be as describing as possible, but not too long.
The simple example below illustrates how to write the documentation in general, and there is a bit longer example at the end of this chapter containing also an example of the generated documentation.
class ExampleLib:
"""Library for demo purposes.
This library is only used in an example and it doesn't do anything useful.
"""
def my_keyword(self):
"""Does nothing."""
pass
def your_keyword(self, arg):
"""Takes one argument and does nothing with it.
Example:
| Your Keyword | xxx |
| Your Keyword | yyy |
"""
pass
Tip
If you want to use non-ASCII charactes in the documentation of Python libraries, you must either use UTF-8 as your source code encoding or create docstrings as Unicode.
For more information on Python documentation strings, see PEP-257.
Java libraries
Documentation for Java libraries that use the static library API is written as normal Javadoc comments for the library class and methods. In this case Libdoc actually uses the Javadoc tool internally, and thus tools.jar containing it must be in CLASSPATH. This jar file is part of the normal Java SDK distribution and ought to be found from bin directory under the Java SDK installation.
The following simple example has exactly same documentation (and functionality) than the earlier Python example.
/**
* Library for demo purposes.
* This library is only used in an example and it doesn't do anything useful.
*/
public class ExampleLib {
/**
* Does nothing.
*/
public void myKeyword() {
}
/**
Takes one argument and does nothing* with it.
* Example:
* | Your Keyword | xxx |
* | Your Keyword | yyy |
*/
public void yourKeyword(String arg) {
}
}
Dynamic libraries
To be able to generate meaningful documentation for dynamic libraries, the libraries must return keyword argument names and documentation using getkeywordarguments and getkeyworddocumentation methods (or using their camelCase variants getKeywordArguments andgetKeywordDocumentation). Libraries can also support general library documentation via special __intro and __init values to the get_keyword_documentation method.
See the Dynamic library API section for more information about how to create these methods.
Importing section
A separate section about how the library is imported is created based on its initialization methods. For a Python library, if it has an init method that takes arguments in addition to self, its documentation and arguments are shown. For a Java library, if it has a public constructor that accepts arguments, all its public constructors are shown.
class TestLibrary:
def init(self, mode='default')
"""Creates new TestLibrary. mode
argument is used to determine mode."""
self.mode = mode
def some_keyword(self, arg):
"""Does something based on given arg
.
What is done depends on the mode
specified when importing
the library.
"""
if self.mode == 'secret':
# ...
Resource file documentation
Keywords in resource files can have documentation using [Documentation] setting, and this documentation is also used by Libdoc. First line of the documentation (until the first implicit newline or explicit \n) is considered to be the short documentation similarly as with test libraries.
Also the resource file itself can have Documentation in the Setting table for documenting the whole resource file.
Possible variables in resource files are not documented.
An example resource file | ||
---|---|---|
Setting | Value | Value |
Documentation | Resource file for demo purposes. | |
... | This resource is only used in an example | and it doesn't do anything useful. |
Keyword | Action | Argument | Argument |
---|---|---|---|
My Keyword | [Documentation] | Does nothing | |
No Operation | |||
Your Keyword | [Arguments] | ${arg} | |
[Documentation] | Takes one argument and does nothing with it.\n | Example:\n | |
No Operation |
5.1.3 Documentation syntax
Libdoc supports documentation in Robot Framework's own documentation syntax, HTML, plain text, and reStructuredText. The format to use can be specified in test library source code using ROBOT_LIBRARY_DOC_FORMAT attribute or given from the command line using --docformat (-F) option. In both cases the possible case-insensitive values are ROBOT (default), HTML, TEXT and reST.
Robot Framework's own documentation format is the default and generally recommended format. Other formats are especially useful when using existing code with existing documentation in test libraries. Support for other formats was added in Robot Framework 2.7.5.
Robot Framework documentation syntax
Most important features in Robot Framework's documentation syntax are formatting using bold and italic, custom links and automatic conversion of URLs to links, and the possibility to create tables and pre-formatted text blocks (useful for examples) simply with pipe character. If documentation gets longer, support for section titles (new in Robot Framework 2.7.5) can also be handy.
Some of the most important formatting features are illustrated in the example below. Notice that since this is the default format, there is no need to use ROBOT_LIBRARY_DOC_FORMAT attribute nor give the format from the command line.
"""Example library in Robot Framework format.
- Formatting with bold and _italic._
- URLs like http://example.com are turned to links.
- Custom links like [http://robotframework.org|Robot Framework] are supported.
- Linking to My Keyword
works.
"""
def my_keyword():
"""Nothing more to see here."""
HTML documentation syntax
When using HTML format, you can create documentation pretty much freely using any syntax. The main drawback is that HTML markup is not that human friendly, and that can make the documentation in the source code hard to maintain and read. Documentation in HTML format is used by Libdoc directly without any transformation or escaping. The special syntax for linking to keywords using syntax like My Keyword
is supported, however.
Example below contains the same formatting examples as the previous example. Now ROBOT_LIBRARY_DOC_FORMAT attribute must be used or format given on the command line like --docformat HTML.
"""Example library in HTML format.
<ul>
<li>Formatting with <b>bold</b> and <i>italic</i>.
<li>URLs are not turned to links automatically.
<li>Custom links like <a href="http://www.w3.org/html">HTML</a> are supported.
<li>Linking to My Keyword
works.
</ul>
"""
ROBOT_LIBRARY_DOC_FORMAT = 'HTML'
def my_keyword():
"""Nothing more to see here."""
Plain text documentation syntax
When the plain text format is used, Libdoc uses the documentation as-is. Newlines and other whitespace are preserved except for indentation, and HTML special characters (<>&) escaped. The only formatting done is turning URLs into clickable links and supporting internal linking like My Keyword
.
"""Example library in plain text format.
- Formatting is not supported.
- URLs like http://example.com are turned to links.
- Custom links are not supported.
- Linking to My Keyword
works.
"""
ROBOT_LIBRARY_DOC_FORMAT = 'text'
def my_keyword():
"""Nothing more to see here"""
reStructuredText documentation syntax
reStructuredText is simple yet powerful markup syntax used widely in Python projects (including this User Guide) and elsewhere. The main limitation is that you need to have the docutils module installed to be able to generate documentation using it. Because backtick characters have special meaning in reStructuredText, linking to keywords requires them to be escaped like `My Keyword`.
"""Example library in reStructuredText format.
- Formatting with bold and italic.
- URLs like http://example.com are turned to links.
- Custom links like reStructuredText__ are supported.
- Linking to `My Keyword` works but requires backtics to be escaped.
__ http://docutils.sourceforge.net
"""
ROBOT_LIBRARY_DOC_FORMAT = 'reST'
def my_keyword():
"""Nothing more to see here"""
5.1.4 Internal linking
Libdoc supports internal linking to keywords and different sections in the documentation. Linking is done by surrounding the target name with backtick characters like target
. Target names are case-insensitive and possible targets are explained in the subsequent sections.
There is no error or warning if a link target is not found, but instead Libdoc just formats the text in italics. Earlier this formatting was recommended to be used when referring to keyword arguments, but that was problematic because it could accidentally create internal links. Nowadays it is recommended to use inline code style with double backticks like argument
instead. The old formatting of single backticks may even be removed in the future in favor of giving an error when a link target is not found.
In addition to the examples in the following sections, internal linking and argument formatting is shown also in the longer example at the end of this chapter.
Linking to keywords
All keywords the library have automatically create link targets and they can be linked using syntax Keyword Name
. This is illustrated with the example below where both keywords have links to each others.
def keyword(log_level="INFO"):
"""Does something and logs the output using the given level.
Valid values for log level` are "INFO" (default) "DEBUG" and "TRACE".
See also Another Keyword
.
"""
# ...
def another_keyword(argument, log_level="INFO"):
"""Does something with the given argument else and logs the output.
See Keyword
for information about valid log levels.
"""
# ...
Note
When using reStructuredText documentation syntax, backticks must be escaped like `Keyword Name`.
Linking to automatic sections
The documentation generated by Libdoc always contains sections for overall library introduction, shortcuts to keywords, and for actual keywords. If a library itself takes arguments, there is also separate importing section.
All these sections act as targets that can be linked, and the possible target names are listed in the table below. Using these targets is shown in the example of the next section.
Automatic section link targets | |
---|---|
Section | Target |
Introduction | introduction and library introduction |
Importing | importing and library importing |
Shortcuts | shortcuts (New in Robot Framework 2.7.5.) |
Keywords | keywords (New in Robot Framework 2.7.5.) |
Linking to custom sections
Starting from version 2.7.5, Robot Framework's documentation syntax supports custom section titles, and the titles used in the library or resource file introduction automatically create link targets. The example below illustrates linking both to automatic and custom sections:
"""Library for libdoc demonstration purposes.
This library does not do anything useful.
= My section =
We do have a custom section in the documentation, though.
"""
def keyword():
"""Does nothing.
See introduction
for more information and My section
to test how
linking to custom sections works.
"""
pass
Note
Linking to custom sections works only when using Robot Framework documentation syntax.
Note
Prior to Robot Framework 2.8, only the first level section titles were linkable.
5.1.5 Representing arguments
Libdoc handles keywords' arguments automatically so that arguments specified for methods in libraries or user keywords in resource files are listed in a separate column. User keyword arguments are shown without ${} or @{} to make arguments look the same regardless where keywords originated from.
Regardless how keywords are actually implemented, Libdoc shows arguments similarly as when creating keywords in Python. This formatting is explained more thoroughly in the table below.
How Libdoc represents arguments | ||
---|---|---|
Arguments | Now represented | Examples |
No arguments | Empty column. | |
One or more argument | List of strings containing argument names. | one_argument |
Default values for arguments | Default values separated from names with =. | arg=default value |
Variable number of arguments (varargs) | Last (or second last with kwargs) argument has * before its name. | *varargs |
Free keyword arguments (kwargs) | Last arguments has ** before its name. | **kwargs |
When referring to arguments in keyword documentation, it is recommended to use inline code style like argument
.
5.1.6 Libdoc example
The following example illustrates how to use the most important documentation formatting possibilities, internal linking, and so on. Click here to see how the generated documentation looks like.
class LoggingLibrary:
"""Library for logging messages.
= Table of contents =
- Usage
- Valid log levels
- Examples
- Importing
- Shortcuts
- Keywords
= Usage =
This library has several keyword, for example Log Message
, for logging
messages. In reality the library is used only for _Libdoc demonstration_
purposes.
= Valid log levels =
Valid log levels are INFO
, DEBUG
, and TRACE
. The default log
level can be set during importing
.
= Examples =
Notice how keywords are linked from examples.
| Log Message
| My message | | |
| Log Two Messages
| My message | Second message | level=DEBUG |
| Log Messages
| First message | Second message | Third message |
"""
ROBOT_LIBRARY_VERSION = '0.1'
def init(self, default_level='INFO'):
"""The default log level can be given at library import time.
See Valid log levels
section for information about available log
levels.
Examples:
| =Setting= | =Value= | =Value= | =Comment= |
| Library | LoggingLibrary | | # Use default level (INFO) |
| Library | LoggingLibrary | DEBUG | # Use the given level |
"""
self.default_level = self._verify_level(default_level)
def _verify_level(self, level):
level = level.upper()
if level not in ['INFO', 'DEBUG', 'TRACE']:
raise RuntimeError("Invalid log level'%s'. Valid levels are "
"'INFO', 'DEBUG', and 'TRACE'")
return level
def log_message(self, message, level=None):
"""Writes given message to the log file using the specified log level.
The message to log and the log level to use are defined using
message
and level
arguments, respectively.
If no log level is given, the default level given during `library
importing` is used.
"""
level = self._verify_level(level) if level else self.default_level
print "%s %s" % (level, message)
def log_two_messages(self, message1, message2, level=None):
"""Writes given messages to the log file using the specified log level.
See Log Message
keyword for more information.
"""
self.log_message(message1, level)
self.log_message(message2, level)
def log_messages(self, *messages):
"""Logs given messages using the log level set during importing
.
See also Log Message
and Log Two Messages
.
"""
for msg in messages:
self.log_message(msg)
All standard libraries have documentation generated by Libdoc and their documentation (and source code) act as a more realistic examples.