How does the FOR Scope work?

107 views
Skip to first unread message

Cristian

unread,
Apr 13, 2010, 5:04:18 PM4/13/10
to robotframework-users
Hi guys,
I have a problem with a list variable. I think is a scope one or there
is something that I am doing wrong.

Here is my keywords:

*** Keywords ***
Submit10AppFromDataFile
:FOR ${data} IN @{APPDATA}
\ @{aux} Combine Lists ${APPDATA_HEADER} ${data}
\ FillForm @{aux}

FillForm
[Arguments] @{data}
${length} = Get Length ${data}
${half}= Convert To Integer ${${length}/2}
:FOR ${index} IN RANGE 0 ${half}
\ ${key} = Convert To String @{data}[${index}]
\ ${value} = Convert To String @{data}[${${index}+${HALF}}]


My problem is when I call the keyword FillForm using as argument
"@{data}", for some reason, the variable ${length} always is 4 (The
size of @{APPDATA}} but it has all the elements from APPDATA_HEADER
and APPDATA and should be the size 8.

If I change the name of FillForm's argument ( @{data} ) to another, it
works fine!.

I know the easy solution will be dont use the same name, but as I am
working in a generics keyword for QA, they could use any name and I
wouldn't like to use weird names in my keyword for avoid QA uses the
same name.

Cheers,
Cristian.

Cristian

unread,
Apr 14, 2010, 10:04:28 AM4/14/10
to robotframework-users
I forgot to say:
The @{APPDATA} = [['a0','b0','c0','d0'],....,['an','bn','cn','dn']]
(List of list)
The @{APPDATA_HEADER} = ['h1','h2','h3','h4']
so ${data}, for the first iteration is: ['a0','b0','c0','d0']

so, finally : @{aux} = ['h1','h2','h3','h4','a0','b0','c0','d0']

When I check the length in FillForm I get 4 and not 8 (The argument:
@{data} comes with the 8 element, so shouldn't be the length 4)

Greeting,
Cristian

Pekka Klärck

unread,
Apr 14, 2010, 5:43:24 PM4/14/10
to cmal...@gmail.com, robotframework-users
2010/4/14 Cristian <cmal...@gmail.com>:

> Hi guys,
> I have a problem with a list variable. I think is a scope one or there
> is something that I am doing wrong.
>
> Here is my keywords:
>
> *** Keywords ***
> Submit10AppFromDataFile
>    :FOR  ${data}  IN  @{APPDATA}
>    \  @{aux}  Combine Lists  ${APPDATA_HEADER}  ${data}
>    \  FillForm  @{aux}
>
> FillForm
>    [Arguments]  @{data}
>    ${length} =  Get Length  ${data}
>    ${half}=  Convert To Integer  ${${length}/2}
>    :FOR  ${index}  IN RANGE  0  ${half}
>    \  ${key} =  Convert To String  @{data}[${index}]
>    \  ${value} =  Convert To String  @{data}[${${index}+${HALF}}]
>
>
> My problem is when I call the keyword FillForm using as argument
> "@{data}", for some reason, the variable ${length} always is 4 (The
> size of @{APPDATA}} but it has all the elements from APPDATA_HEADER
> and APPDATA and should be the size 8.
>
> If I change the name of FillForm's argument ( @{data} ) to another, it
> works fine!.

This weird problem doesn't actually have anything to do with FOR
loops. It's caused by variables used in higher level keywords leaking
to lower level keywords. If you, for example, create variable ${data}
in a keyword, all keyword that this keyword uses can see that
variable. This has been _really_ bad design decision and I definitely
consider it a bug rather than a feature. I hope this mis-feature can
be removed at some point, but because existing tests may use it we
cannot remove it without deprecation. Unfortunately the current
variable implementation is so naïve that deprecation isn't easy in RF
2.5, but refactoring variables is already on a list of issues for 2.6.
This particular issue is now also in the tracker [1].

The reason you don't get the length of `@{data}` when you do
`${length} = Get Length ${data}` is that because `${data}` variable
exists (in higher level keyword) its length is returned. As explained
in the User Guide, using list variables as scalars currently only
works when there is no scalar variable with the same basename. I said
"currently" because we are already actively removing that wart [3&4].

[1] http://code.google.com/p/robotframework/issues/detail?id=532
[2] http://robotframework.googlecode.com/svn/tags/robotframework-2.1.3/doc/userguide/RobotFrameworkUserGuide.html#list-variables
[3] http://code.google.com/p/robotframework/issues/detail?id=484
[4] http://code.google.com/p/robotframework/issues/detail?id=483

> I know the easy solution will be dont use the same name, but as I am
> working in a generics keyword for QA, they could use any name and I
> wouldn't like to use weird names in my keyword for avoid QA uses the
> same name.

In this case using different name is probably the easiest solution. An
alternative solution is doing `${data}= Create List @{data}` in the
beginning of your FillForm keyword, because then the new `${data}`
variable will hide the variable in higher level inside this keyword
(and all keywords used by it). A drawback is that in RF 2.5 you will
get warnings from having scalar and list variables with the same name
because of [3]. Another alternative is getting the length like
`${length}= Evaluate len(@{data})`. This is a bit obscure but ought
to work with your data.

Anyway, I'm very sorry for the inconvenience. Thanks for bringing this
design wart into attention of other users.

Cheers,
.peke
--
Agile Tester/Developer/Consultant :: http://eliga.fi
Lead Developer of Robot Framework :: http://robotframework.org

Reply all
Reply to author
Forward
0 new messages