robot framework selenium How to retrieve a key from a diccionary - python

Recently I am attempting doing automation test in python with selenium-robot framework in two different browsers, but I am having an error when i try log the Alias of a Browser. The error says: "Dictionary '#{alias}' has no key '1'".
The code is this on:
*** Settings ***
Library SeleniumLibrary
*** Variables ***
${url} http://google.com
${browser} chrome
*** Test Cases ***
TC to demostrate Browser Operation Keywords in Robot Framework
[Documentation] TC to demostrate Browser Operation Keywords in Robot Framework
Open Browser http://google.com Chrome alias=ChromeRCV
Maximize Browser Window
Open Browser about:blank ff alias=RCVFF
&{alias} Get Browser Aliases
Log #{alias}[1]
#{browser_ID} Get Browser Ids
Log #{browser_ID}[1]
Switch Browser 1
Input Text //*[#id="tsf"]/div[2]/div[1]/div[1]/div/div[2]/input RCVAcademy
Sleep 4s
Switch Browser #{alias}[1]
Go To http://salesforce.com
Close All Browsers

This is due to how Robot interprets the variables. Since you have written #{alias}[1] Robot assumes that the value on index 1 of list alias is also a list. To avoid this issue in future, think first what you want to get out from the variable before assigning the $, # or &. You can see better explanation in the Robot Framework User Guide.
Consider the below example
&{DICT}= {"key1": "value1", "key2": "value2"}
# Get a list of keys
#{KEYS}= #{DICT.keys}
# ==> #{KEYS}= ["key1", "key2]
# Get a value from dictionary
${VALUE}= ${DICT}[key1]
# ==> ${VALUE}= value1
# Get a value from list
${VALUE}= ${LIST}[0]
# ==> ${VALUE}= key1
As you can see, only when returning a list value, are we using the # sign. This is because whenever using the # sign, Robot will interpret the given value as a list of multiple values and attempt to pass each value separately - This is also why normally lists are passed with $ as arguments to make Robot pass them as single variable instead of multiple separate values.
Additionally you are attempting to return a value from a dictionary with a list-like index. This will not work that way - You'll either have to access the value based on the key or then as a list of keys or values.
Since you only need the key to access the browser with the alias, you might as well simply use the following
Log ${aliases.keys()}[1]
# or to log everything in the dictionary
Log ${aliases}

It appears you have misunderstood the return value of the Get Browser Aliases - it returns a dict where the key is the alias you have given to an instance, and the value is the index.
Thus when you have typed [1] you are targeting the alias 1 (integer), but that's not one of the aliases you've set - and thus it's not a key in that dictionary, and thus - the error you got.
Change to this - the "ChromeRCV" is an alias you actually have, and it should work:
Log #{alias}['ChromeRCV']

Related

How to Use IF and ELSE in Robot Framework

Create user //Is my test case name
${random_string}= Generate Random String 8 [LOWER]
Set Global Variable ${random_string}
${body}= create dictionary email=${random_string}#mail.com firstName=${random_string} lastName=${random_string} role=ADMIN
${response}= Post On Session mysession /user json=${body} headers=${headers} //This is One Response for POST Method
${getuserresponse}= GET On Session mysession /user headers=${headers} //This is 2nd response for GET method which return all the users
FOR ${i} IN #{getuserresponse.json()}
#Validation
IF ${i['firstName']} == ${random_string} // I want to check weather GET Response contains email that I send from POST request
Log User Created Successfully
ELSE
Log User Not Created Successfully
END
Instead it gives me Error as
Evaluating IF condition failed: Evaluating expression 'ptrmipuy'(this is random_string) failed: NameError: name 'ptrmipuy' is not defined nor importable as module
Your conditions cannot have sequences with two or more spaces, since that's what robot uses to parse a statement. Everywhere you have == it needs to be ==
Also, your expressions either need to quote the string values or you can use the special syntax that converts the robot variables into python variables.
IF "${i['firstName']}" == "${random_string}"
-or-
IF $i['firstName'] == $random_string
This is covered in the documentation for the BuiltIn library, in a section titled Evaluating Expressions
Try below snippet of if else, if it works then copy paste this syntax and replace your variable. Also print your variable before comparing, if it has extra quotes, then you might get that error.
Also you should have only space before and after this symbol "=="
*** Test Cases ***
Testifelse
${Variation}= Set Variable NA
IF "${Variation}" == "NA"
Log if
ELSE
Log else
END

