Variables from variables file - robotframework

I am trying to use variables from a variables phyton file.
I think I am doing everything as described in the user manual, yet, the variables remain unavailable to me.
This is the variables file
TEST_VAR = 'Michiel'
def get_variables(environment = 'UAT'):
if environment.upper() == 'INT':
ENV = {"NAME": "Bol.com INT",
"BROWSER": "safari",
"URL": "www.bol.com"}
else:
ENV = {"NAME": "Bol.com UAT",
"BROWSER": "firefox",
"URL": "www.bol.com"}
return ENV
I import this like this:
*** Settings ***
Variables Variables.py ${ENVIRONMENT}
Library Selenium2Library
Resource ../PO/MainPage.robot
Resource ../PO/LoginPage.robot
*** Variables ***
${ENVIRONMENT}
*** Keywords ***
Initialize suite
log ${TEST_VAR}
log start testing on ${ENV.NAME}
Start application
open browser ${ENV.URL} ${ENV.BROWSER}
Stop application
close browser
Both files are at the same level in the folder structure.
Yet the variables from the file are not available to me. Not even the normal variable.
Can someone tell me what I am doing wrong here?
Must be something small that I'm forgetting.
Many thanks.

When you use a variable file like this, you don't end up with a variable named ${ENV}. Instead, every key in the dictionary that you return becomes a variable.
From the robot framework user guide (emphasis added):
An alternative approach for getting variables is having a special get_variables function (also camelCase syntax getVariables is possible) in a variable file. If such a function exists, Robot Framework calls it and expects to receive variables as a Python dictionary or a Java Map with variable names as keys and variable values as values.
In this specific case that means that you will end up with the variables ${NAME}, ${BROWSER} and ${URL}.
If you want to set a variable named ${ENV}, you will have to make that part of the returned dictionary
# Variables.py
from robot.utils import DotDict
def get_variables(environment="UAT"):
...
return {
"ENV": DotDict(ENV)
}

Related

Robotframework : file_1.robot needs to update a variable in file_2.robot

I tried using the Set Global Variable keyword but I am not sure if I am doing this correct. I was hoping to make 2 files have access to this variable. Here is my variables section. I am using VS code with Robot plugin for syntax highlighting. The error show when I run this
is:
Invalid variable name 'Set Global Variable'.robotcode.diagnostics(ModelError)
*** Variables ***
Set Global Variable ${VERBOSE} 0
${SERIAL_PORT} None
Is there a special library I need to import to use Set Global Variable?
My use case is that I have 2 robot files both of them need to know if Verbose mode is enabled. I pass verbose to file_1.robot file via command line, I was hoping I could also pass the verbose variable to a Resource file_2.robot, but I am unable to do this because
in my second file there is no "command line argument to pass in to it"
Is there a way from file_1.robot I can set/update a variable in file_2.robot ?
For file one i can do this via command line, but for file 2 I was hoping something like this would exist:
Resource ../resources/Serial.robot -v Verbose:0
(in this case Serial.robot is the infamous file 2 )
To make things even simpler I dont need Verbose in File 1 , i Just need it to pass it on to the resource file somehow
Set Global Variable is a keyword that could be used inside test cases or custom keywords. What you need is to define variable (link to documentation).
I pass verbose to file_1.robot file via command line, I was hoping I could also pass the verbose variable to a Resource file_2.robot, but I am unable to do this because in my second file there is no "command line argument to pass in to it"
Nope, you are passing global variable visible from everywhere. Take a look at documentation about scopes and priorities for variables.
If you want to define once and use in multiple places you could create file with common variables and import in both files. Example:
Here you define:
# BaseVariables.robot
*** Variables ***
${VERBOSE} 0
And use:
# file_1.robot
*** Settings ***
Resource BaseVariables.robot
and in second file
# file_2.robot
*** Settings ***
Resource BaseVariables.robot

Robotframework, How to define a dynamic variable name

I want to Define variable having dynamic name.
For example
${${FILE}{VAR}} Create List // ${FILE} = TEST, ${VAR} = VAR
Then I want to get variable named '${TESTVAR}'.
Here is my Summarized code...
*** Settings ***
Library SeleniumLibrary
Library ExcelLibrary
Library Collections
*** Variables ***
${VAR}= VAR
*** Keywords ***
Open Document And Assign Variable
[Arguments] ${FILE}
Open Excel Document filename=${FILE} doc_id=doc_var
${${FILE}${VAR}} Create List # It doesn't work ..
The previous answer is not really accurate.
This can be achieved exactly with robot's "Variables inside variables" feature like so:
FOR ${idx} IN RANGE 3
${var_name} = Catenate SEPARATOR=_ var ${idx}
Set Suite Variable ${${var_name}} ${idx}
END
you get:
   var_1=1
   var_2=2
   var_3=3
