How to use dictionary instead of of list in robot framework

Currently Im using this code to get text from each boxes in column
I want to use dictionary instead of list in my code

${text_List}=  Create List #1st list
FOR  ${list}  IN RANGE  3  ${element_count}+1 #count depends on element present but it will be same as ${total_list_count} below
${list_text}=  Get Text  ${xpath}${list}
Append To List   ${text_List}  ${list_text}
END
#expected output= ['124', '1445', '1123', '456', '2354'] 

FOR  ${element}  IN RANGE  1  ${total_list_count}+1 #list count is same as  ${text_List} 1st list count
@{Text_List}  Create List
${web_elements}=  Get WebElements   ${xpath}
FOR ${ele}  IN  ${web_elements}
    ${element_txt}=  Get Text  ${ele}
     Append To List  ${Text_List}   ${element_txt}
 END
END

I tried with following code to use dictionary

*** Test Cases ***
Example Test Case
${text_dict}= Create Dictionary # Create an empty dictionary named ${text_dict}
FOR ${list} IN RANGE 3 ${element_count}+1
${list_text}= Get Text ${xpath}${list} # Get the text value of the ${list} element
Set To Dictionary ${text_dict} ${list_text} ${EMPTY} # Add the text value as key to the dictionary with an empty value
END

FOR  ${element}  IN RANGE  1  ${total_list_count}+1  # Loop through a range of values which is same as the count of elements in ${text_dict}
    ${web_elements}=  Get WebElements  ${xpath}  # Get a list of web elements using an xpath expression
    FOR ${ele}  IN  ${web_elements}  # Loop through the web elements
        ${element_txt}=  Get Text  ${ele}  # Get the text value of the web element
        ${key}=  Get From Dictionary  ${text_dict}  ${element}  # Get the key value from ${text_dict} using ${element} as index
        Set To Dictionary  ${text_dict}  ${key}  ${element_txt}  # Set the value of the key in ${text_dict} with ${element_txt}
    END
END 

With above code got error as:
Dictionary does not contain key ‘1’
because of following line i think

        ${key}=  Get From Dictionary  ${text_dict}  ${element}

I’m expecting output as

{'124': 'for loop text one by one for that column', '1445': 'for loop text one by one for next column', '1223': 'for loop text one by one for that next column', '456': 'for loop text one by one for that next column', '2354': 'for loop text one by one for that next column'}

Basically as the error reads, Its saying it doesn’t contain key ‘1’

Which ${element} will in your case equal either 1 or a number from that upto your list count+1 variable you’ve provided (your examples above don’t show the value assigned to these or how the count is returned) the line from above:

FOR ${element} IN RANGE 1 ${total_list_count}+1

as that’s the value your giving the kw to get from the dictionary:

${key}= Get From Dictionary ${text_dict} ${element}

for which if there’s no matching key when using the Get From Dictionary it will fail, unless you use a default as per usings for that keyword.

If you wanted to keep to getting by index then you could use the Get Dictionary Keys to get all keys, and then use Get From List keyword to get the key by index? both keywords are from the collections library, and then you could use the Get From Dictionary by passing in the return value (key) returned from Get From List, assuming getting by index is what you were trying to do, I’m sure you can also use the Evaluate keyword in a much cleaner way (don’t use it often and away from my computer to give you a proper example)

Note, Get From List will be 0 indexed.

Definitely worth considering a default on Get From Dictionary for cases it may not exists and handling that, without knowing/seeing more.

Worthy mention: Support for default is new in Robot Framework 6.0.

