As part of a Robot Framework test I would like to access multiple objects from my page with the same keyword. The xpath of the objects looks like this:
//div[#class='col-sm-4 ng-scope']//h1[#class='ng-binding'][contains(text(),'Bot1')]
//div[#class='col-sm-4 ng-scope']//h1[#class='ng-binding'][contains(text(),'Bot2')]
//div[#class='col-sm-4 ng-scope']//h1[#class='ng-binding'][contains(text(),'Botx')]
I've tried to set a list variable with the name of my test objects (elements)
*** Variables ***
#{TESTBOTS} = Bot1 Bot2 Botx
*** Keywords ***
Delete Bots
go to ${LANDINGURL}
Sleep 3s
Click Element //div[#class='col-sm-4 ng-scope']//h1[#class='ng-binding'][contains(text(), #{TESTBOTS})]
However, I get the following error:
FAIL Element with locator '//div[#class='col-sm-2 ng-scope']//h1[#class='ng-binding'][contains(text(),'${TESTBOTS')]' not found.
I'd really appreciate if you could point me to the right direction. Thanks!
The error message still does not seem to fit the snippet, I believe.
But anyway: with #{TESTBOTS} you unwrap the complete list. I would have expect an error like No element found with text 'Bot1 Bot2 Botx'
I think this should work iterating the list of testbots:
FOR ${testbot} IN #{TESTBOTS}
Click Element //div[#class='col-sm-4 ng-scope']//h1[#class='ng-binding'][contains(text(), ${testbot})]
END
Related
I'm trying to create a FOR Loop in Robot Framework that will click through a set of links on a page. Trying to avoid a string of "Click Element" lines and just make a loop out of it. I believe my base code is correct in the loop construction, but PyCharm is seeing the first line of the loop as its own keyword, which isn't right. It's not moving past that part. Any ideas here?
My variables are known, just stored off on another file.
Documentation Homepage
Library Zoomba.GUILibrary
Library Process
Resource ../../Pages/resource.robot
Suite Setup Browser Setup ${url}
*** Keywords ***
Menu Navigation
${list}= Create List ${TUAbout} ${TUAcademics} ${TUResearch}
:FOR ${item} IN #{list}
Wait For And Click Element ${item}
END
*** Test Cases ***
TC 001 Menu Navigation
Menu Navigation```
You need at least 2 spaces for the variables on the FOR line and FOR syntax has changed in more recent versions of RF so :FOR is deprecated syntax use just FOR e.g.
FOR ${item} IN #{list}
I believe that should be enough to fix the current error you're seeing
The source is this obstacle: https://obstaclecourse.tricentis.com/Obstacles/87912
What I got this far is:
*** Settings ***
Library Browser
Library XML
Library Collections
Library String
Documentation BE FAST AUTOMATE
*** Variables ***
${links}= <isbn>
${rechts}= </isbn>
*** Test Cases ***
Execute a for loop only three times
Open Browser https://obstaclecourse.tricentis.com/Obstacles/87912
Click id=loadbooks
${alles}= Get Text id=books
This one is mentioned: 'hard'
The Get Text literally gets all the text which is fine, but from that point I have no clue how the get the isbn (from the specific, or even ... any)
A bit further thanks to this page: Parse XML only returns first element
*** Settings ***
Library Browser enable_presenter_mode=False
Library XML
Library Collections
Library String
Documentation BE FAST AUTOMATE
*** Variables ***
##{ROBOTS}= 1 2 3
${links}= <isbn>
${rechts}= </isbn>
*** Test Cases ***
Find the isbn
Open Browser https://obstaclecourse.tricentis.com/Obstacles/87912
sleep 5s
Click id=loadbooks
${alles}= Get Text id=books
${x}= Parse Xml ${alles}
${el_my_value}= XML.Get Element ${x} .//isbn
Log ${el_my_value}
${first_text}= Get Element Text ${el_my_value}
but now I still need the isbn corresponding to the correct title.
because the response is: Multiple elements (6) matching './/isbn' found.
I don't think I should post this as you are suppose to build the answer to the exercise, not google it...
Nevertheless, here it goes.
The data is hidden and if you carefully look into the html of the page you will see that after clicking the button "Load books" a javascript function is kicked that will set the value into the xml and into a variable.
After knowing this information is very simple to get the value that we want just using simple robot + selenium:
*** Settings ***
Library SeleniumLibrary
*** Test Cases ***
Insert Correct ISBN
Open Browser https://obstaclecourse.tricentis.com/Obstacles/87912 Chrome
Click Element id=loadbooks
${isbnValue} Execute Javascript return isbn
Input Text id=isbn ${isbnValue}
I've a situation in my app where I need to click on file name from a /div table which will save the file name internally and gets displayed in a /div grid. Every time I run the automation, I need to click on a new file.
I don't have any problem in clicking the file to be saved.
But after the click, the app stores the file in a /div grid and I want to select the file that I added.
For this I used this approach:
I am storing the file name in a global variable ${g_ExtractedFileName}
For eg: XX_YY_Response_IdNum_48015_2020-07-27T12-18-44.334442.txt
My complete Xpath to the file is something like this
xpath://div[#role='row']//span[contains(text(),'XX_YY_Response_IdNum_48015_2020-07-27T12-18-44.334442.txt')]
For this I have the below:-
${attachedFileXpath1}= set variable xpath://div[#role='row']//span[contains(text(),'
${attachedFileXpath2}= set variable ${g_ExtractedFileName}
${attachedFileXpath3}= set variable ')]'
${attachedFileXpath}= set variable ${attachedFileXpath1}${attachedFileXpath2}${attachedFileXpath3}
click element ${attachedFileXpath}
This throws an error
SyntaxError: Failed to execute 'evaluate' on 'Document': The string
'//div[#role='row']//span[contains(text(),'XX_YY_Response_IdNum_48015_2020-07-27T12-18-44.334442.txt
')]'' is not a valid XPath expression.
When I don't use the variables and simply use (hard coded value for file name)
click element xpath://div[#role='row']//span[contains(text(),'XX_YY_Response_IdNum_48015_2020-07-27T12-18-44.334442.txt')]
It works correctly.
I also tried this but same error
${attachedFileXpath}= catenate ${attachedFileXpath1}${attachedFileXpath2}${attachedFileXpath3}
I am not sure when the 3 variables are concatenated, it cuts off the variable value to a new line causing this problem.
Any help is much appreciated.
The simplest approach is to simply use the replace functionality that is already present in Robot Framework variables. The below example will result in an Element not found error, but that is expected.
*** Settings ***
Library SeleniumLibrary
*** Variables ***
${g_ExtractedFileName} XX_YY_Response_IdNum_48015_2020-07-27T12-18-44.334442.txt
*** Test Cases ***
Use Global String in Locator
Open Browser https://google.com chrome
click element xpath://div[#role='row']//span[contains(text(),'${g_ExtractedFileName}')]
[Teardown] Close All Browsers
Simply create keyword which accept the file name as argument and returns complete valid xpath expression. It will be re-usable and elegant solution -
*** Test case ***
Select file saved in div grid
${attached_file_xpath}= GetAttachedFileXpath ${File_Name}
Click Element ${attached_file_xpath}
*** Keywords ***
GetAttachedFileXpath [Arguments] ${File_Name}
return from keyword xpath://div[#role='row']//span[contains(text(),'${File_Name}')]
in Katalon is a very nice way to parameterize the selectors for GUI elements, so that you can easily select very similar elements with the help arguments. I want to do something similar like that in Robot Framework.
EDIT: Better example, that is more easy to understand:
We have several GUI elements we have to interact with when testing. As the elements' selectors are very similar, we want to parameterize specific parts of it. In this case, we want to parametrize the $(selector) part of the selector:
*** Variables ***
$(overview.element} //div[contains(#class, $(selector)')]
We want to be able to do that, so that we can avoid something like that
*** Variables ***
$(overview.home} //div[contains(#class, home')]
$(overview.settings} //div[contains(#class, settings')]
$(overview.overview} //div[contains(#class, overview')]
We want to give that parameter within the test cases. Means: We can specify which element we want to select. Something like that:
[Arguments] ${selector}
Click $(overview.element)(${selector})
Is that possible? And if yes: How?
You can use the built-in keyword Replace variables to perform the substitution before using the locator. For this to work you'll have to escape the variable reference when defining ${overview.element}
Example:
*** Variables ***
${overview.element} //div[contains(#class, \${selector}')]
*** Keywords ***
Example keyword
[Arguments] ${selector}
${locator}= Replace variables ${overview.element}
log locator is ${locator}
*** Test cases ***
Example
example keyword settings
When you run the above, the log should show this:
Badly need your help. In Vehicle ID column, I would like to find a vehicle and once it finds it, it will click on it... How can I do that in Robot Framework? What approach should i be using?
For looping in table you can use xpath easily:
*** Test Cases ***
Stackoverflow Test
[Tags] #InDevelop
Go To https://www.w3schools.com/html/html_tables.asp
Wait Until Element Is Visible id=customers ${global_timeout}
:FOR ${index} IN RANGE 2 8
\ Wait Until Element Is Visible xpath=//*[#id="customers"]/tbody/tr[${index}]/td[1] ${global_timeout}
\ ${var} = Get Text xpath=//*[#id="customers"]/tbody/tr[${index}]/td[1]
\ Log ${var}
In order to click the correct element, you probably need to compare the variable content with your expected value. That can be done this way:
${areYouMyLine} = Run Keyword and Return Status Should Be Equal As Strings ${var} Island Trading
Run Keyword If ${areYouMyLine} Click Elementxpath=//*[#id="customers"]/tbody/tr[${index}]/td[1]
And also don't forget to Exit your For Loop since you found your element.
Exit For Loop
However this is not the best practice. You probably should go to your product team asking for some data attributes which will help you to find your line. Alternatively, if you know your table content, put it into a list and use For In Loop instead. Good stuff about loops can be found here: https://blog.codecentric.de/en/2013/05/robot-framework-tutorial-loops-conditional-execution-and-more/