<commit_before><?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" />
<title>Robot Framework Quick Start Guide</title>
<style type="text/css">

/* Robot Framework User Guide Style Sheet

   This stylesheet contains styles from restructuredText's default 
   'html4css1.css' and after that modifications needed for Robot Framework User
   Guide. These styles are added into the same file against suggestions at 
   reST's stylesheet  howto mentioned below, because we want to be able to 
   embed all styles into the created HTML file. Everything before 'Robot 
   Framework User Guide Modifications' text is from 'html4css1.css' without 
   any changes so that part can still be changed easily.
*/


/*
:Author: <NAME> (<EMAIL>)
:Id: $Id: html4css1.css 5196 2007-06-03 20:25:28Z wiemann $
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.

See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/

/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
  border: 0 }

table.borderless td, table.borderless th {
  /* Override padding for "table.docutils td" with "! important".
     The right padding separates the table cells. */
  padding: 0 0.5em 0 0 ! important }

.first {
  /* Override more specific margin styles with "! important". */
  margin-top: 0 ! important }

.last, .with-subtitle {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dl.docutils dd {
  margin-bottom: 0.5em }

/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
  font-weight: bold }
*/

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

/* Uncomment (and remove this text!) to get reduced vertical space in
   compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
  margin-bottom: 0.5em }

div.compound .compound-last, div.compound .compound-middle {
  margin-top: 0.5em }
*/

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em ;
  margin-right: 2em }

div.footer, div.header {
  clear: both;
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin: 0 0 0.5em 1em ;
  border: medium outset ;
  padding: 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
  margin-top: 0.4em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

hr.docutils {
  width: 75% }

img.align-left {
  clear: left }

img.align-right {
  clear: right }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em }

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

span.section-subtitle {
  /* font-size relative to parent (h1..h6 element) */
  font-size: 80% }

table.citation {
  border-left: solid 1px gray;
  margin-left: 1px }

table.docinfo {
  margin: 2em 4em }

table.docutils {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.footnote {
  border-left: solid 1px black;
  margin-left: 1px }

table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

table.docutils th.field-name, table.docinfo th.docinfo-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap ;
  padding-left: 0 }

h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
  font-size: 100% }

ul.auto-toc {
  list-style-type: none }


/* **************************************** *
 * Robot Framework User Guide Modifications * 
 * **************************************** */

/* Tables -- both those used with examples and those with normal tabular data */

table.example, table.tsv-example, table.messages, table.tabular {
    border: 1px solid #808080;
    border-collapse: collapse;
    empty-cell: show;
    margin: 0.5em 2em;
}
table.example caption, table.tsv-example caption, table.tabular caption {
    text-align: left;
    padding-bottom: 0.5em;
    font-style: italic;
    margin: 0.5em 2em;
}
table.example th, table.example td, table.tsv-example td {
    border: 1px solid #808080;
    font-family: arial,helvetica,sans-serif;
    font-size: 0.8em;
    padding: 0.1em 0.3em;
    height: 1.2em;
}
table.example th {
    background: #E0E0E0;
}
table.tabular th, table.tabular td {
    border: 1px solid black;
    font-size: 0.9em;
    padding: 0.1em 0.3em;
    height: 1.2em;
}
table.messages {
    border: none;
    font-family: monospace;
}
table.messages td {
    vertical-align: top;
}
table.messages td.time {
    width: 6em;
    letter-spacing: -0.05em;
} 
table.messages td.level {
    width: 4em;
    text-align: center;
}


/* Roles -- these are defined in roles.txt file */

.var {
    background: #f4f4f4;
}
.opt {
    font-style: italic;
}
.prog, .code, .cli {
    background: #f4f4f4;
    font-family: monospace;
}
.msg {
    font-family: monospace;
}
.name {  
    font-style: italic;
}
.path {
    font-style: italic;
}
.misc, .literal {
    background: #f4f4f4;
}


/* Overridden and modified styles */

div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
  border: 2px solid gray;
}
pre.literal-block, pre.doctest-block {
    background: #f4f4f4;
}


/* Pygments 

- Styles generated using "HtmlFormatter().get_style_defs('.highlight')"
- Changed only background from f8f8f8 to f4f4f4 and added margin
- For more details see e.g. http://pygments.org/docs/quickstart/
*/

