Search code examples
pythonc#robotframeworkselenium2library

Robot framework : how to add variable to your declared variable


How to add variable to your declared variable in robot framework?

I have a lot of table variables in my script. Below is a sample

*** Variable ***
${Amount1_Column} xpath=//div[@id='*GFtable***0***EventDealDataValidationMask***report***unfixedData']/table/tbody/tr[1]/td[4]/div/table/tbody/tr[3]/td
${Amount2_Column}  xpath=//div[@id='*GFtable***0***EventDealDataValidationMask***report***unfixedData']/table/tbody/tr[1]/td[6]/div/table/tbody/tr[3]/td
${CounterParty_Column}  xpath=//div[@id='*GFtable***0***EventDealDataValidationMask***report***unfixedData']/table/tbody/tr[1]/td[90]/div/table/tbody/tr[3}]/td
${CurrencyPair_Column}  xpath=//div[@id='*GFtable***0***EventDealDataValidationMask***report***unfixedData']/table/tbody/tr[1]/td[76]/div/table/tbody/tr[3}]/td
${SpotRate_Column}  xpath=//div[@id='*GFtable***0***EventDealDataValidationMask***report***unfixedData']/table/tbody/tr[1]/td[13]/div/table/tbody/tr[3]/td

Then in my test cases I use get element count to count my table row and use that to my variables like the sample below

${Count}  get element count  xpath=//div[@id='*GFtable***0***EventDealDataValidationMask***report***unfixedData']/table
set suite variable  ${New_Count}  ${Count}

Now I use the ${New_Count} variable to my declared variable like the sample below

*** Variable ***
${Amount1_Column}  xpath=//div[@id='*GFtable***0***EventDealDataValidationMask***report***unfixedData']/table/tbody/tr[1]/td[4]/div/table/tbody/tr[${New_Count}]/td
${Amount2_Column}  xpath=//div[@id='*GFtable***0***EventDealDataValidationMask***report***unfixedData']/table/tbody/tr[1]/td[6]/div/table/tbody/tr[${New_Count}]/td

Upon running the script, my variable isn't recognized.


Solution

  • Disclaimer: I wouldn't really recommend your approach, some alternatives suggested at the end.

    That variable is not recognized because of the execution order; the framework first goes over and defines all variables, then executes suite setup keyword, then case setup ones, and then the ones in the cases.
    You probably see where this is heading to - you are using a var in the Variables section, but at this point no keyword has been ran yet, and the Set Suite Variable has not been executed; e.g. you are using an undefined variable.

    One might say, "ok, I'll define a placeholder for ${New_Count} so it is defined; then it will be re-defined in my case, and the locator will be good". Yes, no; the locator will be defined once - when it is evaluated in the Variables section, and will use the placeholder value. You change ${New_Count} later - but it doesn't change where it was used before in any way (e.g. it's not used as a pointer; string variable values are "static").

    So what can be done?

    • If you do want to use this approach, on calculating the value of ${New_Count} you also recalculate the locators you use it in; and call Set Suite Variable on them.
    • Another solution - only if the locators are in a separate file - might be to call the Reload Library keyword on it, forcing the framework to reevaluate their values with the new value of ${New_Count}; but I don't know does it support .robot files, I personally haven't tried it.
    • you can have the variables in a python file, that calls BuiltIn().get_variable_value('${New_Count}') and returns a dynamically calculated value.
    • I personally like to use something like 1 & 3, but in RF - create a keyword "Return Selenium Locator For Element BlahBlah“, that uses a placeholder locator - never used directly for anything else, modify it based on conditions/arguments (like your count variable) and returns the prepared locator. Then the caller can use it for selenium keywords, or what not. (I think I have an old post with details how and why, explaining other benefits - like how this keywords can also verify the element is actually present, etc.)