Template in Robot Framework
| Introduction | |
| Test Template Setting | |
| Data-driven Style | |
| Named Columns | |
| Arguments Embedded to Keyword Name | |
| Related Articles |
Introduction
Test templates transform regular keyword-driven test cases into data-driven tests.
While the body of a keyword-driven test case is built from keywords and their possible arguments,
template test cases contain only the arguments for the keyword template.
Instead of repeating the same keyword multiple times for each test and/or for all tests in a file, you can use it
only for each test or only once per file.
Keywords used as a template can accept both regular positional and named arguments, as well as
arguments embedded in the keyword name
.
Unlike other settings, it is not possible to define a template using variables.
Basic Usage
How a keyword including consecutive positional arguments can be used as a template is illustrated by the test examples.
These two tests are completely reliable.
Official Documentation
That a test case uses a template can be specified by setting the [Template] test case after declaring the test case name.
*** Test Cases *** Normal test case Example keyword first argument second argument Templated test case [Template] Example keyword first argument second argument Another templated test case [Template] Example keyword first argument second argument
Test Template
If all test cases in a Test Suite use the same template, you can specify it
in the
*** Settings ***
section using Test Template
*** Settings *** Test Template Example keyword *** Test Cases *** Templated test case first round 1 first round 2 second round 1 second round 2 third round 1 third round 2 Another templated test case first round 1 first round 2 second round 1 second round 2 third round 1 third round 2
In this example, there was no need to write [Template] twice. Whether or not to use Test Template is usually decided based on the specific test architecture.
An example that combines the use of Test Template and
Embedded Arguments in the key name
(Embedded Arguments) can be found in
here
Approaches to writing tests
Templates are a tool for Data-driven testing. To understand the essence of this approach, it is usually explained how it differs from Keyword-driven testing.
Keyword-driven Style
Workflow tests, such as the positive login test described here, are created based on several keywords and their possible arguments.
Their typical structure is as follows:
-
First, the system is transferred to its initial state
- Open Browser To Login Page in the Valid Login example
-
Then something is done to the system
- Username is entered - Input Username
- Password is entered - Input Password
- Credentials are submitted - Submit Credentials
-
And finally, it is checked that the system behaves as expected
- The welcome page should be opened - User Page Should Be Open
Data-driven Style
Another style of writing test cases is the data-driven approach, where test cases
use only one higher-level keyword, often created as a custom keyword,
which hides the actual testing workflow.
These tests are very useful when you need to test the same scenario with different inputs and/or outputs.
It would be possible to repeat the same keyword in each test, but the templating functionality allows you to specify a keyword to
be used only once.
official documentation
Example
An example using six separate tests, the difference between which is only in the name and the arguments that are passed to the template. This example uses Test Template and named columns. To simulate an unfilled field, we use a special variable ${EMPTY}
*** Settings *** Test Template Login with invalid credentials should fail *** Test Cases *** USERNAME PASSWORD Invalid User Name invalid ${VALID PASSWORD} Invalid Password ${VALID USER} invalid Invalid User Name and Password invalid invalid Empty User Name ${EMPTY} ${VALID PASSWORD} Empty Password ${VALID USER} ${EMPTY} Empty User Name and Password ${EMPTY} ${EMPTY}
Naming the columns as in the example above makes the tests easier to understand.
This is possible because the header row
ignores all cells in
except the first one.
The example above contains six separate tests, one for each invalid username/password combination.
The example below illustrates how to run just one test against all combinations. The same approach + embedded
arguments in the key name we have already used
here
When using test templates, all test rounds are executed even in the presence of failures, so there is no real functional
difference between the two styles.
In the example above, the individual combinations are named to make it easier to see what they are testing, but potentially
a large number of these tests could skew the statistics.
Which style to use depends on context and personal preference.
*** Test Cases *** Invalid Password [Template] Login with invalid credentials should fail invalid ${VALID PASSWORD} ${VALID USER} invalid invalid whatever ${EMPTY} ${VALID PASSWORD} ${VALID USER} ${EMPTY} ${EMPTY} ${EMPTY}
Named Columns
Let's apply the named column approach to the test from my demo project
*** Settings *** Documentation Flasky App Login DD Test Resource users/users.resource Suite Setup Setup Suite Force Tags ui login Test Template Submiting credentials should forward to page with title *** Variables *** *** Keywords *** Create Unique User &{unique_user}= Generate Unique User Set Suite Variable ${unique_user} Setup Suite Create Unique User Register User user=${unique_user} # To reduce variable names two new # variables are created here ${VALID USER}= Set Variable ${unique_user.username} Set Suite Variable ${VALID USER} ${VALID PASSWD}= Set Variable ${unique_user.password} Set Suite Variable ${VALID PASSWD} Test Setup Tasks Start Chromium Browser Test Teardown Tasks Close Browser Submiting credentials should forward to page with title [Arguments] ${username} ${password} ${expected_title} Open Browser To Login Page Log ${username} Log ${password} Input Username ${username} Input Password ${password} Submit Credentials ${title}= Get Title Log ${title} Should Be Equal ${title} ${expected_title} *** Test Cases *** USERNAME PASSWORD EXPECTED TITLE Valid Credentials ${VALID USER} ${VALID PASSWD} User Information - Demo App Invalid User Name invalid ${VALID PASSWD} Login Failure - Demo App Invalid Password ${VALID USER} invalid Login Failure - Demo App Invalid User Name and Password invalid invalid Login Failure - Demo App Empty User Name ${EMPTY} ${VALID PASSWD} Log In - Demo App Empty Password ${VALID USER} ${EMPTY} Log In - Demo App Empty User Name and Password ${EMPTY} ${EMPTY} Log In - Demo App Empty User Name Invalid Password ${EMPTY} invalid Log In - Demo App Invalid User Name Empty Password invalid ${EMPTY} Log In - Demo App
Arguments embedded in keyword name
Let's look at an example of a template where the arguments are embedded in the keyword name itself.
From the
official documentation
you can learn that
templates support a variation of the
syntax for embedded arguments
.
In templates, this syntax works in such a way that
if the Template keyword contains variables in its name,
they are considered argument placeholders and are replaced with the actual arguments used in the template.
The resulting keyword is then used without positional arguments.
This is best illustrated with an example:
*** Keywords *** The result of ${calculation} should be ${expected} ${result} = Calculate ${calculation} Should Be Equal ${result} ${expected} *** Test Cases *** Normal test case with embedded arguments The result of 1 + 1 should be 2 The result of 1 + 2 should be 3 Template with embedded arguments [Template] The result of ${calculation} should be ${expected} 1 + 1 2 1 + 2 3
When built-in arguments are used with templates, the number of arguments in the template keyword name must
match the number of arguments it is used with.
However, the argument names do not have to match the arguments of the original keyword, and it is also possible to use completely different arguments:
*** Test Cases *** Different argument names [Template] The result of ${foo} should be ${bar} 1 + 1 2 1 + 2 3 Only some arguments [Template] The result of ${calculation} should be 3 1 + 2 4 - 1 New arguments [Template] The ${meaning} of ${life} should be 42 result 21 * 2
The main advantage of using built-in arguments with templates is that the names of the
arguments are explicit.
When using regular arguments, a similar effect can be achieved by naming the columns that contain the arguments.
This is illustrated in the section
Data-driven Style
, and you can also
combine
named columns and built-in arguments.
*** Settings *** Documentation Flasky App Login DD Test Resource users/users.resource Suite Setup Setup Suite Force Tags ui login *** Variables *** *** Keywords *** Create Unique User &{unique_user}= Generate Unique User Set Suite Variable ${unique_user} Setup Suite Create Unique User Register User user=${unique_user} Test Setup Tasks Start Chromium Browser Test Teardown Tasks Close Browser Providing ${username} and ${password} Title Should Be ${expected} Open Browser To Login Page Log ${username} Log ${password} Input Username ${username} Input Password ${password} Submit Credentials ${title}= Get Title Log ${title} Should Be Equal ${title} ${expected} *** Test Cases *** Login With Credentials [Documentation] A test case that covers both ... valid, invalid and missing ... credentials entry [Template] Providing ${username} and ${password} Title Should Be ${expected} ${unique_user.username} ${unique_user.password} User Information - Demo App WRONG WRONG Login Failure - Demo App ${unique_user.username} WRONG Login Failure - Demo App WRONG ${unique_user.password} Login Failure - Demo App ${EMPTY} ${EMPTY} Log In - Demo App ${unique_user.username} ${EMPTY} Log In - Demo App ${EMPTY} ${unique_user.password} Log In - Demo App WRONG ${EMPTY} Log In - Demo App ${EMPTY} WRONG Log In - Demo App
Such a set of tests is considered one text case.
robot login.robot
============================================================================== Login :: Flasky App Login DD Test ============================================================================== Login With Credentials | PASS | ------------------------------------------------------------------------------ Login :: Flasky App Login DD Test | PASS | 1 test, 1 passed, 0 failed ============================================================================== Output: /robot/src/tests/ui/output.xml Log: /robot/src/tests/ui/log.html Report: /robot/src/tests/ui/report.html
Inside this test case, the keyword Providing ${username} and ${password} Title Should Be ${expected} will be executed eight times, and the log will show the argument values already substituted, for example:
Providing WRONG and WRONG Title Should Be
Login Failure - Demo App
…
If the solution with one test case for all variants of entered data is not suitable, you can split the test case into several.
Since the same template will be used everywhere, it is appropriate to use
Test Template
and not write everywhere
[Template]
The following example uses the code from
the previous
with the difference that in *** Settings *** Test Template is added and the test case is divided into three parts by the type of entered credentials.
*** Settings *** … Test Template Providing ${username} and ${password} Title Should Be ${expected} … *** Test Cases *** With Valid Credentials ${unique_user.username} ${unique_user.password} User Information - Demo App With Invalid Credentials WRONG WRONG Login Failure - Demo App ${unique_user.username} WRONG Login Failure - Demo App WRONG ${unique_user.password} Login Failure - Demo App With Missing Credentials ${EMPTY} ${EMPTY} Log In - Demo App ${unique_user.username} ${EMPTY} Log In - Demo App ${EMPTY} ${unique_user.password} Log In - Demo App WRONG ${EMPTY} Log In - Demo App ${EMPTY} WRONG Log In - Demo App
Compatible with built-in arguments, Test Template and named columns
*** Settings *** Documentation Flasky App Login DD Test Resource users/users.resource Suite Setup Setup Suite Force Tags ui login Test Template Providing ${username} and ${password} Title Should Be ${expected} *** Variables *** *** Keywords *** Create Unique User &{unique_user}= Generate Unique User Set Suite Variable ${unique_user} Setup Suite Create Unique User Register User user=${unique_user} # To reduce variable names two new # variables are created here ${VALID USER}= Set Variable ${unique_user.username} Set Suite Variable ${VALID USER} ${VALID PASSWD}= Set Variable ${unique_user.password} Set Suite Variable ${VALID PASSWD} Test Setup Tasks Start Chromium Browser Test Teardown Tasks Close Browser Providing ${username} and ${password} Title Should Be ${expected} Open Browser To Login Page Log ${username} Log ${password} Input Username ${username} Input Password ${password} Submit Credentials ${title}= Get Title Log ${title} Should Be Equal ${title} ${expected} *** Test Cases *** USERNAME PASSWORD EXPECTED TITLE Valid Credentials ${VALID USER} ${VALID PASSWD} User Information - Demo App Invalid User Name invalid ${VALID PASSWD} Login Failure - Demo App Invalid Password ${VALID USER} invalid Login Failure - Demo App Invalid User Name and Password invalid invalid Login Failure - Demo App Empty User Name ${EMPTY} ${VALID PASSWD} Log In - Demo App Empty Password ${VALID USER} ${EMPTY} Log In - Demo App Empty User Name and Password ${EMPTY} ${EMPTY} Log In - Demo App Empty User Name Invalid Password ${EMPTY} invalid Log In - Demo App Invalid User Name Empty Password invalid ${EMPTY} Log In - Demo App
Such a test case is treated as nine separate tests.
| Robot Framework | |
| Basics | |
| Login Test | |
| Variables | |
| Pass Args to KW |