Run Keyword If and comparison to None

17,430 views
Skip to first unread message

Michael Walle

unread,
Dec 4, 2014, 8:12:49 AM12/4/14
to robotframe...@googlegroups.com
Hi everyone,

Is there a way to compare a value with the actual value None?

Consider the following statement:

Run Keyword If '${value}' is not 'None' My Keyword

Now if ${value} is None the keyword is not run, but in case ${value} is
the string 'None' it is not executed either, which is wrong IMHO.

I guess this isn't possible with the current syntax/keyword, because you
always have to convert ${value} to a string (by putting it in quotes)
and the you'll lost the information whether it was None or an actual
string.

-michael

Guy Kisel

unread,
Dec 4, 2014, 3:04:55 PM12/4/14
to robotframe...@googlegroups.com, mic...@walle.cc

Michael Walle

unread,
Dec 5, 2014, 3:30:56 AM12/5/14
to Guy Kisel, robotframe...@googlegroups.com
Am 2014-12-04 21:04, schrieb Guy Kisel:
> On Thursday, December 4, 2014 5:12:49 AM UTC-8, Michael Walle wrote:
>> Is there a way to compare a value with the actual value None?
>>
>> Consider the following statement:
>>
>> Run Keyword If '${value}' is not 'None' My Keyword
>>
>> Now if ${value} is None the keyword is not run, but in case ${value}
>> is
>> the string 'None' it is not executed either, which is wrong IMHO.
>>
>> I guess this isn't possible with the current syntax/keyword, because
>> you
>> always have to convert ${value} to a string (by putting it in
>> quotes)
>> and the you'll lost the information whether it was None or an actual
>>
>> string.
>
The problem is not the ${None} variable, but the fact that '${value}'
will be converted to the string 'None'. If you'll write

Run Keyword If ${value} is not None My Keyword

i'd guess it'll work in the "value == None" case but not if value is set
to a string, because in the latter case the statement which will be
evauluated is "somestring is not None", which will raise a NameError
because somestring is undefined.

-michael

Guy Kisel

unread,
Dec 5, 2014, 5:13:16 PM12/5/14
to robotframe...@googlegroups.com, guy....@gmail.com, mic...@walle.cc
Interesting, I was going to comment that in my code, Run Keyword If    ${my_variable} is not ${None}     My Keyword   works just fine, but after looking closer, it's because in this case, ${my_variable} is an integer, so evaling the expression works. When the value is a string instead, I get an error unless I quote it, and then I have the same problem as you. (As in, '970 is not None' vs '5M6UIB is not None', where the latter results in Evaluating expression '5M6UIB is not None' failed: SyntaxError: invalid syntax (<string>, line 1))


I'm honestly not sure what the best solution/approach is here. 
I suppose you could do:
${is_none}= Run Keyword And Return Status Should Be Equal ${my_variable}     ${None}
Run Keyword If ${is_none} My Keyword
But this is pretty ugly.

Pekka Klärck

unread,
Dec 6, 2014, 7:03:58 PM12/6/14
to mic...@walle.cc, robotframework-users
2014-12-04 14:12 GMT+01:00 Michael Walle <mic...@walle.cc>:
>
> Is there a way to compare a value with the actual value None?
>
> Consider the following statement:
>
> Run Keyword If '${value}' is not 'None' My Keyword
>
> Now if ${value} is None the keyword is not run, but in case ${value} is the
> string 'None' it is not executed either, which is wrong IMHO.

I agree this can feel weird, but the result is exactly as designed.

> I guess this isn't possible with the current syntax/keyword, because you
> always have to convert ${value} to a string (by putting it in quotes) and
> the you'll lost the information whether it was None or an actual string.

Yes, the expression you used above will be string `'None' is not
'None'` when passed to `Run Keyword If` regardless is ${value} "real"
`None` or string `'None'`. When this expression is evaluated in Python
you typically get False, but the result is actually ambiguous [1].

If the argument passed to `Run Keyword If` is not a string, it will
not be evaluated but rather its truth value is checked directly. I
first thought you could just pass ${value} alone to `Run Keyword If`,
but the I realized that when it contains a string, evaluation will
fail with SyntaxError (unless the string happens to contain a valid
Python expression, in which case the result depends on that
expression). There are, however, at least three somewhat ugly/hackish
ways to use to actually get what you wanted.

1) Check is the value string or None like Guy already proposed:

${is none} = Run Keyword And Return Status Should Be Equal
${value} ${None}
Run Keyword If ${is string} My Keyword

This is both quite ugly and long, but shouldn't be too hard to
understand and ought to work regardless what ${value} actually
contains.

2) Use extended variable syntax [2] to check the type so that the end
result of the variable is just True or False:

Run Keyword If ${value.__class__ is not type(None)} My Keyword

Compared to the above solution this is just one line, but the
expression is _really_ ugly. It's a shame that using a bit nicer

Run Keyword If ${value is None} My Keyword

doesn't work because it has no non-alphanumeric chars after the
variable base name and thus it doesn't match extended variable syntax.
I guess we could extend the extended variable syntax to support also
`is` (and perhaps also `in`) operator when finding variable base
names.