How to programmatically write a while loop in Robot Framework 4.0?

Scenario - I have a file with x number of alphabets (a, b, c, d, e, f).
I want to take this alphabets and write it into a list or a dictionary. The file can end at any alphabet but the loop must stop if it has picked up the last alphabet and there is no other alphabets.
Each alphabet must be captured individually and appended to the list/dictionary and not using variables like what is the length of file as we don't know this and it will always change.
Run loop until file is empty and add the contents into a list/dictionary. The dictionary can be as {1:a,2:b,3:c,4....}.
Maybe a case of using Exit For Loop If?
There is no while loop in the framework. What you can do is the following:
If this is file.txt:
a,b,c,d,e,f
This is how you could read each letter and put it into a dictionary.
Read the file as whole.
Split it based on the structure of the file.
Loop through the list got by the splitting.
*** Settings ***
Library OperatingSystem
Library Collections
*** Test Cases ***
Test
&{dict}= Create Dictionary
${key}= Evaluate 0
${file}= Get File file.txt
${splitted}= Evaluate """${file}""".split(',')
FOR ${letter} IN #{splitted}
${key}= Evaluate ${key} + 1
Set To Dictionary ${dict} ${key} ${letter}
END
Log ${dict}
As for a web example it depends on the application but here is a general approach. This test will open Stack Overflow and get all questions then log everything about them. It will only fetch the first page but you could loop (FOR) through all pages similarly.
Define a locator that would match all "records".
Get a list of records by using the Get WebElements keyword.
Loop through the list and apply logic.
*** Settings ***
Library SeleniumLibrary
*** Test Cases ***
Web Example
Open Browser https://stackoverflow.com/questions Headless Firefox
${questions}= Get WebElements //*[starts-with(#id, "question-summary-")]
FOR ${q} IN #{questions}
Log ${q.text}
END
[Teardown] Close Browser

No Keyword with name 'Get Json Value' Found Error or any Keywords that I use in HttpLibrary.HTTP in Robot Framework

I am using Robotframework-httplibrary for automating API calls which in this case I want to get the value of the token produced by POST method. So that I can use it on the PUT method to change the password. but unfortunately I've been enountering this error that keywords are not found even though I already declared the library.
This is a quick example
*** Settings ***
Library HttpLibrary.HTTP
Library Collections
Library JSONLibrary
Library SeleniumLibrary
*** Variables ***
${web_service}= http://10.0.50.168:18000
*** Test Cases ***
Create Large JSON Document
${document}= Catenate
... {
... "token" : "oPVo3b3NdkW8uDL2tiyZii"
... }
Should Be Valid JSON ${document}
${result}= Get Json Value ${document} token
Should Be Equal ${result} "oPVo3b3NdkW8uDL2tiyZii"
You have set python-3.x as a question tag so I assume you're running Python 3.x on your machine. The HttpLibrary (robotframework-httplibrary package) is made for Python 2.x so it's not compliant with your version. There are numerous renamed functions and old syntax exception handling done within that library so there is no way for you to run it using Python 3.
You may either seek a different approach or downgrade your machine's Python & Robot Framework installations into Python 2.X compliant versions.
I see you want to call Should Be Valid JSON and Get Json Value. This can be achieved without the HttpLibrary as well:
You may employ the Python's json library's json.loads() to validate JSON. If it's not valid json, it will raise an exception.
Instead of Get Json Value you can just store the JSON into a dictionary and read the appropriate field.
Here is an example of validating JSON format, fetching token from the JSON and then asserting it is as expected:
*** Test Cases ***
Create Large JSON Document
${document}= Catenate
... {
... "token" : "oPVo3b3NdkW8uDL2tiyZii"
... }
# Verify json is a valid format and set it to dictionary:
&{JSON}= Evaluate json.loads('''${document}''') json
# Get token from JSON
${result}= Set Variable ${JSON['token']}
Should Be Equal ${result} oPVo3b3NdkW8uDL2tiyZii