Please note that variables resolution is happening only for keywords arguments (at least for robot version 3.1.2 that I am using), therefore either one of 'Set test variable', 'Set Suite Variable' or 'Set Global Variable' keywords must be used. The following won't work:
FOR ${idx} IN RANGE 3
${var_name} = Catenate SEPARATOR=_ var ${idx}
${${var_name}} = ${idx}
END
results in:
    No keyword with name '${${var_name}} =' found.
For your list case you just need to create a list variable and reassign it to dynamically named variable using the above mentioned keywords
This is currently not possible with Robot Framework. You can use "variables inside variables" to resolve the values of variables (see the documentation on this topic) but not to resolve/set the name of the variable itself.
Though I am afraid that would be confusing anyway. Maybe you can explain your motivations and people can come up with another solution for your problem.

Robot: assign variables in setup phase using Run Keywords

I'm trying to create a setup phase for a test case in which I assign variables. I know in order to do multiple keywords I need to use Run Keywords, but is it possible to set variables when doing this? For example:
*** Test Cases ***
Case1
[Setup] Run Keywords
... ${var1}= Keyword1
... AND ${var2}= Keyword2
obviously the above doesn't work because ${var1} and ${var2} are just treated as arguments to Run Keywords. Since they haven't been defined yet, setup fails.
No, you cannot. Even though you added "using Run Keywords", this question has the same answer as Is possible to create new variable in suite/test set up - Robot Framework?
You can use the Set Suite Variable keywork to do that.
set suite variable ${var1} Hello World
You might need to escape the variable...
set suite variable \${var1} Hello World
From the builtin library documentation:
If a variable already exists within the new scope, its value will be overwritten. Otherwise a new variable is created. If a variable already exists within the current scope, the value can be left empty and the variable within the new scope gets the value within the current scope.
The question here why are you trying to do this?
The way I do it, if I want to call keywords and set their outputs in variables
to reuse them in my test suite, I do the following:
*** Settings ***
Library BuiltIn
Suite Setup Initialize Variables
*** Keywords ***
Initialize Variables
${Argument1} = Set Variable some_value
${output1} = Keyword1 ${Argument1}
${output2} = Keyword2
${output3} = Keyword3 ${Argument1} other_value
*** Test Cases ***
Test Case 1
# Here you can use the variables that you initialized in the Suite Setup.
Log ${output1}
Log ${output2}
Log ${output3}
Test Case 2
# Also here you can use the same variables.
No Operation
Note: If you want to setup the variables for each test case, you can do it either in the settings section like this:
*** Settings ***
Test Setup Initialize Variables
Or you can use the setting in the test case itself (same as what you did in your question)
Test Case 1
[Setup] Initialize Variables
Note that "Initialize Variables" can take arguments as well if you need.

Why is the value of a suite variable lost after importing it from a resource file?

From what I read about variable scopes and importing resource files in robotframework doc i would expect this to work (python 2.7, RF 2.8.7):
Test file:
*** Settings ***
Resource VarRes.txt
Suite Setup Preconditions
*** Variables ***
*** Test Cases ***
VarDemo
Log To Console imported [${TODAY}]
*** Keywords ***
Resource file:
*** Settings ***
Library DateTime
*** Variables ***
${TODAY} ${EMPTY} # Initialised during setup, see keyword Preconditions
*** Keywords ***
Format Local Date
[Arguments] ${inc} ${format}
${date} = Get Current Date time_zone=local increment=${inc} day result_format=${format}
[Return] ${date} # formatted date
Preconditions
${TODAY} = Format Local Date 0 %Y-%m-%d
Log To Console inited [${TODAY}]
However the output is:
inited [2015-03-20]
imported []
RF documentation states:
Variables with the test suite scope are available anywhere in the test
suite where they are defined or imported. They can be created in
Variable tables, imported from resource and ....
which I think is done here.
If I add a line to keyword Preconditions like this, it works:
Preconditions
${TODAY} = Format Local Date 0 %Y-%m-%d
Set Suite Variable ${TODAY}
Log To Console inited [${TODAY}]
The reason is that in the first line a local variable is defined, instead of initialising the test suite variable declared in the variable table. A paragraph in RF doc hints to that:
Variables set during the test execution either using return values
from keywords or using Set Test/Suite/Global Variable keywords always
override possible existing variables in the scope where they are set
I think a major drawback of RF is that you cannot define variables dynamically in the variable table. Setting the scope of a variable from within a keyword is something I try to avoid.
For dynamic variables, you might to use a variable file in Python. See the section "Implementing variable file as Python or Java class" in the User Guide.
For example, I use a variables.py with:
if platform.system() in ['Darwin', 'Linux']:
OS_FAMILY = 'unix'
elif platform.system() == 'Windows':
OS_FAMILY = 'windows'
else:
OS_FAMILY = 'unknown'
OS_FAMILY_IS_UNIX = OS_FAMILY == 'unix'
OS_FAMILY_IS_WINDOWS = OS_FAMILY == 'windows'
Then in the Robot Tests I can use the dynamic variables ${OS_FAMILY}, ${OS_FAMILY_IS_UNIX}, and ${OS_FAMILY_IS_WINDOWS} anywhere.
You should be able to do create your ${TODAY} variable.