3) Use extended variable syntax to get repr() of the variable value.
With strings this repr has quotes so they can be evaluated fine:

Run Keyword If ${value.__repr__()} is None My Keyword

This solution has a downside that it fails with SyntaxError if the
object has a repr that cannot be evaluated. That shouldn't be a
problem with base types, but you can have issues with custom objects.
Also in this case there would be more Pythonic way to get the repr
which doesn't work due to extended variable syntax limitations:

Run Keyword If ${repr(value)} is None My Keyword

We could take a look supporting wrapping variables with function like
this, but I'm not sure how reliable it could be done and how readable
the syntax actually is.


Does anyone have any other ideas how to solve this problem? With more
complex checks it would probably be best just to move the logic to a
custom library, but this particular case is something I hope could be
done cleanly also on Robot data level. Should we consider extending
the extended variable syntax like discussed in 2) and 3) above?

Cheers,
.peke

[1] `is` operator in Python verifies object identity. When comparing
short strings the result typically is same as with `==` operator that
verifies equality, because Python keeps short strings in memory and
reuses them. This is an implementation detail and shouldn't be relied
on, though.
[2] http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#extended-variable-syntax
--
Agile Tester/Developer/Consultant :: http://eliga.fi
Lead Developer of Robot Framework :: http://robotframework.org

Pekka Klärck

unread,
Dec 9, 2014, 6:36:14 AM12/9/14
to mic...@walle.cc, robotframework-users
2014-12-07 1:03 GMT+01:00 Pekka Klärck <pe...@iki.fi>:
>
> 2) Use extended variable syntax [2] to check the type so that the end
> result of the variable is just True or False:
>
> Run Keyword If ${value.__class__ is not type(None)} My Keyword
>
> Compared to the above solution this is just one line, but the
> expression is _really_ ugly. It's a shame that using a bit nicer
>
> Run Keyword If ${value is None} My Keyword
>
> doesn't work because it has no non-alphanumeric chars after the
> variable base name and thus it doesn't match extended variable syntax.

Using `==` instead of `is` works and is definitely better than
`value.__class__ ...`:

Run Keyword If ${value == None} My Keyword

This works reliable as long as `value` isn't an object with a custom
and broken `__eq__`.

> 3) Use extended variable syntax to get repr() of the variable value.
> With strings this repr has quotes so they can be evaluated fine:
>
> Run Keyword If ${value.__repr__()} is None My Keyword
>
> This solution has a downside that it fails with SyntaxError if the
> object has a repr that cannot be evaluated. That shouldn't be a
> problem with base types, but you can have issues with custom objects.
> Also in this case there would be more Pythonic way to get the repr
> which doesn't work due to extended variable syntax limitations:
>
> Run Keyword If ${repr(value)} is None My Keyword
>
> We could take a look supporting wrapping variables with function like
> this, but I'm not sure how reliable it could be done and how readable
> the syntax actually is.

I discussed this with Jussi yesterday and we agreed that using Python
built-in methods like ${len(var)}, ${hasattr(var, 'foo')} etc. would
sometimes be useful. We'll prototype how hard implementing this would
be and may include it in RF 2.8.7.

Cheers,
.peke

Jussi Malinen

unread,
Dec 10, 2014, 10:05:56 AM12/10/14
to pekka....@gmail.com, mic...@walle.cc, robotframework-users

>
>> 3) Use extended variable syntax to get repr() of the variable value.
>> With strings this repr has quotes so they can be evaluated fine:
>>
>> Run Keyword If ${value.__repr__()} is None My Keyword
>>
>> This solution has a downside that it fails with SyntaxError if the
>> object has a repr that cannot be evaluated. That shouldn't be a
>> problem with base types, but you can have issues with custom objects.
>> Also in this case there would be more Pythonic way to get the repr
>> which doesn't work due to extended variable syntax limitations:
>>
>> Run Keyword If ${repr(value)} is None My Keyword
>>
>> We could take a look supporting wrapping variables with function like
>> this, but I'm not sure how reliable it could be done and how readable
>> the syntax actually is.
>
> I discussed this with Jussi yesterday and we agreed that using Python
> built-in methods like ${len(var)}, ${hasattr(var, 'foo')} etc. would
> sometimes be useful. We'll prototype how hard implementing this would
> be and may include it in RF 2.8.7.
>

It wasnt too hard to do, but some of the limitations (like only one variable supported etc) felt a bit weird and artificial. We created a new issue for a more expressive syntax targeted at 2.9: https://github.com/robotframework/robotframework/issues/1868

The idea is that using double curly braces (or something similar) you could evaluate free python expressions with all robot variables available in python namespace. For example:

${{ len(var) + len(var2) }}
@{{ [name.upper() for name in my_list] }}

Cheers,
Jussi

Michael Walle

unread,
Dec 10, 2014, 10:18:02 AM12/10/14
to Jussi Malinen, pekka....@gmail.com, robotframework-users
sounds good.

-michael


Reply all
Reply to author
Forward
0 new messages