Hi all,
Last week a client of mine asked could he simplify a user keyword that
looked more or less like this:
Do Something
[Arguments] ${arg}
${temp1} = Run Keyword If "${arg}" == "xxx"
... Some Keyword arg1 arg2
${temp2} = Run Keyword Unless "${arg}" == "xxx"
... Another Keyword another arg
${return} = Set Variable If "${arg}" == "xxx"
... ${temp1} ${temp2}
[Return] ${return}
Basically the above keyword executes either `Some Keyword` or `Another
Keyword`, depending on the value of `${arg}`, and returns the results
of the executed keyword. Pretty simple task but unfortunately complex
in Robot Framework test data.
My first reaction how to simplify this was moving the logic into a
custom test library. Although that is often the best solution,
especially if the needed logic grows more complex, it may not always
be that easy. The biggest problem is that if keywords to be executed
are themselves user keywords, executing them from Python isn't
possible directly. Moving from Robot test data to "real" programming
may also be a quite big jump for people without much "real"
programming experience.
Because of the explained drawbacks in moving the logic to a test
library, I started to think could we make it possible to simplify the
above keyword otherwise. After pondering this a little, I believe that
implementing following two enhancements would be a good idea. I'm very
interested to hear your opinions too, but please read this mail to the
end first.
1) `ELSE` support for `Run Keyword If`.
Creating if/else construct using `Run Keyword If/Run Keyword Unless`
works pretty well if you only want to execute certain keywords, but
gets pretty complicated if you are interested in the return values. As
the above example demonstrates, you need to add one more `Set Variable
If` into the equation to make that work. If, on the other hand, `Run
Keyword If` would support `ELSE`, you would only run one keyword get
one return value. I assume it's not only me who thinks that the below
example quite a bit simpler than the original.
Do Something
[Arguments] ${arg}
${return} = Run Keyword If "${arg}" == "xxx"
... Some Keyword arg1 arg2
... ELSE
... Another Keyword another arg
[Return] ${return}
Notice that the else "branch" is denoted with capital `ELSE`. I chose
that because I wanted it to stand out and also be less likely to clash
with arguments passed to `Some Keyword`. It is obviously still
possible that someone is nowadays passing `ELSE` as an argument to a
keyword used with `Run Keyword If`, but I think that is pretty
unlikely. It is also easy to escape this string like `\ELSE` if you
actually want to use the literal value. This change would,
nevertheless, be at least potentially backwards incompatible.
2) Implicit user keyword return values.
Returning a value from a keyword only to use it with `[Return]` is a
bit boring. Robot could easily behave like e.g. Ruby and return the
return value of the last executed keyword if no explicit return value
is specified. That would simplify our example still a little bit more:
Do Something
[Arguments] ${arg}
Run Keyword If "${arg}" == "xxx"
... Some Keyword arg1 arg2
... ELSE
... Another Keyword another arg
I can see someone arguing that the previous example was more explicit
than the last one, but they could keep using `[Return]`. A nice thing
about this enhancement is that it ought to be fully
backwards-compatible.
----------------
What do you think about these two enhancements? Should we implement
them? Should they be includes already to RF 2.7.4 that is otherwise
pretty much ready? I've already prototyped both of them and know that
implementing them is very easy.
Cheers,
.peke
--
Agile Tester/Developer/Consultant ::
http://eliga.fi
Lead Developer of Robot Framework ::
http://robotframework.org