I am a list which is - ['','','','Some-Value','',''] , I am trying to remove all the null/empty values from list so that the final result be ['Some-Value'].
Below is the code which I tried but so no luck so far
${list_size} = Get Length ${list}
For ${index} IN RANGE ${list_size}
${item} Get Form List ${list} ${index}
Run Keyword if '${item}' == '' Remove ${item} from list ${list}
enter code here
End
Can anyone help to solve this problem ? Thank you!
Robot framework enables you to use Evaluate keyword, and than it is just a python problem.
This code example produces the result you are looking for.
*** Variables ***
#{list_variable} ${empty} some text ${empty}
*** Test Cases ***
Replace a String
${cleared_list}= Evaluate [x for x in #{list_variable} if x]
Log ${cleared_list}
Related
I have a functioning Robot Framework test that scrapes the elements of a page and returns the link text. My problem is, some of these fields are empty and some of them have text. I do not care what the text is, however. This is an example of the output I get:
"Link Text="
"Link Text=" John Doe
"Link Text=" Jane Doe
In this case, I would only want the program to return items 2 and 3, and not Log item 1. Here is my code to achieve this right now.
TEST
${Count}= Get Element Count //a
Log To Console Total= ${Count} \n
FOR ${INDEX} IN RANGE 1 ${Count}-1
${text}= Get Text xpath=(//a)[${INDEX}]
${href}= Run Keyword And Return Status Get Element Attribute xpath=(//a)[${INDEX}] #href
Run Keyword If ${href} Log To Console ${INDEX}. "Link Text=" ${text}
... ELSE Log To Console NONE
END
So this does give me a pass, and I do get the link text I'm asking for. I just need to take out the blank entries. I know my loop is functional, but I can't figure out how to parse the blank fields. How can I do this? Any ideas? Please let me know, thanks so much!
In these situations I usualy use Get Length and test if greater than zero.
Here is your modified example:
TEST
${Count}= Get Element Count //a
Log To Console Total= ${Count} \n
FOR ${INDEX} IN RANGE 1 ${Count}-1
${text}= Get Text xpath=(//a)[${INDEX}]
${size}= Get Length ${text}
${href}= Run Keyword And Return Status Get Element Attribute xpath=(//a)[${INDEX}] #href
Run Keyword If ${href} and ${size} > 0 Log To Console ${INDEX}. "Link Text=" ${text}
... ELSE Log To Console NONE
END
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
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}
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
Suppose I have a code in python that generates a dictionary as the result. I need to write each element of dictionary in a separate folder which later will be used by other set of rules in snakemake.
I have written the code as following but it does not work!
simulation_index_dict={1:'test1',2:'test2'}
def indexer(wildcards):
return(simulation_index_dict[wildcards.simulation_index])
rule SimulateAll:
input:
expand("{simulation_index}/ProteinCodingGene/alfsim.drw",simulation_index=simulation_index_dict.keys())
rule simulate_phylogeny:
output:
ProteinCodingGeneParams=expand("{{simulation_index}}/ProteinCodingGene/alfsim.drw"),
IntergenicRegionParams=expand("{{simulation_index}}/IntergenicRegions/dawg_IR.dawg"),
RNAGeneParams=expand("{{simulation_index}}/IntergenicRegions/dawg_RG.dawg"),
RepeatRegionParams=expand("{{simulation_index}}/IntergenicRegions/dawg_RR.dawg"),
params:
value= indexer,
shell:
"""
echo {params.value} > {output.ProteinCodingGeneParams}
echo {params.value} > {output.IntergenicRegionParams}
echo {params.value} > {output.RNAGeneParams}
echo {params.value} > {output.RepeatRegionParams}
"""
The error it return is :
InputFunctionException in line 14 of /$/test.snake:
KeyError: '1'
Wildcards:
simulation_index=1
It seems that problems is with the params section of the rule because deleting it will eliminates the error but I can not figure out what is wrong with the params!
The solution: using strings as dictionary keys
One can guess from the error message (KeyError: '1') that some query in a dictionary went wrong on a key that is '1', which happens to be a string.
However, the dictionary used in the indexer "params" function has integers as keys.
Apparently, using strings instead of ints as keys to this simulation_index_dict dictionary solves the problem (see comments below the question).
The cause: loss of type information during workflow inference
The cause of the problem is likely that the integer nature (inherited from simulation_index_dict.keys()) of the value assigned to the simulation_index parameter of the expand in SimulateAll is "forgotten" in subsequent steps of the workflow inference.
Indeed, the expand results in a list of strings, which are then matched against the output of the other rules (which also consist in strings), to infer the values of the wildcards attributes (which are also strings). Therefore, when the indexer function is executed, wildcards.simulation_index is a string, and this causes a KeyError when looking it up in simulation_index_dict.