.highlight  { background: #f4f4f4; margin: 1em 2em; }
.highlight .c { color: #408080; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #008000; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #808080 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.highlight .kp { color: #008000 } /* Keyword.Pseudo */
.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #B00040 } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BA2121 } /* Literal.String */
.highlight .na { color: #7D9029 } /* Name.Attribute */
.highlight .nb { color: #008000 } /* Name.Builtin */
.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0000FF } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #19177C } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
.highlight .sc { color: #BA2121 } /* Literal.String.Char */
.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
.highlight .ss { color: #19177C } /* Literal.String.Symbol */
.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #19177C } /* Name.Variable.Class */
.highlight .vg { color: #19177C } /* Name.Variable.Global */
.highlight .vi { color: #19177C } /* Name.Variable.Instance */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */

</style>
</head>
<body>
<div class="document" id="robot-framework-quick-start-guide">
<h1 class="title">Robot Framework Quick Start Guide</h1>

<!-- This data file has been placed in the public domain. -->
<!-- Derived from the Unicode character mappings available from
<http://www.w3.org/2003/entities/xml/>.
Processed by unicode2rstsubs.py, part of Docutils:
<http://docutils.sourceforge.net>. -->
<!-- Roles to use in text like :rolename:`text`. Styled in userguide.css.
- var    variables
- opt    settings in setting table (e.g. Force Tags), tc/kw tables
         (e.g [Documentation]) and command line options (e.g. - -name)
- prog   program names (e.g. rebot, risto.py)
- code   programming code
- msg    test case status and message, as well as log messages and levels
- name   keyword, library, test case, test suite, etc. names
- cli    command line examples (note that options alone use opt)
- path   file names and paths
- misc   everything else (synonym to ``text``) -->
<div class="line-block">
<div class="line">Copyright © Nokia Siemens Networks 2008</div>
<div class="line">Licensed under the Apache License, Version 2.0</div>
</div>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#introduction" id="id6">Introduction</a><ul>
<li><a class="reference internal" href="#overview" id="id7">Overview</a></li>
<li><a class="reference internal" href="#installation" id="id8">Installation</a></li>
<li><a class="reference internal" href="#running-this-demo" id="id9">Running this demo</a></li>
<li><a class="reference internal" href="#introducing-the-sample-application" id="id10">Introducing the sample application</a></li>
</ul>
</li>
<li><a class="reference internal" href="#test-cases" id="id11">Test cases</a><ul>
<li><a class="reference internal" href="#first-test-cases" id="id12">First test cases</a></li>
<li><a class="reference internal" href="#higher-level-test-cases" id="id13">Higher-level test cases</a></li>
<li><a class="reference internal" href="#data-driven-test-cases" id="id14">Data-driven test cases</a></li>
</ul>
</li>
<li><a class="reference internal" href="#keywords" id="id15">Keywords</a><ul>
<li><a class="reference internal" href="#built-in-keywords" id="id16">Built-in keywords</a></li>
<li><a class="reference internal" href="#library-keywords" id="id17">Library keywords</a></li>
<li><a class="reference internal" href="#user-defined-keywords" id="id18">User-defined keywords</a></li>
</ul>
</li>
<li><a class="reference internal" href="#variables" id="id19">Variables</a><ul>
<li><a class="reference internal" href="#defining-variables" id="id20">Defining Variables</a></li>
<li><a class="reference internal" href="#using-variables" id="id21">Using variables</a></li>
</ul>
</li>
<li><a class="reference internal" href="#organizing-test-cases" id="id22">Organizing test cases</a><ul>
<li><a class="reference internal" href="#test-suites" id="id23">Test suites</a></li>
<li><a class="reference internal" href="#setup-and-teardown" id="id24">Setup and teardown</a></li>
<li><a class="reference internal" href="#using-tags" id="id25">Using tags</a></li>
</ul>
</li>
<li><a class="reference internal" href="#creating-test-libraries" id="id26">Creating test libraries</a></li>
</ul>
</div>
<div class="section" id="introduction">
<h1><a class="toc-backref" href="#id6">Introduction</a></h1>
<div class="section" id="overview">
<h2><a class="toc-backref" href="#id7">Overview</a></h2>
<p>Robot Framework is a keyword-driven test automation framework.  Test
cases live in HTML or TSV (tab-separated values) test files and make
use of keywords implemented in test libraries to drive the software
under test. Because Robot Framework is flexible and extensible, it is
ideally suited to testing complex software with a variety of
interfaces: user interfaces, command line, web services, proprietary
programming interfaces, etc.</p>
<p>Robot Framework is open source software and installation packages,
source code and further documentation is available through
<a class="reference external" href="http://robotframework.org">http://robotframework.org</a>. This guide is designed to introduce the
basic concepts of Robot Framework.  For a detailed technical
description, please refer to <a class="reference external" href="http://code.google.com/p/robotframework/wiki/UserGuide">Robot Framework User Guide</a>.</p>
</div>
<div class="section" id="installation">
<h2><a class="toc-backref" href="#id8">Installation</a></h2>
<p>A precondition for installing Robot Framework is having <a class="reference external" href="http://python.org">Python</a> installed.
In addition, to use test libraries written in Java, <a class="reference external" href="http://jython.org">Jython</a> must be
installed. To use this Quick Start Guide, Python is enough.</p>
<p>There are three different ways to install Robot Framework, of which
the most suitable can be chosen. Detailed installation instructions
can be found from the <a class="reference external" href="http://code.google.com/p/robotframework/wiki/UserGuide">user guide</a>.</p>
<ol class="arabic simple">
<li>There is a binary installer for Windows platform. It is enough to
double-click the installer and follow instructions.</li>
<li>On every platform, Robot Framework can be installed from
source. To install from source, extract the source distribution
and run command <span class="cli">python setup.py install</span>.</li>
<li>If Python package management system <a class="reference external" href="http://peak.telecommunity.com/DevCenter/EasyInstall">Easy Install</a> is available,
Robot Framework can be installed by issuing command
<span class="cli">easy_install robotframework</span>. On Windows you also need to
run <span class="path">robot_postinstall.py</span> script manually.</li>
</ol>
<p>After the framework is installed, it is useful to include the
directory containing start-up scripts in <span class="var">PATH</span> environment
variable. On UNIX-like systems this should actually happen
automatically, but on Windows this must be done from <tt class="docutils literal"><span class="pre">Control</span> <span class="pre">Panel</span> <span class="pre">&gt;</span>
<span class="pre">System</span> <span class="pre">&gt;</span> <span class="pre">Advanced</span> <span class="pre">&gt;</span> <span class="pre">Environment</span> <span class="pre">Variables</span></tt> by adding e.g.
<span class="path">C:\Python25\Scripts</span> to <span class="var">PATH</span>.</p>
<p>Successful installation can be verified with command <span class="cli">pybot
--version</span> which should output something like:</p>
<pre class="literal-block">
$ pybot --version
Robot 2.0.1 (Python 2.5.2 on linux2)
</pre>
</div>
<div class="section" id="running-this-demo">
<h2><a class="toc-backref" href="#id9">Running this demo</a></h2>
<p>This Quick Start Guide also acts as an executable demo.  To run it,
open a command shell, cd to this directory, and type the following
command at the command line:</p>
<pre class="literal-block">
pybot quickstart.html
</pre>
<p>The tests in this file will execute and generate the following reports:</p>
<dl class="docutils">
<dt><span class="path">report.html</span></dt>
<dd>the test results summary</dd>
<dt><span class="path">log.html</span></dt>
<dd>the test results details</dd>
<dt><span class="path">output.xml</span></dt>
<dd>the test results in a portable XML format for integration with other tools</dd>
</dl>
<p>Open <a class="reference external" href="report.html">report.html</a> (the link works only after this guide has been executed) in your browser, then click on the links to explore
the results. The <span class="path">report.html</span> file links to the <span class="path">log.html</span> file.</p>
<p>There are also a number of command line options that can be used to
control the test execution and generated outputs. Complete list can be
viewed by issuing <span class="cli">pybot --help</span>. For example the following
command changes the name of the log file and the name of the top level
test suite:</p>
<pre class="literal-block">
pybot --log mylog.html --name My_Fine_Tests quickstart.html
</pre>
</div>
<div class="section" id="introducing-the-sample-application">
<h2><a class="toc-backref" href="#id10">Introducing the sample application</a></h2>
<p>The sample application for this paper is a variation on a classic
login example: it is a command-line based authentication server written
in Python. At the moment, the sample application allows a user to do
three things:</p>
<ul class="simple">
<li>Create an account with a valid password.</li>
<li>Log in with a valid user name and password.</li>
<li>Change the password of an existing account.</li>
</ul>
<p>The application itself is in the <span class="path">sut</span> directory and can be
executed with a command <span class="cli">python sut/login.py</span>. Attempting to log
in with a non-existent user account or with an invalid password
results in the same error message:</p>
<pre class="literal-block">
&gt; python sut/login.py login nobody P4ssw0rd
Access Denied
</pre>
<p>After creating a user account with valid password login succeeds:</p>
<pre class="literal-block">
&gt; python sut/login.py create fred P4ssw0rd
SUCCESS

&gt; python sut/login.py login fred P4ssw0rd
Logged In
</pre>
<p>There are two requirements that a password must fulfill to be valid: it must
be between 7-12 characters long, and it must contain lower and upper case
letters and numbers, but it must not contain special characters. Trying to
create a user with invalid password fails:</p>
<pre class="literal-block">
&gt; python sut/login.py create fred short
Creating user failed: Password must be 7-12 characters long

&gt; python sut/login.py create fred invalid
Creating user failed: Password must be a combination of lowercase and
uppercase letters and numbers
</pre>
<p>Changing password with invalid credentials results in the same error message
as logging in with invalid credentials. The validity of new password is
verified and if not valid, an error message is given:</p>
<pre class="literal-block">
&gt; python sut/login.py change-password fred wrong NewP4ss
Changing password failed: Access Denied

&gt; python sut/login.py change-password fred P4ssw0rd short
Changing password failed: Password must be 7-12 characters long

&gt; python sut/login.py change-password <PASSWORD> P<PASSWORD> New<PASSWORD>
SUCCESS
</pre>
<p>The application uses a simple database file to keep track on user
statuses. The file is located in operating system dependent temporary
directory.</p>
</div>
</div>
<div class="section" id="test-cases">
<h1><a class="toc-backref" href="#id11">Test cases</a></h1>
<div class="section" id="first-test-cases">
<h2><a class="toc-backref" href="#id12">First test cases</a></h2>
<p>Robot Framework test cases are created using a simple tabular syntax. For example the following table has two tests:</p>
<blockquote>
<ul class="simple">
<li>User can create an account and log in</li>
<li>User cannot log in with bad password</li>
</ul>
</blockquote>
<table border="1" class="example docutils">
<colgroup>
<col width="38%" />
<col width="34%" />
<col width="14%" />
<col width="14%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Test Case</th>
<th class="head">Action</th>
<th class="head">Argument</th>
<th class="head">Argument</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>User can create an account and log in</td>
<td>Create Valid User</td>
<td>fred</td>
<td>P4ssw0rd</td>
</tr>
<tr><td></td>
<td>Attempt to Login with Credentials</td>
<td>fred</td>
<td>P4ssw0rd</td>
</tr>
<tr><td></td>
<td>Status Should Be</td>
<td>Logged In</td>
<td></td>
</tr>
<tr><td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr><td>User cannot log in with bad password</td>
<td>Create Valid User</td>
<td>betty</td>
<td>P4ssw0rd</td>
</tr>
<tr><td></td>
<td>Attempt to Login with Credentials</td>
<td>betty</td>
<td>wrong</td>
</tr>
<tr><td></td>
<td>Status Should Be</td>
<td>Access Denied</td>
<td></td>
</tr>
</tbody>
</table>
<p>Notice that these tests read almost like manual tests written in
English rather than like automated test cases. Robot Framework uses the
keyword-driven approach that supports writing tests that capture the
essence of the actions and expectations in natural language. Test
cases are constructed from keywords (normally in the second column) and
their possible arguments.</p>
</div>
<div class="section" id="higher-level-test-cases">
<h2><a class="toc-backref" href="#id13">Higher-level test cases</a></h2>
<p>Test cases can also be created using only high-level keywords that
take no arguments. This style allows using totally free text which is
suitable for communication even with non-technical customers or
other stakeholders. Robot Framework does not enforce any particular
style for writing test cases, and it is possible to use for example
<em>given-when-then</em> format popularized by <a class="reference external" href="http://en.wikipedia.org/wiki/Behavior_driven_development">behavior-driven development</a>
(BDD) like in the example below.</p>
<table border="1" class="example docutils">
<colgroup>
<col width="36%" />
<col width="64%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Test Case</th>
<th class="head">Steps</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>User can change password</td>
<td>Given a user has a valid account</td>
</tr>
<tr><td></td>
<td>when she changes her password</td>
</tr>
<tr><td></td>
<td>then she can log in with the new password</td>
</tr>
<tr><td></td>
<td>and she cannot use the old password anymore</td>
</tr>
</tbody>
</table>
<p>This kind of use-case or user-story-like test cases are ideally suited
for <em>acceptance test-driven development</em> (ATTD). In ATTD acceptance
tests are written before implementing actual product features and they
act also as requirements.</p>
</div>
<div class="section" id="data-driven-test-cases">
<h2><a class="toc-backref" href="#id14">Data-driven test cases</a></h2>
<p>Quite often several test cases are otherwise similar but they have
slightly different input or output data. In these situations
<em>data-driven</em> test cases, like six tests below, allow varying the test
data without duplicating the workflow.</p>
<table border="1" class="example docutils">
<colgroup>
<col width="29%" />
<col width="41%" />
<col width="11%" />
<col width="19%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Test Case</th>
<th class="head">Action</th>
<th class="head">Password</th>
<th class="head">Expected error message</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>Too short password</td>
<td>Creating user with invalid password should fail</td>
<td>abCD5</td>
<td>${PWD INVALID LENGTH}</td>
</tr>
<tr><td>Too long password</td>
<td>Creating user with invalid password should fail</td>
<td>abCD567890123</td>
<td>${PWD INVALID LENGTH}</td>
</tr>
<tr><td>Password without lowercase letters</td>
<td>Creating user with invalid password should fail</td>
<td>123DEFG</td>
<td>${PWD INVALID CONTENT}</td>
</tr>
<tr><td>Password without capital letters</td>
<td>Creating user with invalid password should fail</td>
<td>abcd56789</td>
<td>${PWD INVALID CONTENT}</td>
</tr>
<tr><td>Password without numbers</td>
<td>Creating user with invalid password should fail</td>
<td>AbCdEfGh</td>
<td>${PWD INVALID CONTENT}</td>
</tr>
<tr><td>Password with special characters</td>
<td>Creating user with invalid password should fail</td>
<td>abCD56+</td>
<td>${PWD INVALID CONTENT}</td>
</tr>
</tbody>
</table>
<p>In these tests there is only one keyword per test case, and it is
responsible for trying to create a user with the provided password and
checking that creation fails with an expected error message. Notice
that the error messages are specified using <a class="reference internal" href="#variables">variables</a>.</p>
</div>
</div>
<div class="section" id="keywords">
<h1><a class="toc-backref" href="#id15">Keywords</a></h1>
<p>Keywords that test cases are created from come from three sources:
<a class="reference internal" href="#built-in-keywords">built-in keywords</a> are always available, <a class="reference internal" href="#library-keywords">library keywords</a> come
from imported test libraries, and so called <a class="reference internal" href="#user-defined-keywords">user keywords</a> can be
created using the same tabular syntax that is used for creating test
cases.</p>
<div class="section" id="built-in-keywords">
<h2><a class="toc-backref" href="#id16">Built-in keywords</a></h2>
<p>Some generally useful keywords such as <span class="name">Get Time</span> and
<span class="name">Should Be Equal</span> are always available. Technically these
keywords come from a test library called <a class="reference external" href="http://code.google.com/p/robotframework/wiki/BuiltInLibrary">BuiltIn</a> and you can
see its documentation for a complete list of available keywords.</p>
</div>
<div class="section" id="library-keywords">
<h2><a class="toc-backref" href="#id17">Library keywords</a></h2>
<p>All lowest level keywords are defined in test libraries which are
implemented using standard programming languages. Robot Framework
comes with a <a class="reference external" href="http://code.google.com/p/robotframework/wiki/TestLibraries">handful of libraries</a> including an <a class="reference external" href="http://code.google.com/p/robotframework/wiki/OperatingSystemLibrary">OperatingSystem</a>
library to support common operating system functions, and a
<a class="reference external" href="http://code.google.com/p/robotframework/wiki/ScreenshotLibrary">Screenshot</a> library for taking screenshots.  In addition to these
<em>standard libraries</em>, there are other libraries distributed in
separate open source projects, such as <a class="reference external" href="http://code.google.com/p/robotframework-seleniumlibrary">SeleniumLibrary</a> for Web
testing. It is also easy to <a class="reference internal" href="#creating-test-libraries">implement your own libraries</a> when
there is no suitable library available.</p>
<p>To be able to use keywords provided by a test library, it must be taken
into use.  Tests in this file need keywords from the standard
OperatingSystem library (e.g. <span class="name">Remove File</span>) as well as from a
custom made LoginLibrary (e.g. <span class="name">Attempt to login with
credentials</span>). Both of these libraries are imported in so called
<em>setting table</em> below.</p>
<table border="1" class="example docutils">
<colgroup>
<col width="38%" />
<col width="62%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Setting</th>
<th class="head">Value</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>Library</td>
<td>OperatingSystem</td>
</tr>
<tr><td>Library</td>
<td>testlibs/LoginLibrary.py</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="user-defined-keywords">
<h2><a class="toc-backref" href="#id18">User-defined keywords</a></h2>
<p>One of the most powerful features of Robot Framework is the ability to
easily create new higher-level keywords from other keywords. The
syntax for creating these so called <em>user-defined keywords</em>, or <em>user
keywords</em> for short, is similar to the syntax that is used for
creating test cases. All the higher-level keywords needed in previous
test cases are created in the <em>keyword table</em> below.</p>
<table border="1" class="example docutils">
<colgroup>
<col width="37%" />
<col width="26%" />
<col width="24%" />
<col width="13%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Keyword</th>
<th class="head">Action</th>
<th class="head">Argument</th>
<th class="head">Argument</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>Clear login database</td>
<td>Remove file</td>
<td>${DATABASE FILE}</td>
<td></td>
</tr>
<tr><td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr><td>Create valid user</td>
<td>[Arguments]</td>
<td>${username}</td>
<td>${password}</td>
</tr>
<tr><td></td>
<td>Create user</td>
<td>${username}</td>
<td>${password}</td>
</tr>
<tr><td></td>
<td>Status should be</td>
<td>SUCCESS</td>
<td></td>
</tr>
<tr><td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr><td>Creating user with invalid password should fail</td>
<td>[Arguments]</td>
<td>${password}</td>
<td>${error}</td>
</tr>
<tr><td></td>
<td>Create user</td>
<td>example</td>
<td>${password}</td>
</tr>
<tr><td></td>
<td>Status should be</td>
<td>Creating user failed: ${error}</td>
<td></td>
</tr>
<tr><td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr><td>Login</td>
<td>[Arguments]</td>
<td>${username}</td>
<td>${password}</td>
</tr>
<tr><td></td>
<td>Attempt to login with credentials</td>
<td>${username}</td>
<td>${password}</td>
</tr>
<tr><td></td>
<td>Status should be</td>
<td>Logged In</td>
<td></td>
</tr>
<tr><td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr><td><em># Used by BDD test cases (this is a comment)</em></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr><td>Given a user has a valid account</td>
<td>Create valid user</td>
<td>${USERNAME}</td>
<td>${PASSWORD}</td>
</tr>
<tr><td>When she changes her password</td>
<td>Change password</td>
<td>${USERNAME}</td>
<td>${PASSWORD}</td>
</tr>
<tr><td></td>
<td>...</td>
<td>${NEW PASSWORD}</td>
<td></td>
</tr>
<tr><td></td>
<td>Status should be</td>
<td>SUCCESS</td>
<td></td>
</tr>
<tr><td>Then she can log in with the new password</td>
<td>Login</td>
<td>${USERNAME}</td>
<td>${NEW PASSWORD}</td>
</tr>
<tr><td>And she cannot use the old password anymore</td>
<td>Attempt to login with credentials</td>
<td>${USERNAME}</td>
<td>${PASSWORD}</td>
</tr>
<tr><td></td>
<td>Status should be</td>
<td>Access Denied</td>
<td></td>
</tr>
</tbody>
</table>
<p>User-defined keywords can include actions defined by other
user-defined keywords, built-in keywords, or library keywords.  As you
can see from this example, user-defined keywords can take parameters.
They can also return values and even contain FOR loops. For now, the
important thing to know is that user-defined keywords enable test
creators to create reusable steps for common action sequences.
User-defined keywords can also help the test author keep the tests as
readable as possible and use appropriate abstraction levels in
different situations.</p>
</div>
</div>
<div class="section" id="variables">
<h1><a class="toc-backref" href="#id19">Variables</a></h1>
<div class="section" id="defining-variables">
<h2><a class="toc-backref" href="#id20">Defining Variables</a></h2>
<p>Variables are an integral part of Robot Framework. Usually any data used in
tests that is subject to change is best defined as variables. Syntax for
variable definition is quite simple, as seen in this table:</p>
<table border="1" class="example docutils">
<colgroup>
<col width="22%" />
<col width="78%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Variable</th>
<th class="head">Value</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>${USERNAME}</td>
<td>janedoe</td>
</tr>
<tr><td>${PASSWORD}</td>
<td><PASSWORD></td>
</tr>
<tr><td>${NEW PASSWORD}</td>
<td><PASSWORD></td>
</tr>
<tr><td></td>
<td></td>
</tr>
<tr><td>${DATABASE FILE}</td>
<td>${TEMPDIR}${/}robotframework-quickstart-db.txt</td>
</tr>
<tr><td></td>
<td></td>
</tr>
<tr><td>${PWD INVALID LENGTH}</td>
<td>Password must be 7-12 characters long</td>
</tr>
<tr><td>${PWD INVALID CONTENT}</td>
<td>Password must be a combination of lowercase and uppercase letters and numbers</td>
</tr>
</tbody>
</table>
<p>Variables can also be given from the command line which is useful if
the tests need to be executed in different environments. For example
this demo can be executed like:</p>
<pre class="literal-block">
pybot --variable USERNAME:johndoe --variable PASSWORD:<PASSWORD> quickstart.html
</pre>
<p>In addition to user defined variables, there are some built-in
variables that are always available. These variables include
<span class="var">${TEMPDIR}</span> and <span class="var">${/}</span> which are used in the above table.</p>
</div>
<div class="section" id="using-variables">
<h2><a class="toc-backref" href="#id21">Using variables</a></h2>
<p>Variables can be used in most places in the test data. They are most
commonly used as arguments to keywords like the following test case
demonstrates.  Return values from keywords can also be assigned to
variables and used later. For example following <span class="name">Database Should
Contain</span> <a class="reference internal" href="#user-defined-keywords">user keyword</a> sets database content to <span class="var">${database}</span>
variable and then verifies the content using <a class="reference internal" href="#built-in-keywords">built-in keyword</a>
<span class="name">Should Contain</span>.</p>
<table border="1" class="example docutils">
<colgroup>
<col width="34%" />
<col width="24%" />
<col width="15%" />
<col width="15%" />
<col width="13%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Test Case</th>
<th class="head">Action</th>
<th class="head">Argument</th>
<th class="head">Argument</th>
<th class="head">Argument</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>User status is stored in database</td>
<td>[Tags]</td>
<td>variables</td>
<td>database</td>
<td></td>
</tr>
<tr><td></td>
<td>Create Valid User</td>
<td>${USERNAME}</td>
<td>${PASSWORD}</td>
<td></td>
</tr>
<tr><td></td>
<td>Database Should Contain</td>
<td>${USERNAME}</td>
<td>${PASSWORD}</td>
<td>Inactive</td>
</tr>
<tr><td></td>
<td>Login</td>
<td>${USERNAME}</td>
<td>${PASSWORD}</td>
<td></td>
</tr>
<tr><td></td>
<td>Database Should Contain</td>
<td>${USERNAME}</td>
<td>${PASSWORD}</td>
<td>Active</td>
</tr>
</tbody>
</table>
<table border="1" class="example docutils">
<colgroup>
<col width="23%" />
<col width="16%" />
<col width="14%" />
<col width="36%" />
<col width="12%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Keyword</th>
<th class="head">Action</th>
<th class="head">Argument</th>
<th class="head">Argument</th>
<th class="head">Argument</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>Database Should Contain</td>
<td>[Arguments]</td>
<td>${username}</td>
<td>${password}</td>
<td>${status}</td>
</tr>
<tr><td></td>
<td>${database} =</td>
<td>Get File</td>
<td>${DATABASE FILE}</td>
<td></td>
</tr>
<tr><td></td>
<td>Should Contain</td>
<td>${database}</td>
<td>${username}\t${password}\t${status}</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="section" id="organizing-test-cases">
<h1><a class="toc-backref" href="#id22">Organizing test cases</a></h1>
<div class="section" id="test-suites">
<h2><a class="toc-backref" href="#id23">Test suites</a></h2>
<p>Collections of test cases are called test suites in Robot
Framework. Every input file which contains test cases forms a test
suite. When <a class="reference internal" href="#running-this-demo">running this demo</a>, you see test suite
<span class="name">Quickstart</span> in the console output. This name is got from the
file name and it is also visible in the report and log.</p>
<p>It is possible to organize test cases hierarchically by placing test
case files into directories and these directories into other
directories. All these directories automatically create higher level
test suites that get their names from directory names.  Since test
suites are just files and directories, they are trivially placed into
any version control system.</p>
<p>You can test running a directory as a test suite by running following
command in the directory where this guide is located:</p>
<pre class="literal-block">
pybot .
</pre>
</div>
<div class="section" id="setup-and-teardown">
<h2><a class="toc-backref" href="#id24">Setup and teardown</a></h2>
<p>If you want a set of actions to occur before and after each test
executes, use the <span class="name">Test Setup</span> and <span class="name">Test Teardown</span>
settings like so:</p>
<table border="1" class="example docutils">
<colgroup>
<col width="38%" />
<col width="62%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Setting</th>
<th class="head">Value</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>Test Setup</td>
<td>Clear Login Database</td>
</tr>
<tr><td>Test Teardown</td>
<td></td>
</tr>
</tbody>
</table>
<p>Similarly you can use the <span class="name">Suite Setup</span> and <span class="name">Suite
Teardown</span> settings to specify actions to be executed before and after
an entire test suite executes.</p>
</div>
<div class="section" id="using-tags">
<h2><a class="toc-backref" href="#id25">Using tags</a></h2>
<p>Robot Framework allows setting tags for test cases to give them free
metadata.  Tags can be set for all test cases in a file with
<span class="name">Default Tags</span> or <span class="name">Force Tags</span> settings like in the table
below. It is also possible to define tags for single test case like in
<a class="reference internal" href="#using-variables">earlier</a> <span class="name">User status is stored in database</span> test.</p>
<table border="1" class="example docutils">
<colgroup>
<col width="39%" />
<col width="31%" />
<col width="31%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Setting</th>
<th class="head">Value</th>
<th class="head">Value</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>Force Tags</td>
<td>quickstart</td>
<td></td>
</tr>
<tr><td>Default Tags</td>
<td>example</td>
<td>smoke</td>
</tr>
</tbody>
</table>
<p>When you look at a report after test execution, you can see that tests
have specified tags associated with them and there are also statistics
generated based on tags. Tags can also be used for many other
purposes, one of the most important being the possibility to select
what tests to execute. You can try for example following commands:</p>
<pre class="literal-block">
pybot --include smoke quickstart.html
pybot --exclude database quickstart.html
</pre>
</div>
</div>
<div class="section" id="creating-test-libraries">
<h1><a class="toc-backref" href="#id26">Creating test libraries</a></h1>
<p>Robot Framework offers a simple API for creating test libraries, both with
Python and Java. The <a class="reference external" href="http://code.google.com/p/robotframework/wiki/UserGuide">user guide</a> contains detailed description with examples.</p>
<p>Below is the source code of <span class="name">LoginLibrary</span> test library used in
this guide. You can see, for example, how the keyword <span class="name">Create
User</span> is mapped to actual implementation of method
<span class="code">create_user</span>.</p>
<div class="highlight"><pre><span class="k">import</span> <span class="nn">os</span>
<span class="k">import</span> <span class="nn">sys</span>


<span class="k">class</span> <span class="nc">LoginLibrary</span><span class="p">:</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">sut_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">__file__</span><span class="p">),</span>
                                <span class="s">&#39;..&#39;</span><span class="p">,</span> <span class="s">&#39;sut&#39;</span><span class="p">,</span> <span class="s">&#39;login.py&#39;</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_command_prefix</span> <span class="o">=</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s"> &#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">executable</span><span class="p">,</span> <span class="n">sut_path</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_status</span> <span class="o">=</span> <span class="s">&#39;&#39;</span>

    <span class="k">def</span> <span class="nf">create_user</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_run_command</span><span class="p">(</span><span class="s">&#39;create&#39;</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">change_password</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">old_pwd</span><span class="p">,</span> <span class="n">new_pwd</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_run_command</span><span class="p">(</span><span class="s">&#39;change-password&#39;</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">old_pwd</span><span class="p">,</span> <span class="n">new_pwd</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">attempt_to_login_with_credentials</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_run_command</span><span class="p">(</span><span class="s">&#39;login&#39;</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">status_should_be</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">expected_status</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">expected_status</span> <span class="o">!=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_status</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">AssertionError</span><span class="p">(</span><span class="s">&quot;Expected status to be &#39;</span><span class="si">%s</span><span class="s">&#39; but was &#39;</span><span class="si">%s</span><span class="s">&#39;&quot;</span>
                                  <span class="o">%</span> <span class="p">(</span><span class="n">expected_status</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_status</span><span class="p">))</span>

    <span class="k">def</span> <span class="nf">_run_command</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">command</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
        <span class="n">command</span> <span class="o">=</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_command_prefix</span><span class="p">,</span> <span class="n">command</span><span class="p">,</span> <span class="s">&#39; &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">args</span><span class="p">))</span>
        <span class="n">process</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">popen</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_status</span> <span class="o">=</span> <span class="n">process</span><span class="o">.</span><span class="n">read</span><span class="p">()</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
        <span class="n">process</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
<!-- Link targets: -->
</div>
</div>
<div class="footer">
<hr class="footer" />
<p>Generated by <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>. Syntax highlighting by <a class="reference external" href="http://pygments.org/">Pygments</a>.</p>
<p>Generated on: 2008-08-21 09:55 UTC.
</p>

</div>
</body>
</html>
<commit_msg>regenerated to take style updates into use (after adding svn:eol-style the whole file is not changed in every commit)<commit_after><?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" />
<title>Robot Framework Quick Start Guide</title>
<style type="text/css">

/* Robot Framework User Guide Style Sheet

   This stylesheet contains styles from restructuredText's default 
   'html4css1.css' and after that modifications needed for Robot Framework User
   Guide. These styles are added into the same file against suggestions at 
   reST's stylesheet  howto mentioned below, because we want to be able to 
   embed all styles into the created HTML file. Everything before 'Robot 
   Framework User Guide Modifications' text is from 'html4css1.css' without 
   any changes so that part can still be changed easily.
*/


/*
:Author: <NAME> (<EMAIL>)
:Id: $Id: html4css1.css 5196 2007-06-03 20:25:28Z wiemann $
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.

See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/

/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
  border: 0 }

table.borderless td, table.borderless th {
  /* Override padding for "table.docutils td" with "! important".
     The right padding separates the table cells. */
  padding: 0 0.5em 0 0 ! important }

.first {
  /* Override more specific margin styles with "! important". */
  margin-top: 0 ! important }

.last, .with-subtitle {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dl.docutils dd {
  margin-bottom: 0.5em }

/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
  font-weight: bold }
*/

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

/* Uncomment (and remove this text!) to get reduced vertical space in
   compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
  margin-bottom: 0.5em }

div.compound .compound-last, div.compound .compound-middle {
  margin-top: 0.5em }
*/

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em ;
  margin-right: 2em }

div.footer, div.header {
  clear: both;
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin: 0 0 0.5em 1em ;
  border: medium outset ;
  padding: 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
  margin-top: 0.4em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

hr.docutils {
  width: 75% }

img.align-left {
  clear: left }

img.align-right {
  clear: right }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em }

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

span.section-subtitle {
  /* font-size relative to parent (h1..h6 element) */
  font-size: 80% }

table.citation {
  border-left: solid 1px gray;
  margin-left: 1px }

table.docinfo {
  margin: 2em 4em }

table.docutils {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.footnote {
  border-left: solid 1px black;
  margin-left: 1px }

table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

table.docutils th.field-name, table.docinfo th.docinfo-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap ;
  padding-left: 0 }

h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
  font-size: 100% }

ul.auto-toc {
  list-style-type: none }


/* **************************************** *
 * Robot Framework User Guide Modifications * 
 * **************************************** */

/* Tables -- both those used with examples and those with normal tabular data */

table.example, table.tsv-example, table.messages, table.tabular {
    border: 1px solid #808080;
    border-collapse: collapse;
    empty-cell: show;
    margin: 0.5em 2em;
}
table.example caption, table.tsv-example caption, table.tabular caption {
    text-align: left;
    padding-bottom: 0.5em;
    font-style: italic;
    margin: 0.5em 2em;
}
table.example th, table.example td, table.tsv-example td {
    border: 1px solid #808080;
    font-family: arial,helvetica,sans-serif;
    font-size: 0.8em;
    padding: 0.1em 0.3em;
    height: 1.2em;
}
table.example th {
    background: #E0E0E0;
}
table.tabular th, table.tabular td {
    border: 1px solid black;
    font-size: 0.9em;
    padding: 0.1em 0.3em;
    height: 1.2em;
}
table.messages {
    border: none;
    font-family: monospace;
}
table.messages td {
    vertical-align: top;
}
table.messages td.time {
    width: 6em;
    letter-spacing: -0.05em;
} 
table.messages td.level {
    width: 4em;
    text-align: center;
}


/* Roles -- these are defined in roles.txt file */

.var {
    background: #f4f4f4;
    font-size: 0.9em;
}
.opt {
    font-style: italic;
}
.prog, .code, .cli {
    background: #f4f4f4;
    font-family: monospace;
}
.msg {
    font-family: monospace;
}
.name {  
    font-style: italic;
}
.path {
    font-style: italic;
}
.misc, .literal {
    background: #f4f4f4;
}


/* Overridden and modified styles */

div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
  border: 2px solid gray;
}
pre.literal-block, pre.doctest-block {
    background: #f4f4f4;
}


/* Pygments 

- Styles generated using "HtmlFormatter().get_style_defs('.highlight')"
- Changed only background from f8f8f8 to f4f4f4 and added margin
- For more details see e.g. http://pygments.org/docs/quickstart/
*/

.highlight  { background: #f4f4f4; margin: 1em 2em; }
.highlight .c { color: #408080; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #008000; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #808080 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.highlight .kp { color: #008000 } /* Keyword.Pseudo */
.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #B00040 } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BA2121 } /* Literal.String */
.highlight .na { color: #7D9029 } /* Name.Attribute */
.highlight .nb { color: #008000 } /* Name.Builtin */
.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0000FF } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #19177C } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
.highlight .sc { color: #BA2121 } /* Literal.String.Char */
.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
.highlight .ss { color: #19177C } /* Literal.String.Symbol */
.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #19177C } /* Name.Variable.Class */
.highlight .vg { color: #19177C } /* Name.Variable.Global */
.highlight .vi { color: #19177C } /* Name.Variable.Instance */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */

</style>
</head>
<body>
<div class="document" id="robot-framework-quick-start-guide">
<h1 class="title">Robot Framework Quick Start Guide</h1>

<!-- This data file has been placed in the public domain. -->
<!-- Derived from the Unicode character mappings available from
<http://www.w3.org/2003/entities/xml/>.
Processed by unicode2rstsubs.py, part of Docutils:
<http://docutils.sourceforge.net>. -->
<!-- Roles to use in text like :rolename:`text`. Styled in userguide.css.
- var    variables
- opt    settings in setting table (e.g. Force Tags), tc/kw tables
         (e.g [Documentation]) and command line options (e.g. - -name)
- prog   program names (e.g. rebot, risto.py)
- code   programming code
- msg    test case status and message, as well as log messages and levels
- name   keyword, library, test case, test suite, etc. names
- cli    command line examples (note that options alone use opt)
- path   file names and paths
- misc   everything else (synonym to ``text``) -->
<div class="line-block">
<div class="line">Copyright © Nokia Siemens Networks 2008</div>
<div class="line">Licensed under the Apache License, Version 2.0</div>
</div>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#introduction" id="id6">Introduction</a><ul>
<li><a class="reference internal" href="#overview" id="id7">Overview</a></li>
<li><a class="reference internal" href="#installation" id="id8">Installation</a></li>
<li><a class="reference internal" href="#running-this-demo" id="id9">Running this demo</a></li>
<li><a class="reference internal" href="#introducing-the-sample-application" id="id10">Introducing the sample application</a></li>
</ul>
</li>
<li><a class="reference internal" href="#test-cases" id="id11">Test cases</a><ul>
<li><a class="reference internal" href="#first-test-cases" id="id12">First test cases</a></li>
<li><a class="reference internal" href="#higher-level-test-cases" id="id13">Higher-level test cases</a></li>
<li><a class="reference internal" href="#data-driven-test-cases" id="id14">Data-driven test cases</a></li>
</ul>
</li>
<li><a class="reference internal" href="#keywords" id="id15">Keywords</a><ul>
<li><a class="reference internal" href="#built-in-keywords" id="id16">Built-in keywords</a></li>
<li><a class="reference internal" href="#library-keywords" id="id17">Library keywords</a></li>
<li><a class="reference internal" href="#user-defined-keywords" id="id18">User-defined keywords</a></li>
</ul>
</li>
<li><a class="reference internal" href="#variables" id="id19">Variables</a><ul>
<li><a class="reference internal" href="#defining-variables" id="id20">Defining Variables</a></li>
<li><a class="reference internal" href="#using-variables" id="id21">Using variables</a></li>
</ul>
</li>
<li><a class="reference internal" href="#organizing-test-cases" id="id22">Organizing test cases</a><ul>
<li><a class="reference internal" href="#test-suites" id="id23">Test suites</a></li>
<li><a class="reference internal" href="#setup-and-teardown" id="id24">Setup and teardown</a></li>
<li><a class="reference internal" href="#using-tags" id="id25">Using tags</a></li>
</ul>
</li>
<li><a class="reference internal" href="#creating-test-libraries" id="id26">Creating test libraries</a></li>
</ul>
</div>
<div class="section" id="introduction">
<h1><a class="toc-backref" href="#id6">Introduction</a></h1>
<div class="section" id="overview">
<h2><a class="toc-backref" href="#id7">Overview</a></h2>
<p>Robot Framework is a keyword-driven test automation framework.  Test
cases live in HTML or TSV (tab-separated values) test files and make
use of keywords implemented in test libraries to drive the software
under test. Because Robot Framework is flexible and extensible, it is
ideally suited to testing complex software with a variety of
interfaces: user interfaces, command line, web services, proprietary
programming interfaces, etc.</p>
<p>Robot Framework is open source software and installation packages,
source code and further documentation is available through
<a class="reference external" href="http://robotframework.org">http://robotframework.org</a>. This guide is designed to introduce the
basic concepts of Robot Framework.  For a detailed technical
description, please refer to <a class="reference external" href="http://code.google.com/p/robotframework/wiki/UserGuide">Robot Framework User Guide</a>.</p>
</div>
<div class="section" id="installation">
<h2><a class="toc-backref" href="#id8">Installation</a></h2>
<p>A precondition for installing Robot Framework is having <a class="reference external" href="http://python.org">Python</a> installed.
In addition, to use test libraries written in Java, <a class="reference external" href="http://jython.org">Jython</a> must be
installed. To use this Quick Start Guide, Python is enough.</p>
<p>There are three different ways to install Robot Framework, of which
the most suitable can be chosen. Detailed installation instructions
can be found from the <a class="reference external" href="http://code.google.com/p/robotframework/wiki/UserGuide">user guide</a>.</p>
<ol class="arabic simple">
<li>There is a binary installer for Windows platform. It is enough to
double-click the installer and follow instructions.</li>
<li>On every platform, Robot Framework can be installed from
source. To install from source, extract the source distribution
and run command <span class="cli">python setup.py install</span>.</li>
<li>If Python package management system <a class="reference external" href="http://peak.telecommunity.com/DevCenter/EasyInstall">Easy Install</a> is available,
Robot Framework can be installed by issuing command
<span class="cli">easy_install robotframework</span>. On Windows you also need to
run <span class="path">robot_postinstall.py</span> script manually.</li>
</ol>
<p>After the framework is installed, it is useful to include the
directory containing start-up scripts in <span class="var">PATH</span> environment
variable. On UNIX-like systems this should actually happen
automatically, but on Windows this must be done from <tt class="docutils literal"><span class="pre">Control</span> <span class="pre">Panel</span> <span class="pre">&gt;</span>
<span class="pre">System</span> <span class="pre">&gt;</span> <span class="pre">Advanced</span> <span class="pre">&gt;</span> <span class="pre">Environment</span> <span class="pre">Variables</span></tt> by adding e.g.
<span class="path">C:\Python25\Scripts</span> to <span class="var">PATH</span>.</p>
<p>Successful installation can be verified with command <span class="cli">pybot
--version</span> which should output something like:</p>
<pre class="literal-block">
$ pybot --version
Robot 2.0.1 (Python 2.5.2 on linux2)
</pre>
</div>
<div class="section" id="running-this-demo">
<h2><a class="toc-backref" href="#id9">Running this demo</a></h2>
<p>This Quick Start Guide also acts as an executable demo.  To run it,
open a command shell, cd to this directory, and type the following
command at the command line:</p>
<pre class="literal-block">
pybot quickstart.html
</pre>
<p>The tests in this file will execute and generate the following reports:</p>
<dl class="docutils">
<dt><span class="path">report.html</span></dt>
<dd>the test results summary</dd>
<dt><span class="path">log.html</span></dt>
<dd>the test results details</dd>
<dt><span class="path">output.xml</span></dt>
<dd>the test results in a portable XML format for integration with other tools</dd>
</dl>
<p>Open <a class="reference external" href="report.html">report.html</a> (the link works only after this guide has been executed) in your browser, then click on the links to explore
the results. The <span class="path">report.html</span> file links to the <span class="path">log.html</span> file.</p>
<p>There are also a number of command line options that can be used to
control the test execution and generated outputs. Complete list can be
viewed by issuing <span class="cli">pybot --help</span>. For example the following
command changes the name of the log file and the name of the top level
test suite:</p>
<pre class="literal-block">
pybot --log mylog.html --name My_Fine_Tests quickstart.html
</pre>
</div>
<div class="section" id="introducing-the-sample-application">
<h2><a class="toc-backref" href="#id10">Introducing the sample application</a></h2>
<p>The sample application for this paper is a variation on a classic
login example: it is a command-line based authentication server written
in Python. At the moment, the sample application allows a user to do
three things:</p>
<ul class="simple">
<li>Create an account with a valid password.</li>
<li>Log in with a valid user name and password.</li>
<li>Change the password of an existing account.</li>
</ul>
<p>The application itself is in the <span class="path">sut</span> directory and can be
executed with a command <span class="cli">python sut/login.py</span>. Attempting to log
in with a non-existent user account or with an invalid password
results in the same error message:</p>
<pre class="literal-block">
&gt; python sut/login.py login nobody P4ssw0rd
Access Denied
</pre>
<p>After creating a user account with valid password login succeeds:</p>
<pre class="literal-block">
&gt; python sut/login.py create fred P4ssw0rd
SUCCESS

&gt; python sut/login.py login fred P4ssw0rd
Logged In
</pre>
<p>There are two requirements that a password must fulfill to be valid: it must
be between 7-12 characters long, and it must contain lower and upper case
letters and numbers, but it must not contain special characters. Trying to
create a user with invalid password fails:</p>
<pre class="literal-block">
&gt; python sut/login.py create fred short
Creating user failed: Password must be 7-12 characters long

&gt; python sut/login.py create fred invalid
Creating user failed: Password must be a combination of lowercase and
uppercase letters and numbers
</pre>
<p>Changing password with invalid credentials results in the same error message
as logging in with invalid credentials. The validity of new password is
verified and if not valid, an error message is given:</p>
<pre class="literal-block">
&gt; python sut/login.py change-password fred wrong NewP4ss
Changing password failed: Access Denied

&gt; python sut/login.py change-password fred P<PASSWORD> short
Changing password failed: Password must be 7-12 characters long

&gt; python sut/login.py change-password fred P<PASSWORD>rd New<PASSWORD>
SUCCESS
</pre>
<p>The application uses a simple database file to keep track on user
statuses. The file is located in operating system dependent temporary
directory.</p>
</div>
</div>
<div class="section" id="test-cases">
<h1><a class="toc-backref" href="#id11">Test cases</a></h1>
<div class="section" id="first-test-cases">
<h2><a class="toc-backref" href="#id12">First test cases</a></h2>
<p>Robot Framework test cases are created using a simple tabular syntax. For example the following table has two tests:</p>
<blockquote>
<ul class="simple">
<li>User can create an account and log in</li>
<li>User cannot log in with bad password</li>
</ul>
</blockquote>
<table border="1" class="example docutils">
<colgroup>
<col width="38%" />
<col width="34%" />
<col width="14%" />
<col width="14%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Test Case</th>
<th class="head">Action</th>
<th class="head">Argument</th>
<th class="head">Argument</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>User can create an account and log in</td>
<td>Create Valid User</td>
<td>fred</td>
<td>P4ssw0rd</td>
</tr>
<tr><td></td>
<td>Attempt to Login with Credentials</td>
<td>fred</td>
<td>P4ssw0rd</td>
</tr>
<tr><td></td>
<td>Status Should Be</td>
<td>Logged In</td>
<td></td>
</tr>
<tr><td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr><td>User cannot log in with bad password</td>
<td>Create Valid User</td>
<td>betty</td>
<td>P4ssw0rd</td>
</tr>
<tr><td></td>
<td>Attempt to Login with Credentials</td>
<td>betty</td>
<td>wrong</td>
</tr>
<tr><td></td>
<td>Status Should Be</td>
<td>Access Denied</td>
<td></td>
</tr>
</tbody>
</table>
<p>Notice that these tests read almost like manual tests written in
English rather than like automated test cases. Robot Framework uses the
keyword-driven approach that supports writing tests that capture the
essence of the actions and expectations in natural language. Test
cases are constructed from keywords (normally in the second column) and
their possible arguments.</p>
</div>
<div class="section" id="higher-level-test-cases">
<h2><a class="toc-backref" href="#id13">Higher-level test cases</a></h2>
<p>Test cases can also be created using only high-level keywords that
take no arguments. This style allows using totally free text which is
suitable for communication even with non-technical customers or
other stakeholders. Robot Framework does not enforce any particular
style for writing test cases, and it is possible to use for example
<em>given-when-then</em> format popularized by <a class="reference external" href="http://en.wikipedia.org/wiki/Behavior_driven_development">behavior-driven development</a>
(BDD) like in the example below.</p>
<table border="1" class="example docutils">
<colgroup>
<col width="36%" />
<col width="64%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Test Case</th>
<th class="head">Steps</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>User can change password</td>
<td>Given a user has a valid account</td>
</tr>
<tr><td></td>
<td>when she changes her password</td>
</tr>
<tr><td></td>
<td>then she can log in with the new password</td>
</tr>
<tr><td></td>
<td>and she cannot use the old password anymore</td>
</tr>
</tbody>
</table>
<p>This kind of use-case or user-story-like test cases are ideally suited
for <em>acceptance test-driven development</em> (ATTD). In ATTD acceptance
tests are written before implementing actual product features and they
act also as requirements.</p>
</div>
<div class="section" id="data-driven-test-cases">
<h2><a class="toc-backref" href="#id14">Data-driven test cases</a></h2>
<p>Quite often several test cases are otherwise similar but they have
slightly different input or output data. In these situations
<em>data-driven</em> test cases, like six tests below, allow varying the test
data without duplicating the workflow.</p>
<table border="1" class="example docutils">
<colgroup>
<col width="29%" />
<col width="41%" />
<col width="11%" />
<col width="19%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Test Case</th>
<th class="head">Action</th>
<th class="head">Password</th>
<th class="head">Expected error message</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>Too short password</td>
<td>Creating user with invalid password should fail</td>
<td>abCD5</td>
<td>${PWD INVALID LENGTH}</td>
</tr>
<tr><td>Too long password</td>
<td>Creating user with invalid password should fail</td>
<td><PASSWORD></td>
<td>${PWD INVALID LENGTH}</td>
</tr>
<tr><td>Password without lowercase letters</td>
<td>Creating user with invalid password should fail</td>
<td>123DEFG</td>
<td>${PWD INVALID CONTENT}</td>
</tr>
<tr><td>Password without capital letters</td>
<td>Creating user with invalid password should fail</td>
<td>abcd56789</td>
<td>${PWD INVALID CONTENT}</td>
</tr>
<tr><td>Password without numbers</td>
<td>Creating user with invalid password should fail</td>
<td>AbCdEfGh</td>
<td>${PWD INVALID CONTENT}</td>
</tr>
<tr><td>Password with special characters</td>
<td>Creating user with invalid password should fail</td>
<td>abCD56+</td>
<td>${PWD INVALID CONTENT}</td>
</tr>
</tbody>
</table>
<p>In these tests there is only one keyword per test case, and it is
responsible for trying to create a user with the provided password and
checking that creation fails with an expected error message. Notice
that the error messages are specified using <a class="reference internal" href="#variables">variables</a>.</p>
</div>
</div>
<div class="section" id="keywords">
<h1><a class="toc-backref" href="#id15">Keywords</a></h1>
<p>Keywords that test cases are created from come from three sources:
<a class="reference internal" href="#built-in-keywords">built-in keywords</a> are always available, <a class="reference internal" href="#library-keywords">library keywords</a> come
from imported test libraries, and so called <a class="reference internal" href="#user-defined-keywords">user keywords</a> can be
created using the same tabular syntax that is used for creating test
cases.</p>
<div class="section" id="built-in-keywords">
<h2><a class="toc-backref" href="#id16">Built-in keywords</a></h2>
<p>Some generally useful keywords such as <span class="name">Get Time</span> and
<span class="name">Should Be Equal</span> are always available. Technically these
keywords come from a test library called <a class="reference external" href="http://code.google.com/p/robotframework/wiki/BuiltInLibrary">BuiltIn</a> and you can
see its documentation for a complete list of available keywords.</p>
</div>
<div class="section" id="library-keywords">
<h2><a class="toc-backref" href="#id17">Library keywords</a></h2>
<p>All lowest level keywords are defined in test libraries which are
implemented using standard programming languages. Robot Framework
comes with a <a class="reference external" href="http://code.google.com/p/robotframework/wiki/TestLibraries">handful of libraries</a> including an <a class="reference external" href="http://code.google.com/p/robotframework/wiki/OperatingSystemLibrary">OperatingSystem</a>
library to support common operating system functions, and a
<a class="reference external" href="http://code.google.com/p/robotframework/wiki/ScreenshotLibrary">Screenshot</a> library for taking screenshots.  In addition to these
<em>standard libraries</em>, there are other libraries distributed in
separate open source projects, such as <a class="reference external" href="http://code.google.com/p/robotframework-seleniumlibrary">SeleniumLibrary</a> for Web
testing. It is also easy to <a class="reference internal" href="#creating-test-libraries">implement your own libraries</a> when
there is no suitable library available.</p>
<p>To be able to use keywords provided by a test library, it must be taken
into use.  Tests in this file need keywords from the standard
OperatingSystem library (e.g. <span class="name">Remove File</span>) as well as from a
custom made LoginLibrary (e.g. <span class="name">Attempt to login with
credentials</span>). Both of these libraries are imported in so called
<em>setting table</em> below.</p>
<table border="1" class="example docutils">
<colgroup>
<col width="38%" />
<col width="62%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Setting</th>
<th class="head">Value</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>Library</td>
<td>OperatingSystem</td>
</tr>
<tr><td>Library</td>
<td>testlibs/LoginLibrary.py</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="user-defined-keywords">
<h2><a class="toc-backref" href="#id18">User-defined keywords</a></h2>
<p>One of the most powerful features of Robot Framework is the ability to
easily create new higher-level keywords from other keywords. The
syntax for creating these so called <em>user-defined keywords</em>, or <em>user
keywords</em> for short, is similar to the syntax that is used for
creating test cases. All the higher-level keywords needed in previous
test cases are created in the <em>keyword table</em> below.</p>
<table border="1" class="example docutils">
<colgroup>
<col width="37%" />
<col width="26%" />
<col width="24%" />
<col width="13%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Keyword</th>
<th class="head">Action</th>
<th class="head">Argument</th>
<th class="head">Argument</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>Clear login database</td>
<td>Remove file</td>
<td>${DATABASE FILE}</td>
<td></td>
</tr>
<tr><td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr><td>Create valid user</td>
<td>[Arguments]</td>
<td>${username}</td>
<td>${password}</td>
</tr>
<tr><td></td>
<td>Create user</td>
<td>${username}</td>
<td>${password}</td>
</tr>
<tr><td></td>
<td>Status should be</td>
<td>SUCCESS</td>
<td></td>
</tr>
<tr><td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr><td>Creating user with invalid password should fail</td>
<td>[Arguments]</td>
<td>${password}</td>
<td>${error}</td>
</tr>
<tr><td></td>
<td>Create user</td>
<td>example</td>
<td>${password}</td>
</tr>
<tr><td></td>
<td>Status should be</td>
<td>Creating user failed: ${error}</td>
<td></td>
</tr>
<tr><td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr><td>Login</td>
<td>[Arguments]</td>
<td>${username}</td>
<td>${password}</td>
</tr>
<tr><td></td>
<td>Attempt to login with credentials</td>
<td>${username}</td>
<td>${password}</td>
</tr>
<tr><td></td>
<td>Status should be</td>
<td>Logged In</td>
<td></td>
</tr>
<tr><td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr><td><em># Used by BDD test cases (this is a comment)</em></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr><td>Given a user has a valid account</td>
<td>Create valid user</td>
<td>${USERNAME}</td>
<td>${PASSWORD}</td>
</tr>
<tr><td>When she changes her password</td>
<td>Change password</td>
<td>${USERNAME}</td>
<td>${PASSWORD}</td>
</tr>
<tr><td></td>
<td>...</td>
<td>${NEW PASSWORD}</td>
<td></td>
</tr>
<tr><td></td>
<td>Status should be</td>
<td>SUCCESS</td>
<td></td>
</tr>
<tr><td>Then she can log in with the new password</td>
<td>Login</td>
<td>${USERNAME}</td>
<td>${NEW PASSWORD}</td>
</tr>
<tr><td>And she cannot use the old password anymore</td>
<td>Attempt to login with credentials</td>
<td>${USERNAME}</td>
<td>${PASSWORD}</td>
</tr>
<tr><td></td>
<td>Status should be</td>
<td>Access Denied</td>
<td></td>
</tr>
</tbody>
</table>
<p>User-defined keywords can include actions defined by other
user-defined keywords, built-in keywords, or library keywords.  As you
can see from this example, user-defined keywords can take parameters.
They can also return values and even contain FOR loops. For now, the
important thing to know is that user-defined keywords enable test
creators to create reusable steps for common action sequences.
User-defined keywords can also help the test author keep the tests as
readable as possible and use appropriate abstraction levels in
different situations.</p>
</div>
</div>
<div class="section" id="variables">
<h1><a class="toc-backref" href="#id19">Variables</a></h1>
<div class="section" id="defining-variables">
<h2><a class="toc-backref" href="#id20">Defining Variables</a></h2>
<p>Variables are an integral part of Robot Framework. Usually any data used in
tests that is subject to change is best defined as variables. Syntax for
variable definition is quite simple, as seen in this table:</p>
<table border="1" class="example docutils">
<colgroup>
<col width="22%" />
<col width="78%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Variable</th>
<th class="head">Value</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>${USERNAME}</td>
<td>janedoe</td>
</tr>
<tr><td>${PASSWORD}</td>
<td><PASSWORD></td>
</tr>
<tr><td>${NEW PASSWORD}</td>
<td>e<PASSWORD></td>
</tr>
<tr><td></td>
<td></td>
</tr>
<tr><td>${DATABASE FILE}</td>
<td>${TEMPDIR}${/}robotframework-quickstart-db.txt</td>
</tr>
<tr><td></td>
<td></td>
</tr>
<tr><td>${PWD INVALID LENGTH}</td>
<td>Password must be 7-12 characters long</td>
</tr>
<tr><td>${PWD INVALID CONTENT}</td>
<td>Password must be a combination of lowercase and uppercase letters and numbers</td>
</tr>
</tbody>
</table>
<p>Variables can also be given from the command line which is useful if
the tests need to be executed in different environments. For example
this demo can be executed like:</p>
<pre class="literal-block">
pybot --variable USERNAME:johndoe --variable PASSWORD:<PASSWORD>e quickstart.html
</pre>
<p>In addition to user defined variables, there are some built-in
variables that are always available. These variables include
<span class="var">${TEMPDIR}</span> and <span class="var">${/}</span> which are used in the above table.</p>
</div>
<div class="section" id="using-variables">
<h2><a class="toc-backref" href="#id21">Using variables</a></h2>
<p>Variables can be used in most places in the test data. They are most
commonly used as arguments to keywords like the following test case
demonstrates.  Return values from keywords can also be assigned to
variables and used later. For example following <span class="name">Database Should
Contain</span> <a class="reference internal" href="#user-defined-keywords">user keyword</a> sets database content to <span class="var">${database}</span>
variable and then verifies the content using <a class="reference internal" href="#built-in-keywords">built-in keyword</a>
<span class="name">Should Contain</span>.</p>
<table border="1" class="example docutils">
<colgroup>
<col width="34%" />
<col width="24%" />
<col width="15%" />
<col width="15%" />
<col width="13%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Test Case</th>
<th class="head">Action</th>
<th class="head">Argument</th>
<th class="head">Argument</th>
<th class="head">Argument</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>User status is stored in database</td>
<td>[Tags]</td>
<td>variables</td>
<td>database</td>
<td></td>
</tr>
<tr><td></td>
<td>Create Valid User</td>
<td>${USERNAME}</td>
<td>${PASSWORD}</td>
<td></td>
</tr>
<tr><td></td>
<td>Database Should Contain</td>
<td>${USERNAME}</td>
<td>${PASSWORD}</td>
<td>Inactive</td>
</tr>
<tr><td></td>
<td>Login</td>
<td>${USERNAME}</td>
<td>${PASSWORD}</td>
<td></td>
</tr>
<tr><td></td>
<td>Database Should Contain</td>
<td>${USERNAME}</td>
<td>${PASSWORD}</td>
<td>Active</td>
</tr>
</tbody>
</table>
<table border="1" class="example docutils">
<colgroup>
<col width="23%" />
<col width="16%" />
<col width="14%" />
<col width="36%" />
<col width="12%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Keyword</th>
<th class="head">Action</th>
<th class="head">Argument</th>
<th class="head">Argument</th>
<th class="head">Argument</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>Database Should Contain</td>
<td>[Arguments]</td>
<td>${username}</td>
<td>${password}</td>
<td>${status}</td>
</tr>
<tr><td></td>
<td>${database} =</td>
<td>Get File</td>
<td>${DATABASE FILE}</td>
<td></td>
</tr>
<tr><td></td>
<td>Should Contain</td>
<td>${database}</td>
<td>${username}\t${password}\t${status}</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="section" id="organizing-test-cases">
<h1><a class="toc-backref" href="#id22">Organizing test cases</a></h1>
<div class="section" id="test-suites">
<h2><a class="toc-backref" href="#id23">Test suites</a></h2>
<p>Collections of test cases are called test suites in Robot
Framework. Every input file which contains test cases forms a test
suite. When <a class="reference internal" href="#running-this-demo">running this demo</a>, you see test suite
<span class="name">Quickstart</span> in the console output. This name is got from the
file name and it is also visible in the report and log.</p>
<p>It is possible to organize test cases hierarchically by placing test
case files into directories and these directories into other
directories. All these directories automatically create higher level
test suites that get their names from directory names.  Since test
suites are just files and directories, they are trivially placed into
any version control system.</p>
<p>You can test running a directory as a test suite by running following
command in the directory where this guide is located:</p>
<pre class="literal-block">
pybot .
</pre>
</div>
<div class="section" id="setup-and-teardown">
<h2><a class="toc-backref" href="#id24">Setup and teardown</a></h2>
<p>If you want a set of actions to occur before and after each test
executes, use the <span class="name">Test Setup</span> and <span class="name">Test Teardown</span>
settings like so:</p>
<table border="1" class="example docutils">
<colgroup>
<col width="38%" />
<col width="62%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Setting</th>
<th class="head">Value</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>Test Setup</td>
<td>Clear Login Database</td>
</tr>
<tr><td>Test Teardown</td>
<td></td>
</tr>
</tbody>
</table>
<p>Similarly you can use the <span class="name">Suite Setup</span> and <span class="name">Suite
Teardown</span> settings to specify actions to be executed before and after
an entire test suite executes.</p>
</div>
<div class="section" id="using-tags">
<h2><a class="toc-backref" href="#id25">Using tags</a></h2>
<p>Robot Framework allows setting tags for test cases to give them free
metadata.  Tags can be set for all test cases in a file with
<span class="name">Default Tags</span> or <span class="name">Force Tags</span> settings like in the table
below. It is also possible to define tags for single test case like in
<a class="reference internal" href="#using-variables">earlier</a> <span class="name">User status is stored in database</span> test.</p>
<table border="1" class="example docutils">
<colgroup>
<col width="39%" />
<col width="31%" />
<col width="31%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Setting</th>
<th class="head">Value</th>
<th class="head">Value</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>Force Tags</td>
<td>quickstart</td>
<td></td>
</tr>
<tr><td>Default Tags</td>
<td>example</td>
<td>smoke</td>
</tr>
</tbody>
</table>
<p>When you look at a report after test execution, you can see that tests
have specified tags associated with them and there are also statistics
generated based on tags. Tags can also be used for many other
purposes, one of the most important being the possibility to select
what tests to execute. You can try for example following commands:</p>
<pre class="literal-block">
pybot --include smoke quickstart.html
pybot --exclude database quickstart.html
</pre>
</div>
</div>
<div class="section" id="creating-test-libraries">
<h1><a class="toc-backref" href="#id26">Creating test libraries</a></h1>
<p>Robot Framework offers a simple API for creating test libraries, both with
Python and Java. The <a class="reference external" href="http://code.google.com/p/robotframework/wiki/UserGuide">user guide</a> contains detailed description with examples.</p>
<p>Below is the source code of <span class="name">LoginLibrary</span> test library used in
this guide. You can see, for example, how the keyword <span class="name">Create
User</span> is mapped to actual implementation of method
<span class="code">create_user</span>.</p>
<div class="highlight"><pre><span class="k">import</span> <span class="nn">os</span>
<span class="k">import</span> <span class="nn">sys</span>


<span class="k">class</span> <span class="nc">LoginLibrary</span><span class="p">:</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">sut_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">__file__</span><span class="p">),</span>
                                <span class="s">&#39;..&#39;</span><span class="p">,</span> <span class="s">&#39;sut&#39;</span><span class="p">,</span> <span class="s">&#39;login.py&#39;</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_command_prefix</span> <span class="o">=</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s"> &#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">executable</span><span class="p">,</span> <span class="n">sut_path</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_status</span> <span class="o">=</span> <span class="s">&#39;&#39;</span>

    <span class="k">def</span> <span class="nf">create_user</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_run_command</span><span class="p">(</span><span class="s">&#39;create&#39;</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">change_password</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">old_pwd</span><span class="p">,</span> <span class="n">new_pwd</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_run_command</span><span class="p">(</span><span class="s">&#39;change-password&#39;</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">old_pwd</span><span class="p">,</span> <span class="n">new_pwd</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">attempt_to_login_with_credentials</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_run_command</span><span class="p">(</span><span class="s">&#39;login&#39;</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">status_should_be</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">expected_status</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">expected_status</span> <span class="o">!=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_status</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">AssertionError</span><span class="p">(</span><span class="s">&quot;Expected status to be &#39;</span><span class="si">%s</span><span class="s">&#39; but was &#39;</span><span class="si">%s</span><span class="s">&#39;&quot;</span>
                                  <span class="o">%</span> <span class="p">(</span><span class="n">expected_status</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_status</span><span class="p">))</span>

    <span class="k">def</span> <span class="nf">_run_command</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">command</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
        <span class="n">command</span> <span class="o">=</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_command_prefix</span><span class="p">,</span> <span class="n">command</span><span class="p">,</span> <span class="s">&#39; &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">args</span><span class="p">))</span>
        <span class="n">process</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">popen</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_status</span> <span class="o">=</span> <span class="n">process</span><span class="o">.</span><span class="n">read</span><span class="p">()</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
        <span class="n">process</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
<!-- Link targets: -->
</div>
</div>
<div class="footer">
<hr class="footer" />
<p>Generated by <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>. Syntax highlighting by <a class="reference external" href="http://pygments.org/">Pygments</a>.</p>
<p>Generated on: 2008-08-21 13:20 UTC.
</p>

</div>
</body>
</html>

{'fraction_non_alphanumeric': 0.1841774461700661, 'fraction_numerical': 0.01639227930740846, 'mean_word_length': 4.9589827232088926, 'pattern_counts': {'":': 0, '<': 3476, '<?xml version=': 2, '>': 3476, 'https://': 0, 'lorem ipsum': 0, 'www.': 6, 'xml': 10}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4126726', 'n_tokens_mistral': 34409, 'n_tokens_neox': 32683, 'n_words': 9600}