UPDATE: With Robot Framework this has changed and became easier to do.
Release note: Running and result models have been changed.
TestSuite, TestCase and Keyword objects used to have keywords attribute containing keywords used in them. This name is misleading
now when they also have FOR and IF objects. With TestCase and
Keyword the attribute was renamed to body and with TestSuite it
was removed altogether. The keywords attribute still exists but it is
read-only and deprecated.
- The new
body does not have create() method for creating keywords, like the old keywords had, but instead it has separate
create_keyword(), create_for() and create_if() methods. This
means that old usages like test.keywords.create() need to be changed
to test.body.create_keyword().
For examples check out this other answer: How to write FOR loop and IF statement programmatically with Robot Framework 4.0?.
BEFORE Robot Framework 4.0:
IF statement
The if statement should be a Run Keyword If keyword with the arguments you need. It is a keyword like any other so you should list everything else in its args list.
- The condition.
- The keyword name for the
True branch.
- Separately any
args to the keyword for the True branch if there is any. Listed separately.
- The
ELSE IF keyword if needed.
- The
ELSE IF condition.
- The keyword name for the
ELSE IF branch.
- Separately any
args to the keyword for the ELSE IF branch if there is any. Listed separately.
- The
ELSE keyword.
- The keyword name for the
ELSE branch.
- Separately any
args to the keyword for the ELSE branch if there is any. Listed separately.
from robot.api import TestSuite
suite = TestSuite('Activate Skynet')
test = suite.tests.create('Should Activate Skynet', tags=['smoke'])
test.keywords.create('Run Keyword If', args=[True, 'Log To Console', 'Condition was TRUE', 'ELSE', 'Log To Console', 'Condition was FALSE'])
test.keywords.create('Run Keyword If', args=[False, 'Log To Console', 'Condition was TRUE', 'ELSE', 'Log To Console', 'Condition was FALSE'])
suite.run()
This is how it looks like in the logs:

FOR loop
As for the for loop. It is a special keyword implemented by robot.running.model.ForLoop class that bases on the robot.running.model.Keyword class. Here is the constructor:

It has a flavor parameter, which is the loop type to be say. So it is IN, IN RANGE, IN ZIP, etc.
Now you instantiating a robot.running.model.Keyword which despite you could set its type to for, it won't have flavor attribute. So when you execute your code it will throw the error you see. It is because the ForRunner will try to access the flavor attribute.
File "/usr/local/lib/python3.7/site-packages/robot/running/steprunner.py", line 52, in run_step
runner = ForRunner(context, self._templated, step.flavor)
AttributeError: 'Keyword' object has no attribute 'flavor'
So you have to use the ForLoop class. Also I am using Robot Framework 3.1.2 so the errors might be different in my case but the approach should be the same.
Here is how it should look like:
from robot.running.model import ForLoop
for_kw = ForLoop(['${i}'], ['10'], flavor='IN RANGE')
test.keywords.append(for_kw)
No this will still fail with error:
FOR loop contains no keywords.
So you have to populate it like:
for_kw.keywords.create('No Operation')
The complete example:
from robot.api import TestSuite
from robot.running.model import ForLoop
suite = TestSuite('Activate Skynet')
test = suite.tests.create('Should Activate Skynet', tags=['smoke'])
test.keywords.create('Log Many', args=['SKYNET', 'activated'], type='setup')
test.keywords.create('Log', args=['SKYNET'])
for_kw = ForLoop(['${i}'], ['10'], flavor='IN RANGE')
for_kw.keywords.create('No Operation')
test.keywords.append(for_kw)
suite.run()
If you run this it will only produce an output XML, you have to run rebot manually to have a log and report HTML file.
