How to iterate over a nested dictionary separating the values

Dear Team!

I am trying to automate a UI menu navigation verification and I do have a nested dictionary in a .py

tabs= {

'key_1': {
    'value_1',
    'value_2',
    'value_3'
},
'key_2': {
    'value_1',
    'value_2',
    'value_3',
    'value_4'
},
'key_3': {
    'value_1',
    'value_2'
}

I did create a keyword to load the keys into variables and similarly for values.

Keyword To Check Tab Visibility

FOR    ${key}    ${value}    IN    &{tabs}
    ${main_key}    Set Variable    ${key}
    Log    ${main_key}

           FOR    ${value}    IN    ${tabs}[${main_key}]
                      ${subkey}    Set Variable    ${value}
                      Log    ${subkey} 
          END
END

What I am trying to achieve here is to verify the main tab and subtab visibility in a menu navigation bar by looking up the locator by the text coming from the dictionary. The key would be the main menu element and the values are its subtabs.

However, as it is a multi value dictionary, when I iterate over the values based on their parent keys, it will load all the values to the same variable.
Like this:

${subkey}= {‘value_1’, ‘value_2’}

I would need to work with these values separately. Is there a way to split these values?

I am likely to over complicate this, if you could please bear with me, I would higly appreciate.

Thank you very much!

Hi Oliver,

Lets start with your data structure:

'key_1': {
    'value_1',
    'value_2',
    'value_3'
},

I’m not sure how python will handle this, even though its declared as a dictionary with the curly braces ({ and }) it’s not a dictionary, because you’ve only given values? not key and value pairs. but likewise you didn’t use square braces ([ and ]) so it’s not a list either.

From your first line I believe you intended the value of ‘key_1’ to be a dictionary, so this is the first thing to fix.

Now let’s move onto your robot script:
This line is good:

FOR    ${key}    ${value}    IN    &{tabs}

This line is unnecessary:

    ${main_key}    Set Variable    ${key}

This line is problematic:

           FOR    ${value}    IN    ${tabs}[${main_key}]
  • you already had declared ${value} and now you’re overwriting it, robot framework will happily do this but it becomes confusing
  • the structure of the FOR indicates your wanting to iterate a list, but the data should be a dictionary (see above), but you’ve use the scalar variable prefix ($) so ${tabs}[${main_key}] will probably evaluate to something like this ['value_1, value_2, value_3'], and ${subkey} will become 'value_1, value_2, value_3'
  • instead of ${tabs}[${main_key}] you could have used ${value}, but used the correct prefix, i.e. &{value} for dictionary or @{value} for list

So now you know what the problems are, here’s my attempt to fix it for you based on what I think you wanted

your data (tabs)

tabs= {
    'key_1': {
        'key_1_1': 'value_1',
        'key_1_2': 'value_2',
        'key_1_3': 'value_3'
    },
    'key_2': {
        'key_2_1': 'value_1',
        'key_2_2': 'value_2',
        'key_2_3': 'value_3',
        'key_2_4': 'value_4'
    },
    'key_3': {
        'key_3_1': 'value_1',
        'key_3_2': 'value_2'
    }
}

and your robot for loop:

FOR    ${main_key}    ${main_value}    IN    &{tabs}
    Log    ${main_key}
    FOR    ${sub_key}    ${sub_value}    IN    &{main_value}
        Log    ${sub_key} 
        Log    ${sub_value} 
    END
END

Hopefully this helps,

Dave.

1 Like

Dear Dave!

Thank you very much for taking the time to explain and correct my mistakes and my poor coding! I do really appreciate that!

I would have probably been better off with a simple list, I still need to think about that. I tend to over complicate my own codes.

You are right, I did give an improper dictionary example in my original post! That was going to be a key value pair everywhere!

All I am trying to accomplish here, is to validate the functionality of a menu bar, that has main menu buttons and once clicked they list a bunch of submenus, with the simplest way possibles. And still utilizing some decent coding and getting all the required locator data from this dictionary.

I would like to achieve this with a single keyword. And not having to declare all the locators one by one, instead using their tag texts to locate and click on them. So, their menu names would get extracted from this dictionary and the code would construct a proper locator that gets passed to a variable, that I could further work with.

This is the reason why I had thought of a FOR loop and a dictionary to set a key as the main menu and attach all the submenus as values to it.

You already helped a lot and I cannot be grateful enough!

Regards,
Oliver

Hi Oliver,

Your welcome, it was reading explanations like this that helped me learn and understand many decades ago when I was learning, so I’m happy to pay it forward and help others, hopefully one day you’ll be able to as well.

If you can extract the menu structure as a dictionary structure like that (i.e. a dictionary of dictionaries) then the simple solution might be to use Dictionaries Should Be Equal from Collections Library to compare the menu structure to the expected structure, then no need to iterate the dictionary at all.

Dave.