Assign a variable within the keyword "Run Keywords" possible? - testing

following code is producing some problem:
API Setup
[Arguments] ${url} ${username} ${password} ${run}=True ${fail}=False
Run Keyword If ${run}
... Run Keywords
... ${passed}= Run Keyword And Return Status Setup ${url} ${username} ${password}
... AND Log To Console ${passed}
... AND Should Not Be Equal ${fail} ${passed}
When I try to execute that, my RF says: Variable '${passed}' not found.
The RED IDE also says
Multiple markers at this line:
• Variable 'passed' is used, but not defined
• Keyword name '${passed}=' contains variables. RED is unable to validate
arguments given to this keyword
Does the keywords "Run Keywords" not allow any assignments of values to variables and if so, is there any "best practice" way to do what I want to do?
Thanks!

The Run Keywords does not allow assignments, that's true. This comes from the parser - the purpose of the keyword is to run other ones; it comes to the line with the assignment (${passed}= Run...), tries to substitute the variable "passed" with its value so it can execute it, but at this point the var is still undefined - and it fails.
It looks like what you want to do is to run a particular keyword (Setup) only if a condition is true, and only if the condition is true then log its outcome, and assert it (the outcome) is the desired one.
This can be achieved by breaking up the block in two. The keyword Run Keyword If returns the value of the embedded keyword, so this will work:
${passed}= Run Keyword If ${run} Run Keyword And Return Status Setup ${url} ${username} ${password}
... ELSE Set Variable ${False}
If ${run} == True the Setup keyword will be ran, and {passed} will hold a True/False value did the execution pass. If ${run} != True we're setting ${passed} to False, just so it doesn't have a value of None (its value is not really important in this case, but doing that gives consistency in the datatypes it has).
And now the other two keywords can be in an if-block by themselves - do their work only when ${run} == True:
Run Keyword If ${run} Run Keywords Log To Console ${passed}
... AND Should Not Be Equal ${fail} ${passed}

It is true that Run Keywords does not allow variable assignment within
Make a keyword that contains everything inside Run Keywords and just call it instead.
For example
*** Test Cases ***
API Setup
[Arguments] ${url} ${username} ${password} ${run}=True ${fail}=False
Run Keyword If ${run} Keyword A
*** Keywords ***
Keyword A
# put everything you need here

Related

Expected list-like value, got string

I have written a keyword which calls a sub-keyword. Now the sub keyword is returning two values which I am trying to store it in an array assigned to main keyword. When I log to console the returned values, it gives an error message saying - Expected list-like value, got string
I have tried the below workarounds(failed):
1. Attempt1:
#{Items1} Run keyword if '${INACTIVEStateCount}'!='0' INACTIVE OTOID selector ${StateCount}
Log To console Values are ${Items1}
2. Attempt2:
#{Items1} Run keyword if '${INACTIVEStateCount}'!='0' INACTIVE OTOID selector ${StateCount}
${Items2} Create List #{Items1}
Log To console Values are ${Items2}
Main keyword:
#{Items1} Run keyword if '${INACTIVEStateCount}'!='0' INACTIVE OTOID selector ${StateCount}
${Items2} Create List #{Items1}
Log To console Values are ${Items2}
SubKeyword:
INACTIVE OTOID selector
[Documentation] Used to select Inactive OTOIDs
[Arguments] ${StateCount} ${LocatorWaitTime}=${defaultWait time}
:FOR ${INDEX} IN RANGE 1 ${StateCount}
\ ${Check}= Run keyword and return status Page should contain element xpath=//*#id='lookupFiberDetailsResult']/table/tbody/tr[${INDEX}]/td[4][text()='INACTIVE']
\ ${OTO_IDStatus} Run keyword if '${Check}'=='True' Get Text xpath=//*[#id='lookupFiberDetailsResult']/table/tbody/tr[${INDEX}]/td[4][text()='INACTIVE']
\ Log to Console Loop${INDEX} - OTOID:${OTO_IDStatus}
\ ${OTO_ID} Run keyword if '${OTO_IDStatus}'!='None' Get Text xpath=//*[#id='lookupFiberDetailsResult']/table/tbody/tr[${INDEX}]/td[2]
\ ${LineIdentifier} Run keyword if '${OTO_IDStatus}'!='None' Get Text xpath=//*[#id='lookupFiberDetailsResult']/table/tbody/tr[${INDEX}]/td[1]
\ Run keyword if '${OTO_IDStatus}'!='None' Log to Console OTOID is: ${OTO_ID}
\ Run keyword if '${OTO_IDStatus}'!='None' Log to Console OTOID is: ${LineIdentifier}
\ Run Keyword If '${OTO_IDStatus}'!='None' [Return] ${OTO_ID}
\ Run Keyword If '${OTO_IDStatus}'!='None' [Return] ${LineIdentifier}
\ Exit For Loop if '${OTO_IDStatus}'!='None'
What I intend to achieve:
I am making the sub-keyword return two values: OTOID and LineIdentifier and store it in an array. And then use these two values separately for further use.
Actual:
When I log to console the values stored in array then I get an error saying:
Expected list-like value, got string
The issue is that you are trying to store the return values from the sub keyword as an array/list but returning strings from it.
*** Keywords ***
Main keyword
${OTO_ID} ${LineIdentifier} Run keyword if '${INACTIVEStateCount}'!='0' INACTIVE OTOID selector ${StateCount}
INACTIVE OTOID selector
Return From Keyword If '${OTO_IDStatus}'!='None' ${OTO_ID} ${LineIdentifier}
This will return the values ${OTO_ID} and ${LineIdentifier} as individual variables and not arrays.
Please note that I've ignored the other steps in the sub keyword just to make the answer simpler.
The line(s) that needs to be replaced:
Run Keyword If '${OTO_IDStatus}'!='None' [Return] ${OTO_ID}
Run Keyword If '${OTO_IDStatus}'!='None' [Return] ${LineIdentifier}
Update:
If you want to strictly return the values as list, use below code
*** Keywords ***
Main keyword
${Identifiers} Run keyword if '${INACTIVEStateCount}'!='0' INACTIVE OTOID selector ${StateCount}
INACTIVE OTOID selector
${Identifiers} Create List
.
<Your FOR loop here>
.
\ Run Keyword If '${OTO_IDStatus}'!='None' Append to List ${identifiers} ${OTO_ID} ${LineIdentifier}
Exit For Loop If '${OTO_IDStatus}'!='None'
Return From Keyword If '${OTO_IDStatus}'!='None' ${Identifiers}
Reference : Robot User guide

