IF/ELSE, FOR, WHILE, TRY/EXCEPT, BREAK, CONTINUE, and Control Flow: Core Concepts and Mental Model
Build a mental model for Robot Framework native branching, iteration, loop control, and structured error recovery while separating expression evaluation from keyword execution and keeping business-facing tests readable.
Learning objectives
- Explain where IF/ELSE, FOR, WHILE, TRY/EXCEPT, BREAK, and CONTINUE sit in Robot Framework execution.
- Distinguish Robot variable replacement from Python-expression evaluation and choose safer $variable access for strings and objects.
- Explain how branch/loop/recovery choices affect keyword and test status rather than merely source-code appearance.
- Use explicit loop limits and narrow error matching as production defaults.
- Recognize when control logic belongs in a user keyword or Python library instead of a business-facing test case.
Current compatibility baseline. Verified
2026-08-31: Robot Framework 7.4.2 is the current stable release;
7.5b1 is a pre-release and is not required in this chapter. Native
IF/ELSE arrived in Robot Framework 4.0;
WHILE, TRY/EXCEPT, BREAK,
CONTINUE, and inline IF are available in
modern Robot Framework 5.0+ syntax. Robot Framework 7.4.2 gives
WHILE a default 10,000-iteration limit; production
examples here set a smaller explicit limit.
1. The practical problem: automation needs decisions without becoming a hidden program
Chapters 01–09 established suites, keywords, variables, standard libraries, and deterministic lifecycle ownership. Real automation still needs decisions: skip an item that is not actionable, iterate over synthetic inputs, poll a bounded local state, or recover from one expected failure while preserving all others.
Robot Framework now has native control structures for these cases. The design risk is not lack of power; it is putting so much branching and recovery logic in a test that the executable specification stops communicating business intent. This chapter therefore treats control flow as an observable, bounded orchestration tool, not a second general-purpose language.
flowchart TD
A[Test/task or user keyword] --> B{Control structure}
B -->|IF/ELSE| C[Chosen branch]
B -->|FOR/WHILE| D[Bounded iterations]
B -->|TRY| E[Keyword execution]
E -->|PASS| F[ELSE if present]
E -->|Matched FAIL| G[EXCEPT branch]
E -->|Unmatched FAIL| H[Test/keyword fails]
F --> I[FINALLY if present]
G --> I
H --> I
C --> J[Next statement / status]
D --> J
I --> J
K[BREAK / CONTINUE] -. only valid in active loop body .-> D
2. Define the objects before writing conditions
| Object | What it owns | What control flow may change |
|---|---|---|
| Test/task | Automation intent and final PASS/FAIL/SKIP result | Which keywords execute and which failure becomes final |
| User keyword | Reusable orchestration contract | Local branches, loops, recovery, and returned values |
| Variable | A value in a defined scope | Read for conditions; possibly reassigned by executed branches |
| Expression | Python-evaluated condition only | Decision result, not external system state by itself |
| External state | Files/process/browser/API/database/etc. | Changes only when executed keywords mutate it |
| Result evidence | output.xml/log/report hierarchy and messages | Records branches, loop iterations, failures, and recovery |
3. Native structure map
| Structure | Primary use | Production guardrail |
|---|---|---|
| IF / ELSE IF / ELSE | Choose one branch | Keep condition understandable; extract complex policy |
| FOR | Iterate known finite data | Prefer finite input and meaningful loop variable names |
| WHILE | Repeat while state changes | Always set an explicit small iteration/time limit for course/production patterns |
| BREAK | Exit current loop early | Use only when the exit condition is obvious and evidenced |
| CONTINUE | Skip remaining current iteration | Do not silently discard unexplained failures |
| TRY / EXCEPT | Handle an expected keyword failure | Match the expected message narrowly; unmatched failures must propagate |
| ELSE in TRY | Run only when TRY succeeds | Useful for success-only post-processing |
| FINALLY | Always execute local cleanup | Do not replace suite/test teardown ownership indiscriminately |
4. Expression evaluation: ${var} replacement and $var access are not the same
IF and WHILE conditions are evaluated as
Python expressions. With ${name}, Robot first replaces
the variable with its string representation and then evaluates the
resulting expression. This is convenient for numbers but fragile for
arbitrary strings, multiline values, quotes, and complex objects.
The special $name syntax gives the evaluator the actual
object.
*** Test Cases ***
Safer String Condition
VAR ${state} ready
IF $state == "ready"
Log State is ready.
END
Numeric Replacement Can Be Fine
VAR ${count} ${3}
IF ${count} > 0
Log Positive count.
END
Trust boundary. An expression is executable Python
syntax. Do not concatenate untrusted external text into expressions
or pass arbitrary user-controlled strings to Evaluate.
Keep conditions authored by the suite and pass data through
variables such as $value.
5. Status propagation is the real behavior
An IF whose condition is false is not a failure; its
body simply does not execute. A normal FOR completes
with PASS unless a keyword fails or a loop-control statement changes
the path. A WHILE that hits its configured limit
normally fails. A TRY failure becomes handled only when
an EXCEPT branch matches and that handler itself
succeeds.
Therefore “the log reached the next line” is not enough evidence. Inspect the error message, which branch matched, loop status, final test status, and surrounding lifecycle cleanup.
6. WHILE is bounded by default—but set a deliberate limit anyway
Robot Framework 7.4.2 has a built-in default of 10,000 WHILE iterations. That safety net is much too large to serve as a domain policy. A production test should set a meaningful count or time budget tied to the operation being modeled.
*** Keywords ***
Advance Until Ready
[Arguments] ${max_attempts}=5
VAR ${attempt} ${0}
VAR ${state} warming
WHILE $state != "ready" limit=${max_attempts}
${attempt}= Evaluate $attempt + 1
${state}= Simulate State ${attempt}
Log attempt=${attempt}; state=${state}
END
RETURN ${state}
7. BREAK and CONTINUE belong to the loop body
BREAK exits the current FOR or
WHILE. CONTINUE skips the rest of the
current iteration. Both may be nested inside IF or
TRY, but they must still be syntactically in the loop
body. Calling a helper keyword that itself contains
BREAK is invalid; a helper should instead return a
decision that the loop body acts on.
FOR ${item} IN alpha skip stop omega
IF $item == "skip" CONTINUE
IF $item == "stop" BREAK
Log processing=${item}
END
8. TRY/EXCEPT matches Robot error messages—not Python exception classes
Robot Framework error recovery deals primarily with keyword failure
messages. Exact matching is the default. Pattern modes such as
GLOB, REGEXP, and START are
available when the variable portion of an expected message must be
tolerated. Invalid syntax and failures that stop the whole execution
cannot be caught with ordinary EXCEPT.
TRY
Fail transient: service warming
EXCEPT transient:* type=GLOB AS ${error}
Log Recovered expected failure: ${error}
ELSE
Log No failure occurred.
FINALLY
Log Local cleanup/evidence step.
END
9. Put control flow at the narrowest readable layer
| Situation | Good location | Why |
|---|---|---|
| One business-visible choice | Test/task or domain keyword | The branch communicates intent |
| Iteration over test data | User keyword or template chapter later | Keeps case readable and loop reusable |
| Small bounded polling | Named user keyword | Centralizes limit/evidence contract |
| Complex policy graph or algorithm | Python library | Robot syntax should not become general application code |
| Expected operational failure mapping | User keyword with narrow TRY/EXCEPT | Preserves failure semantics behind a clear domain contract |
10. Why this matters in DevOps
CI needs deterministic control flow. A green pipeline is trustworthy only if a branch cannot silently hide a failed assertion, a retry loop cannot run forever, and recovery is limited to known transient conditions. Bounded control flow also improves parallelism planning because each test has an understandable upper execution cost.
11. Knowledge check
Why is $state often safer than embedding ${state} directly in an IF expression?
The $state form passes the actual Python object into the evaluation namespace instead of first replacing it with a string that may need quoting or escaping.
What happens when a WHILE loop reaches its normal limit?
The loop exits with FAIL status unless on_limit is explicitly configured otherwise. A production loop should use a deliberate small limit rather than relying on the 10,000-iteration default.
Can BREAK be placed inside a user keyword that is called from a FOR loop?
No. BREAK and CONTINUE must be used in the active loop body, though they may be nested inside IF or TRY structures within that body.
Does an EXCEPT without a message make all failures safe to ignore?
No. It catches ordinary keyword failures broadly and can hide defects. Prefer narrow expected matching; syntax/fatal execution errors are not ordinary catchable failures anyway.
12. Summary and next step
Native control flow changes which Robot statements execute while lifecycle and external-state ownership remain separate. Conditions are Python expressions, loops must be bounded, BREAK/CONTINUE belong to the active loop body, and TRY/EXCEPT should recover only explicitly expected failures. Lesson 2 turns that model into a synthetic state-processing workflow with observable traces.
Further reading
- Robot Framework 7.4.2 User Guide — control structures — FOR, WHILE, BREAK/CONTINUE, IF/ELSE, TRY/EXCEPT, and readability guidance.
-
Robot Framework 7.4.2 User Guide — WHILE loops
— expression evaluation, limits,
on_limit, and output-size considerations. -
Robot Framework 7.4.2 User Guide — TRY/EXCEPT
— exact/pattern matching,
AS,ELSE,FINALLY, and uncatchable failures. -
Robot Framework 7.4.2 User Guide — evaluating expressions
—
${var}replacement versus$varaccess and evaluation namespace behavior. - Robot Framework 7.4.2 BuiltIn — legacy-compatible conditional/loop-control helpers and native-syntax recommendations.
- Robot Framework project site — current stable release stream.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.