0

I have the following css selector

${Table_Row}      css=.tr > td:nth-child(2)

This selector will get me the first instance in a table. The problem is that the table may contain hundreds of instances and I don't want to have hundreds of variables. How can I make the variable more dynamic, that I can pass another variable to determine the 'nth-child' count, without making it a keyword?

Here is a python example of what I mean:

table_row = ".tr > td:nth-child(%s)"

Then if I call this variable

table_row % 5

The result will be

.tr > td:nth-child(5)
2
  • why not create a keyword that accepts the row number as a parameter? Then you can just do get row 32. The logic for computing the locator could be in the keyword. Commented May 10, 2018 at 14:16
  • @BryanOakley This is actually what I am doing now but I just wondered if there is a simpler way to do it inline. Commented May 10, 2018 at 14:40

1 Answer 1

1

If this is something that is repeated often, and you want to centralize the logic and not have to deal with variables at all, then a Custom Locator Strategy,

An example inspired by your question:

*** Test Cases ***
Test Case
    Add Location Strategy   table   Custom Locator Strategy
    Page Should Contain Element table=3

*** Keywords ***
Custom Locator Strategy 
    [Arguments]    ${browser}    ${criteria}    ${tag}    ${constraints}
    ${element}=    Get Webelement   css=.tr > td:nth-child(${criteria}) 
    [Return]    ${element}

This will then work for all keywords that takes a locator as an input argument. The Custom Locator Strategy only needs to return an Web element.

An alternative that in my view fulfills the inline criteria, but in my opinion is not more readable (leave that to the reader) is to use the string object functions. They are described in and around the Advanced Variable Syntax section of the Robot Framework Guide:

*** Variables ***
${locator_template}    css=.tr > td:nth-child(%) 

*** Test Cases ***
TC
    Log    Locator Template: "${locator_template}"
    ${locator}    Set Variable    ${locator_template.replace("%", "9")}

    Log    Locator Variable: "${locator}"
    Log    Inline Variable: "${locator_template.replace("%", "9")}"
    Log    Locator Template: "${locator_template}"

This example shows how to use the object functions inline. As the Python String object has the method replace, it will provide for a stable way of replacing the same variable and using it's replace output for further assignment in keywords.

It will yield the following result:

Starting test: Robot.String Replace.TC
20180513 12:25:21.057 : INFO : Locator Template: "css=.tr > td:nth-child(%)
20180513 12:25:21.058 : INFO : ${locator} = css=.tr > td:nth-child(9)
20180513 12:25:21.059 : INFO : Locator Variable: "css=.tr > td:nth-child(9)"
20180513 12:25:21.060 : INFO : Inline Variable: "css=.tr > td:nth-child(9)"
20180513 12:25:21.061 : INFO : Locator Template: "css=.tr > td:nth-child(%)"
Ending test: Robot.String Replace.TC

As you can tell the replace function returns the result, and does not update the original string. This makes it useful for using as as reusable template.

Sign up to request clarification or add additional context in comments.

3 Comments

This is correct but it is similar to what I'm doing now. I was wondering if there is an option to do it inline without using a keyword in between.
Well @BeniKeyserman this is as close to your ask as it can get - the value is dynamic, based off the number you provide, and you are not creating any custom keywords for getting the locator - you'll be using the standard SeleniumLibrary's ones just by providing the number.
@BeniKeyserman I've updated the answer with an inline example. In my view the brevity of the inline replace function is offset by the reduced readability.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.