Test Template with Robot Framework cannot use variables - robotframework

I have some problems using the robotframework template,how to get variables passed to the template?
Here is my code:
*** Keywords ***
re-random-value
${random int} = Evaluate random.randint(1, 5)
[Return] ${random-num}
*** Test Cases *** test1
[Template] test template
re-random-value # random-num is return value from keywords re-random-value
*** Keywords ***
test template
[Arguments] ${random-num}
log ${random-num}
when I run the test case test1, The result is re-random-value, not the number of values returned by the keyword re-random-value I expected

The documentation on Robot Framework Test Templates states the following:
... test cases with template contain only the arguments for the
template keyword.
Within the context of a test template an argument can never be a keyword, the approach in the example won't work as is.
Assuming for a moment that the keyword may change per line/test case an intermediate keyword can be constructed that takes the name of the keyword as an argument and executes it. In the below updated version of your example this is what is done. Using the FOR loop to generate multiple values.
*** Test Cases ***
test1
[Template] test template
FOR ${index} IN RANGE 1 5
re-random-value # random-num is return value from keywords re-random-value
END
*** Keywords ***
test template
[Arguments] ${keyword}
${value} Run Keyword ${keyword}
Log To Console ${value}
re-random-value
${random int} = Evaluate random.randint(1, 5) modules=random
[Return] ${random int}
Results in (bear in mind the randomness of the values):
==============================================================================
test1 1
3
2
3
| PASS |
------------------------------------------------------------------------------

Related

Build a Robot Framework list from several keyword calls

I have several Robot Framework keywords that return a basic string.
#keyword
def keyword_one():
return 'one'
#keyword
def keyword_two():
return 'two'
In a robot test case, I try to build a list with this items, but I can't figure out how to do that is one line.
*** Test Cases ***
Test Case List
#{my_list}= Create List Keyword One Keywork Two
I tried several syntax but can't make it work.
Of course, something like below works (hardcoded values).
*** Test Cases ***
Test Case List
#{my_list}= Create List one two
Thanks for your help.
At the time that I write this, robot doesn't have the ability to call keywords inline, so what you want isn't directly possible.
You could write your own keyword to do this, however. The keyword can accept multiple keywords as arguments, and use run keyword from the built-in library to run the keyword.
For example, the following keyword definition creates a keyword that creates a list of results from multiple keywords:
Keyword written in python
If you want to try this out, name the file example.py
from robot.libraries.BuiltIn import BuiltIn
builtin = BuiltIn()
def create_list_from_keywords(*keywords):
result = []
for keyword in keywords:
result.append(builtin.run_keyword(keyword))
return result
Example test
*** Settings ***
Library example.py
*** Keywords ***
Keyword one
return from keyword one
Keyword two
return from keyword two
*** Test cases ***
Example
#{actual}= create list from keywords Keyword one Keyword two
#{expected}= create list one two
Should be equal ${actual} ${expected}
Robot-based keyword definition
If you're uncomfortable with python, here's a robot-based keyword definition:
Create list from keywords
[Arguments] #{keywords}
[Return] #{result}
#{result}= create list
FOR ${keyword} IN #{keywords}
${keyword result}= Run keyword ${keyword}
Append to list ${result} ${keyword result}
END
At the moment you are adding the keywords to the list, not the values returned from running those keywords
You would need to call the keywords to get the returned values and add them to the list e.g.
*** Test Cases ***
Test Case List
${keyword_one_val} Keyword One
${keyword_two_val} Keyword Two
#{my_list}= Create List ${keyword_one_val} ${keyword_two_val}
log to console ${my_list}
which outputs:
['one', 'two']

Looping in Robot Framework not incrementing/persisting a variable value

I have the code below that doesn't seem to persist the value of a variable. I am trying to increment it per call however the increment is not persistent in the variable.
*** Settings ***
Library lib.py
*** Variables ***
${x} 0
${inc} 1
*** Keywords ***
My keyword
${x} = evaluate ${x}+${inc}
Log To Console ${x}
# [return] ${x}
*** Test Cases ***
Run endless loop
Run Endless Loop My keyword
=================================================================
lib.py
from robot.libraries.BuiltIn import BuiltIn
def call_keyword(keyword):
return BuiltIn().run_keyword(keyword)
def run_endless_loop(f):
while True:
call_keyword(f)
Am curious what's happening here...
Your keyword works fine, only you are incrementing a local variable.
So in every iteration x will be 0 and it will be incremented to 1.
You have to store the returned value on suite level using the Set Suite Variable keyword.
*** Variables ***
${x} 0
${inc} 1
*** Test Cases ***
Test
My keyword
My keyword
My keyword
*** Keywords ***
My keyword
${x} = evaluate ${x}+${inc}
Set Suite Variable ${x}
Log To Console ${x}

Instantiate empty list in Robot Framework?