Robot framework - generate random data

I have a problem with generating the random string in robot. I am very new in robot and really dont know how to figure it out..
I found some solutions here and I tried to follow then, but I am doing something wrong obviously..
I got this error message in console: No keyword with name '${random_string} = Generate Random String' found.
My test case:
*** Settings ***
Library String
Resource resource.robot
*** Test Cases ***
Add New Project
${random_string} = Generate Random String 12 [LOWER]
Fill In Project Mandatory Fields ${random_string} descriptiondunno
Verify Added Project
[Teardown] Close Browser
In the resource file I have defined the keywords I am using in test:
Fill In Project Mandatory Fields
[Arguments] ${random_string} ${description}
Wait Until Element Is Visible ${PROJECT TITLE}
Input Text ${PROJECT TITLE} ${random_string}
and also:
Verify Added Project
[Arguments] ${random_string}
Click Element ${PROJECTS}
Table Should Contain ${GRID} ${random_string}
I really appreciate any help, because I am really lost in this now :(
Thanks!
What are you using as a separator? Just spaces? If so, maybe increase to using four spaces to clearly separate things
Based on the error it seems to think
${random_string} = Generate Random String 12 [LOWER]
is a keyword, this is not what you want, you only want it to consider Generate Random String a keyword.
Try the below and let us know what happens:
${random_string}= Generate Random String 12 [LOWER]

grabbing HTTP GET parameter from url using Box API in python

I am dealing with the Box.com API using python and am having some trouble automating a step in the authentication process.
I am able to supply my API key and client secret key to Box. Once Box.com accepts my login credentials, they supply me with an HTTP GET parameter like
'http://www.myapp.com/finish_box?code=my_code&'
I want to be able to read and store my_code using python. Any ideas? I am new to python and dealing with APIs.
This is actually a more robust question than it seems, as it exposes some useful functions with web dev in general. You're basically asking how to separate my_code in the string 'http://www.myapp.com/finish_box?code=my_code&'.
Well let's take it in bits and pieces. First of all, you know that you only really need the stuff after the question mark, right? I mean, you don't need to know what website you got it from (though that would be good to save, let's keep that in case we need it later), you just need to know what arguments are being passed back. Let's start with String.split():
>>> return_string = 'http://www.myapp.com/finish_box?code=my_code&'
>>> step1 = return_string.split('?')
["http://www.myapp.com/finish_box","code=my_code&"]
This will return a list to step1 containing two elements, "http://www.myapp.com/finish_box" and "code=my_code&". Well hell, we're there! Let's split the second one again on the equals sign!
>>> step2 = step1[1].split("=")
["code","my_code&"]
Well lookie there, we're almost done! However, this doesn't really allow any more robust uses of it. What if instead we're given:
>>> return_string = r'http://www.myapp.com/finish_box?code=my_code&junk_data=ohyestheresverymuch&my_birthday=nottoday&stackoverflow=usefulplaceforinfo'
Suddenly our plan doesn't work. Let's instead break that second set on the & sign, since that's what's separating the key:value pairs.
step2 = step1[1].split("&")
["code=my_code",
"junk_data=ohyestheresverymuch",
"my_birthday=nottoday",
"stackoverflow=usefulplaceforinfo"]
Now we're getting somewhere. Let's save those as a dict, shall we?
>>> list_those_args = []
>>> for each_item in step2:
>>> list_those_args[each_item.split("=")[0]] = each_item.split("=")[1]
Now we've got a dictionary in list_those_args that contains key and value for every argument the GET passed back to you! Science!
So how do you access it now?
>>> list_those_args['code']
my_code
You need a webserver and a cgi-script to do this. I have setup a single python script solution to this to run this. You can see my code at:
https://github.com/jkitchin/box-course/blob/master/box_course/cgi-bin/box-course-authenticate
When you access the script, it redirects you to box for authentication. After authentication, if "code" is in the incoming request, the code is grabbed and redirected to the site where tokens are granted.
You have to setup a .htaccess file to store your secret key and id.

Categories

Resources