Error in SeleniumLibrary.Input Text - used in if/else block

I have a problem with RobotFramework code. Im trying to make an If/ELSE and testing some functionalities but when I declare the Keyword I get the error:
"Keyword 'SeleniumLibrary.Input Text' expected 2 arguments, got 10."
I tried changing the variables of the Keywords but nothing.
*** Settings ***
Library SeleniumLibrary
*** Variables ***
${WEB} https://google.es #Url we are going to open
${BROWSER} chrome #Browser to use
${SELENIUM_DELAY} 1
*** Test Cases ***
Conditional Test q Different from 0 Equal to 0
*** Keywords ***
Open Browser
Log To Console Opening browser...
Open Browser ${WEB} ${BROWSER}
Maximize Browser Window
Conditional Test
[Arguments] ${textview} ${text} ${text2}
Open Browser
Input Text ${textview} ${text} if ${SELENIUM_DELAY} != 0
... ELSE Input Text ${textview} ${text2}
I just tried to make a condition that if the value of ${SELENIUM_DELAY} is different from 0, then write on google search a String.
The syntax for conditional execution is different, you have to use the keyword Run Keyword If, providing the keywords to run when the condition is true/false (the false is optional). Like this:
Run Keyword If ${SELENIUM_DELAY} != 0 Input Text ${textview} ${text}
... ELSE Input Text ${textview} ${text2}

Robotframework: Suite variable not found in 2nd test case

Hi does anybody know why I cannot reference suite variable defined in TC1 and then referencing it TC2 within one suite I am getting error : Variable not found
Running both tests is ok, but runnig tc1 and then tc2 will produce this error
Python 2.7.13
Ride: 1.7.3.1
Thanx a lot
TC1
TC2
Try next simple code and say if it works, main point here is where you define suite variable by Set Suite Variable, it should be in the first test case or in the one of the setups(Test/Suite Setup):
*** Settings ***
Library Collections
*** Test Cases ***
TestCase1
Log to Console ${EMPTY}
Set Suite Variable ${suite_variable} case1
Log To Console I'm in case 1: ${suite_variable}
TestCase2
Log to Console ${EMPTY}
${variables} Get Variables
Dictionary Should Contain Key ${variables} \${suite_variable}
Log To Console I'm in case 2: ${suite_variable}

How to run a particular keyword multiple times in a test case of robot framework using seleniumlibrary?