In the Robot Framework user guide, it states a variable value is a list or list-like, it is also possible to use it as a list variable like #{EXAMPLE} and There is also an empty list variable #{EMPTY} but I am not able to create an empty list. In the minimally reproducible example below, no matter how I set it up I get the error, TypeError: Expected argument 1 to be a list or list-like, got string instead in my test case. How can I create an empty list that doesn't re-assign itself to be a string?
*** Settings ***
Library Collections
Suite Setup Re-instantiate List
*** Variables ***
#{shouldBeList}= #{EMPTY}
*** Test Cases ***
Add something to the list
Collections.Append to list #{shouldBeList} Test
*** Keywords ***
Re-instantiate List
#{shouldBeList}= Create List ${EMPTY}
Set Suite Variable #{shouldBeList} #{shouldBeList}
# Results:
# Add something to the list | FAIL |
# TypeError: Expected argument 1 to be a list or list-like, got string instead.
I should have read the user guide more closely.
All variables should be assigned using the ${var} syntax, including lists and dicts. The #{var} and &{var} syntax should be used when you want to unpack the ${var}, using the # symbol if it's list-like and & if it's dict-like.
My above code works when written as:
*** Settings ***
Library Collections
Suite Setup Re-instantiate List
*** Variables ***
*** Test Cases ***
Add something to the list
Collections.Append to list ${shouldBeList} Test
*** Keywords ***
Re-instantiate List
${shouldBeList}= Create List
Set Suite Variable #{shouldBeList} #{shouldBeList}

Running test case In loop instead of copy the code

I have several tests in robot. the Idea of all the tests is identical:
- load some parameter to module
- run
- compare expected to actual results
The only thing is different from test to test, is the input and the expected results.
I would like to run the test repeatedly but with different inputs- and each iteration will be considered as different test case - Instead of copy the same code for all of the test cases and change the inputs.
each iteration will have its own test case tag \ documentation \ name (lets say the iteration number)
for example:
FOR ${TC} IN #{TCS} #TCS is array of inputs and expected output
*** Test Cases ***
# edit the tag \ documentation \ test name
module.load ${TC['input']}
${output} = module.run
isValid ${output} ${TC['expectedOutput']}
END
Is it possible in robot?
Thanks:)
The easyest way is to define a Keyword with Arguments and Return Values.
You can call this Keyword in every Tescase (with specified tag/documentation etc), with specified Arguments for the Test and check the Reuturn Values.
You could use the test template feature of the framework, especially the template tests with for loop.
Using it would give the following advantages:
No code duplication. You need one keyword with the test logic, that will be invoked with all list elements.
Each iteration will be independent from the other. So if one iteration fails, the next will be still executed.
It is flexible. The number of iterations is dynamic, you can create an input list in a test or suite setup phase.
Example, note that I am providing my inputs from a variable file.
*** Settings ***
Variables VariableFile.py
*** Test Cases ***
Math test
[Template] Multiplication by 2
FOR ${TC} IN #{TCS}
input=${TC.input} output=${TC.output}
END
*** Keywords ***
Multiplication by 2
[arguments] ${input} ${output}
${result}= Evaluate ${input}*2
Should Be Equal As Integers ${output} ${result} Calculated result:${result} is not equal with the expected:${output}
Variable file:
class DataSet(object):
def __init__(self, input, output):
self.input = input
self.output = output
def __str__(self):
return f'i:{self.input} - o:{self.output}'
TCS = [DataSet(1,2), DataSet(2,4), DataSet(3,6), DataSet(3,7), DataSet(4,8)]
This is the output:

Variable Declaration and Initialization in Robot Framework within a Test Cases block

I tried to Declare and Initialize a variable in Robot Framework using Selenium platform. But I'm getting an Error Keyword name cannot be empty.
I tried the following code
Integer:
*** Test Cases ***
Test Case 1
${item} ${0} # ${}
Boolean:
*** Test Cases ***
Test Case 2
${item} ${true} #${}
String:
*** Test Cases ***
Test Case 3
${item} Stackoverflow
Kindly assist me how to declare and initialize a variable within a Test Cases block in Robot Framework.
Reply for #Goralight
I'm getting an error
You need to use the Set Variable Keyword to assign values to Variables outside the Variable Header:
*** Test Cases ***
Test Case 1
${item} Set Variable ${0} #${}
${item} Set Variable ${true} #${}
${item} Set Variable Stackoverflow
The above assigns the variable you have given in your test cases to the correct value. (This will overwrite ${item} every time of course however) But this will assign the value, to the var ${item}.
Read the Docs about it here
Any questions please ask :)
In my opinion, the following is a more readable way to do it:
*** Test Cases ***
Test Case 1
${item} = Set Variable ${0} #${}
${item} = Set Variable ${true} #${}
${item} = Set Variable Stackoverflow
You will get an error if you do the following:
${item} = Stackoverflow
The reason is that this assignment is expecting a keyword Stackoverflow on right hand side.
Here is a working example of such assignment.
*** Test Cases ***
Test Case 1
${item} = Get My Value
Log ${item}
*** Keywords ***
Get My Value
${my text} = Set Variable Stackoverflow
[return] ${my text}

Resources