Hope that helps anyways (:

NOTE: Log and Log To Console are very good ways of debugging between statements, to full understanding the happenings to why sometimes you might get unexpected results, while testing your own code.

Hi @damies13 sorry for the duplicate you guessed it right i want to take keys by index position but and after getting the values i want to do sum column by column thats what im expecting I tried by using
FOR ${key} IN ${keys} but then i have to again put for loop to go by column index and then again for loop to print all elements with matching xpath as im new to robot framework i think its not right way to use 3-4 inside for loops
So I need some suggestions how can i acheive my expected result so i will adjust in my code accordingly

Hi Leo,

I think you were wanting to reply to @_daryl but tagged me instead.

what you could try; (this is a bit hackish but might do what you want)

Replace this line:

        ${key}=  Get From Dictionary  ${text_dict}  ${element}  # Get the key value from ${text_dict} 

with this:

        ${key}=  Evaluate    list(${text_dict})[${element}]

To explain what is happening here:

  • The Evaluate keyword can run any python code, but you can also use robot variables in the python code that’s evaluated with the Evaluate keyword
  • the list(${text_dict}) part used the python list function to convert the keys of a dictionary to a list of the key names
  • the [${element}] part is taking the nth item from the list we just created from the dictionary keys

While this may work it’s probably not the best way to do things as if there is java script running in the web page you are scraping this data from and it updates the page between when you added the key to the dictionary and when you update the value then there is a potential for a misalignment.

I would prefer to see you gather the keys to a list first then use the key as part of the xpath to get the value so you can be sure the key and value are related, only then add the key and value to the dictionary.

Perhaps the misalignment I mention will never happen and you’ll be lucky, I don’t know anything about the app your testing, but at least consider of you can select the value by the key or if you can select the key and value at the same time in the initial loop so your initial Set To Dictionary ${text_dict} ${list_text} ${EMPTY} can be replaced with Set To Dictionary ${text_dict} ${list_text} ${value}

Dave.

3 Likes

Hi @damies13 @_daryl thanks for the solution code worked with minor changes. How can I make dict of dict in above example

${Outer_Dict}   Create Dictionary
FOR  ${element}  IN RANGE  1  ${total_list_count}+1  # Loop through a range of values which is same as the count of elements in ${text_dict}
    ${web_elements}=  Get WebElements  ${xpath}  # Get a list of web elements using an xpath expression
    ${inner_dict}   Create Dictionary
    FOR ${ele}  IN  ${web_elements}  # Loop through the web elements
        ${element_txt}=  Get Text  ${ele}  # Get the text value of the web element
        ${key}=  Evaluate    list(${text_dict})[${element}]
        Set To Dictionary  ${inner_dict}  ${key}  ${element_txt}  # Set the value of the key in ${text_dict} with ${element_txt}
        Log  ${inner_dict} 
    END
    Set To Dictionary ${outer_dict} ${inner_dict} # Add the inner dictionary to the outer dictionary
END 

Here first I want make dictionary one by one of ${inner_dict} and then make 1 dictionary containing all dictionaries

Can you please suggest or show how can i achve in above code

HI Leo,

You were almost there, compare this line:

        Set To Dictionary    ${inner_dict}    ${key}    ${element_txt}  # Set the value of the key in ${text_dict} with ${element_txt}

to this line:

    Set To Dictionary    ${outer_dict}    ${inner_dict} # Add the inner dictionary to the outer dictionary

You’ll see that in the second one you missed having a key, so start by changing it to:

    Set To Dictionary    ${outer_dict}    element_${element}    ${inner_dict} # Add the inner dictionary to the outer dictionary

Then if you want the keys element_1, element_2, element_3, etc to be something else you can change it from there, but make sure it’s something different each time the FOR loop runs otherwise they will overwrite each other and you’ll end up with only the last ${inner_dict}

Dave.

@damies13 I want same keys which I have used in ${inner_dict}

${key}=  Evaluate    list(${text_dict})[${element}]

{{‘key1’: ‘value1’}, {‘key2’: ‘value2’},{‘key3’: ‘value3’}}

is this possible that we can take same keys as I want to do addition of only values in later part so is it possible

Hi Leo,

this is not a valid dictonary:

You could do this:

{‘key1’: {‘key1’: ‘value1’}, ‘key2’: {‘key2’: ‘value2’}, ‘key3’: {‘key3’: ‘value3’}}

Or you could put the ${inner_dict}'s into a list like this (note the square brackets):

[{‘key1’: ‘value1’}, {‘key2’: ‘value2’},{‘key3’: ‘value3’}]

Dictionary items always have to have a key.

Dave.

@damies13 when I Logged ${inner_dict} and ${outer_dict} it showed only 1st element text fetched I want to store all the get text data then how can i get then in a single variable as I want to do addition and some process on the fetched data

${Outer_Dict}   Create Dictionary
FOR  ${element}  IN RANGE  1  ${total_list_count}+1  # Loop through a range of values which is same as the count of elements in ${text_dict}
    ${web_elements}=  Get WebElements  ${xpath}  # Get a list of web elements using an xpath expression
    ${inner_dict}   Create Dictionary
    FOR ${ele}  IN  ${web_elements}  # Loop through the web elements
        ${element_txt}=  Get Text  ${ele}  # Get the text value of the web element
        ${key}=  Evaluate    list(${text_dict})[${element}]
        Set To Dictionary  ${inner_dict}  ${key}  ${element_txt}  # Set the value of the key in ${text_dict} with ${element_txt}
        Log  ${inner_dict} 
    END
    Set To Dictionary    ${outer_dict}    element_${element}    ${inner_dict} # Add the inner dictionary to the outer dictionary
  Log  ${outer_dict}
END

I want all get text data column by column so that i can use it further

Hi Leo,

Without seeing the data there’s no way I can figure out why.

I’d suggest you add

Log    ${text_dict}

before the outer FOR

then first line of the outer FOR add a Log for ${element}

And in the inner FOR add a log for ${key} just before Set To Dictionary

That should help you figure out why, it could be all the elements of ${text_dict} are the same? or it could be something else?

Hope that helps,

Dave.