I want to execute two keywords in a test-case out of which, one keyword has to be executed only once and the other has to be executed multiple times. Please find the code below to understand the logic of the execution:
*** Settings ***
Test Setup OPEN CHROME BROWSER
Test Teardown CLOSE CHROME BROWSER
Test Template KEYWORD1
Force Tags Smoke
*** Test Cases *** userid userpass content
VALID CREDENTIAL userid#mysite.com mypass CONTENT A
CONTENT B
CONTENT C
*** Keywords ***
--------------------------------------------------------------------------
KEYWORD 1
[Arguments] ${userid} {userpass}
GO TO LOGIN PAGE
ENTER USERID
ENTER PASSWORD
CLICK ON LOGIN BUTTON
-----needs to run once and then KEYWORD 2 should run thrice---------------
KEYWORD 2
[Arguments] ${content}
CLICK ON CONTENT TILE ${content}
DO SOME ACTION
GO TO HOME
I want 'keyword 1' to be executed only once and 'keyword 2' to be repeated 3 times as per the content list. Please guide me how to handle this.
Current issue:
While continuing with second test it asks userid and userpass to be passed again.
What I want to achieve:
Login once into the web-portal(KEYWORD1). RUN KEYWORD 2 with CONTENT A as arguement, then with CONTENT B as arguement and finally with CONTENT C. I should not login for each time the content needs to be changed.
What you need is the Repeat Keyword from the BuildIn library.
Examples:
Repeat Keyword 5 times Go Back
Repeat Keyword ${var} Some Keyword arg1 arg2
Repeat Keyword 2 minutes Some Keyword arg1 arg2
You can create another keyword like below
Execute Keyword Multiple Times
[Arguments] ${keyword_name} #{params}
FOR ${i} IN #{params}
Run Keyword ${keyword_name} ${i}
END
and you can call it
Execute Keyword Multiple Times KEYWORD 2 CONTENT A CONTENT B ...
If You need to give more than one param you can use dict.
I suggest you another way: give to KEYWORD 2 n args and put a loop into it. The code will be more understandable.
*** Settings ***
Test Setup KEYWORD1 ${reg_userid} ${reg_userpass}
Test Teardown CLOSE CHROME BROWSER
Test Template KEYWORD2 ${content}
Force Tags Smoke
*** Test Cases *** content
VALID CREDENTIAL CONTENT A
CONTENT B
CONTENT C
*** Keywords ***
#------------------------KEYWORD 1 runs once--------------------------------
KEYWORD 1
[Arguments] ${userid} {userpass}
OPEN CHROME BROWSER
GO TO LOGIN PAGE
ENTER USERID
ENTER PASSWORD
CLICK ON LOGIN BUTTON
#------------------------KEYWORD 2 runs thrice-----------------------------
KEYWORD 2
[Arguments] ${content}
CLICK ON CONTENT TILE ${content}
DO SOME ACTION
GO TO HOME
***Variables***
${reg_userid} test#test.com
${reg_userpass} password

tcl tcltest unknown option -run

When I run ANY test I get the same message. Here is an example test:
package require tcltest
namespace import -force ::tcltest::*
test foo-1.1 {save 1 in variable name foo} {} {
set foo 1
} {1}
I get the following output:
WARNING: unknown option -run: should be one of -asidefromdir, -constraints, -debug, -errfile, -file, -limitconstraints, -load, -loadfile, -match, -notfile, -outfile, -preservecore, -relateddir, -singleproc, -skip, -testdir, -tmpdir, or -verbose
I've tried multiple tests and nothing seems to work. Does anyone know how to get this working?
Update #1:
The above error was my fault, it was due to it being run in my script. However if I run the following at a command line I got no output:
[root#server1 ~]$ tcl
tcl>package require tcltest
2.3.3
tcl>namespace import -force ::tcltest::*
tcl>test foo-1.1 {save 1 in variable name foo} {expr 1+1} {2}
tcl>echo [test foo-1.1 {save 1 in variable name foo} {expr 1+1} {2}]
tcl>
How do I get it to output pass or fail?
You don't get any output from the test command itself (as long as the test passes, as in the example: if it fails, the command prints a "contents of test case" / "actual result" / "expected result" summary; see also the remark on configuration below). The test statistics are saved internally: you can use the cleanupTests command to print the Total/Passed/Skipped/Failed numbers (that command also resets the counters and does some cleanup).
(When you run runAllTests, it runs test files in child processes, intercepting the output from each file's cleanupTests and adding them up to a grand total.)
The internal statistics collected during testing is available in AFACT undocumented namespace variables like ::tcltest::numTests. If you want to work with the statistics yourself, you can access them before calling cleanupTests, e.g.
parray ::tcltest::numTests
array set myTestData [array get ::tcltest::numTests]
set passed $::tcltest::numTests(Passed)
Look at the source for tcltest in your library to see what variables are available.
The amount of output from the test command is configurable, and you can get output even when the test passes if you add p / pass to the -verbose option. This option can also let you have less output on failure, etc.
You can also create a command called ::tcltest::ReportToMaster which, if it exists, will be called by cleanupTests with the pertinent data as arguments. Doing so seems to suppress both output of statistics and at least most resetting and cleanup. (I didn't go very far in investigating that method.) Be aware that messing about with this is more likely to create trouble than solve problems, but if you are writing your own testing software based on tcltest you might still want to look at it.
Oh, and please use the newer syntax for the test command. It's more verbose, but you'll thank yourself later on if you get started with it.
Obligatory-but-fairly-useless (in this case) documentation link: tcltest