How can I tell robot framework not to log a keyword?

In a robot framework test case I set a variable and then do a process.
Because the setting of the variable is not a very interesting bit of information, I don't want to include that in my report.
| Verifying STUFF |
| | ${endpoint}= | set variable | STUFF
| | Verify
My report contains this:
KEYWORD: ${endpoint} = BuiltIn.Set Variable STUFF
But I would rather not have it there. How can I tell Robot Framework to just not log that line?
------edit------
It looks like this should do it:
pybot --removekeywords NAME:SetVariable testcase.txt
But the Set Variable keywords are still there.
(And yes, I upgraded my robot framework to 2.8.3 to take advantage of this function.)
The best you can do is to use
Set Log Level NONE
but it will still log all the keyword calls, just not anything inside those.
Or if you call a python function which calls another function, then the call to the second function is not logged.
Like this:
*** Settings ***
Library lib.py
*** Test Cases ***
demo
Set Log Level NONE
${a} foo
xyzzy
*** Keywords ***
xyzzy
qwerty
qwerty
No Operation
Log 123
and lib.py being like this:
def foo():
abc = bar()
return abc
def bar():
c = 1
print c
return c
The problem is that when you assign a variable like ${var} = Keyword, the name of the keyword in Robot Framework outputs is ${var} = Keyword, not Keyword as you would expect. If your keyword is from a library or a resource file, its name will also be included like ${var} = MyLibrary.Keyword. The latter is a feature but the former is a bug that is hopefully fixed in RF 2.9.
An easy workaround for the keyword name, for now, including the variable name is using wildcards. Something like this ought to work for you:
--RemoveKeywords 'name:* = BuiltIn.Set Variable'
You can use --removekeywords or --flattenkeywords option on pybot to remove the content of keyword So if you have e.g. keyword "foo" that contains lot's of logging keywords, you can set "--flattenkeywords name:foo" option to pybot, and In the log you'll only see the primary keyword, but no keywords inside it.
http://robotframework.googlecode.com/hg/doc/userguide/RobotFrameworkUserGuide.html?r=2.8.3#removing-and-flattening-keywords
If you use a python library, the following monkey-patching works for me:
from robot.libraries.BuiltIn import BuiltIn
from robot.output.logger import LOGGER
import types
def _nothing(*args, **kwargs):
pass
def disable_keyword_logging(self):
self._logging_methods = (LOGGER.start_keyword, LOGGER.end_keyword)
LOGGER.start_keyword = types.MethodType(_nothing,LOGGER)
LOGGER.end_keyword = types.MethodType(_nothing,LOGGER)
def enable_keyword_logging(self):
LOGGER.start_keyword, LOGGER.end_keyword = self._logging_methods
Then when this script is run:
Disable keyword logging
Log Hello world
Enable keyword logging
the "Log" keyword is not logged to the output but the output is.
If you really want nothing (also no debug/info/warn information logged by the called keywords), you will still have to set the log level to "NONE".
Robot Framework doesn't log "global" variables as part of a variable table. Global is in quotation marks because Set Global Variable actually is logged, but if you initialize your variable like so...
*** Variables ***
${endpoint} stuff
*** Keywords ***
...then it will not be in the Log. Additionally, if you don't want anyone to see the variable at all if they're just looking at the front end of your testing suite, you can bury it in a Resource file and the call the Resource file.
Robot Framework logs your Set Variable keywords and results because Set Variable implies that you're setting a variable dynamically and might be setting it based on the result of a keyword, in which case you'd probably want to know what the result of the keyword is. If you're just creating a static variable, then no extra work beyond the table is required. Is a dynamic variable a required part of your code?

Resources