Chapter 09Lesson 05240–330 min

Checkpoint Lab — Setups, Teardowns, Tags, Timeouts, and Suite Lifecycle

Build a lifecycle matrix with passing, failing, timed-out, and setup-failed disposable tests; predict exact order, prove it from logs/filesystem evidence, then refactor shared mutable state into deterministic per-test ownership.

Checkpoint labLifecycle matrixEvidence packetFailure preservationIsolation refactor

Learning objectives

  • Predict and verify setup/body/teardown order for PASS, body FAIL, setup FAIL, and TIMEOUT cases.
  • Demonstrate that teardown runs after body/setup failure and after test timeout.
  • Compare tag include/skip/exclude behavior using preserved result artifacts.
  • Detect an order-dependent shared-state fixture and refactor it to per-test isolation.
  • Produce a production-style lifecycle convention and evidence packet with safe cleanup.

Current compatibility baseline. Verified 2026-08-31: Robot Framework 7.4.2 is the current stable release and requires Python 3.8+; 7.5b1 is a pre-release and is not required here. Suite, test/task, and user-keyword setups/teardowns are supported; user-keyword [Setup] was added in Robot Framework 7.0. Test Tags is the modern suite-level tag setting, while Force Tags/Default Tags are deprecated. Test timeouts and user-keyword timeouts have different cleanup behavior, which this chapter treats explicitly.

1. Checkpoint charter

Create a self-contained lifecycle lab under a disposable directory. No network, browser, API, database, SSH, container, or paid tool is required. The suite creates only guarded temp state and Robot output evidence. You will run each failure class separately so evidence remains attributable.

Do not normalize failures away. PASS, FAIL, setup FAIL, and TIMEOUT are intentional outcomes. The checkpoint succeeds when you can predict and explain them, not when every Robot command exits zero.

2. Predict the lifecycle matrix before running

Case Suite setup Test setup Body Test teardown Suite teardown Expected status
Pass Yes PASS Runs fully Runs Runs PASS
Body fail Yes PASS Stops at Fail Runs Runs FAIL
Setup fail Yes FAIL Does not run Runs Runs FAIL
Timeout Yes PASS Interrupted at timeout Runs Runs FAIL

3. Implement the lifecycle matrix suite

*** Settings ***
Library           OperatingSystem
Suite Setup       Suite Start
Suite Teardown    Suite End
Test Setup        Case Start
Test Teardown     Case End
Test Tags         rf09    checkpoint

*** Variables ***
${RUN_ID}          checkpoint-001
${ROOT}            ${TEMPDIR}/rf09-checkpoint-${RUN_ID}
${TRACE}           ${OUTPUT DIR}/trace.txt
${SUITE_OWNS_ROOT}    ${False}

*** Test Cases ***
Case Passes
    [Tags]    case-pass
    Trace    ${TEST NAME}|body-start
    File Should Exist    ${CASE_FILE}
    Trace    ${TEST NAME}|body-end

Case Body Fails
    [Tags]    case-body-fail
    Trace    ${TEST NAME}|body-start
    Fail    checkpoint-primary-failure
    Trace    ${TEST NAME}|unreachable

Case Setup Fails
    [Tags]    case-setup-fail
    [Setup]    Failing Case Start
    Trace    ${TEST NAME}|unreachable-body

Case Times Out
    [Tags]    case-timeout
    [Timeout]    250 milliseconds
    Trace    ${TEST NAME}|body-start
    Sleep    2 seconds
    Trace    ${TEST NAME}|unreachable

*** Keywords ***
Suite Start
    Guard Root
    Directory Should Not Exist    ${ROOT}
    Create Directory    ${ROOT}
    Set Suite Variable    ${SUITE_OWNS_ROOT}    ${True}
    Create File    ${TRACE}    suite-setup\n
Case Start
    Create Owned Case File
    Trace    ${TEST NAME}|test-setup

Failing Case Start
    Create Owned Case File
    Trace    ${TEST NAME}|test-setup-before-fail
    Fail    checkpoint-setup-failure

Create Owned Case File
    ${safe}=       Evaluate    re.sub(r'[^A-Za-z0-9_.-]+', '_', $TEST_NAME)    modules=re
    ${case}=       Join Path    ${ROOT}    ${safe}.txt
    Set Test Variable    ${CASE_FILE}    ${case}
    Create File    ${CASE_FILE}    owner=${TEST NAME}\n
Case End
    Trace    ${TEST NAME}|test-teardown-start
    ${status}    ${message}=    Run Keyword And Ignore Error    Remove File    ${CASE_FILE}
    Trace    ${TEST NAME}|remove-status=${status}
    File Should Not Exist    ${CASE_FILE}
    Trace    ${TEST NAME}|test-teardown-end

Suite End
    Trace    suite-teardown-start
    IF    ${SUITE_OWNS_ROOT}
        Guard Root
        Remove Directory    ${ROOT}    recursive=True
        Directory Should Not Exist    ${ROOT}
    ELSE
        Log    Root was not created by this suite; leaving it untouched.
    END
    Trace    suite-teardown-end

Guard Root
    ${candidate}=    Normalize Path    ${ROOT}    case_normalize=True
    ${temp}=         Normalize Path    ${TEMPDIR}    case_normalize=True
    Should Start With    ${candidate}    ${temp}${/}
    Should Contain       ${candidate}    rf09-checkpoint-

Trace
    [Arguments]    ${message}
    Append To File    ${TRACE}    ${message}\n    ...    encoding=UTF-8

4. Preflight

python --version
robot --version
robot --dryrun --outputdir evidence/dryrun suites/checkpoint.robot

Dry run should resolve all lifecycle keywords. It does not demonstrate actual teardown or timeout behavior.

5. Execute each matrix row into separate evidence

robot --include case-pass       --variable RUN_ID:pass-001    --outputdir evidence/pass    suites/checkpoint.robot
robot --include case-body-fail  --variable RUN_ID:body-001    --outputdir evidence/body    suites/checkpoint.robot
robot --include case-setup-fail --variable RUN_ID:setup-001   --outputdir evidence/setup   suites/checkpoint.robot
robot --include case-timeout    --variable RUN_ID:timeout-001 --outputdir evidence/timeout suites/checkpoint.robot

Only the first command should exit successfully. Preserve the other three output directories; their non-zero status is part of the checkpoint.

6. Verify predictions from trace and result hierarchy

For each run, inspect trace.txt, log.html, and output.xml. Confirm:

  • the setup-failed case has no body marker but does have teardown markers;
  • the timeout case has no body-end marker but does have teardown markers;
  • the body-failed case preserves checkpoint-primary-failure;
  • every run ends with suite teardown markers;
  • the guarded scratch root is absent after execution.

7. Add selection evidence

robot --skip case-timeout --outputdir evidence/skip suites/checkpoint.robot
robot --exclude case-timeout --outputdir evidence/exclude suites/checkpoint.robot

Compare reports. With --skip, the timeout test is visible as SKIP and does not execute. With --exclude, it is omitted from the execution result. Record this difference in your evidence packet.

8. Introduce and diagnose a shared-state bug

Create a second suite shared_state_broken.robot. Its suite setup creates one shared file containing clean. Test A appends dirty. Test B asserts the entire file still equals clean. Run both together and then B alone. If the outcomes differ, you have proven order dependence.

*** Settings ***
Library          OperatingSystem
Suite Setup      Prepare Shared File
Suite Teardown   Cleanup Shared File

*** Variables ***
${RUN_ID}         shared-001
${ROOT}           ${TEMPDIR}/rf09-shared-state-${RUN_ID}
${SHARED}         ${ROOT}/shared.txt
${SUITE_OWNS_ROOT}    ${False}

*** Test Cases ***
A Mutates Shared State
    Append To File    ${SHARED}    dirty\n
B Requires Clean State
    ${text}=    Get File    ${SHARED}
    Should Be Equal    ${text}    clean\n
*** Keywords ***
Prepare Shared File
    Directory Should Not Exist    ${ROOT}
    Create Directory    ${ROOT}
    Set Suite Variable    ${SUITE_OWNS_ROOT}    ${True}
    Create File    ${SHARED}    clean\n
Cleanup Shared File
    IF    ${SUITE_OWNS_ROOT}
        ${candidate}=    Normalize Path    ${ROOT}    case_normalize=True
        ${temp}=         Normalize Path    ${TEMPDIR}    case_normalize=True
        Should Start With    ${candidate}    ${temp}${/}
        Should Contain       ${candidate}    rf09-shared-state-
        Remove Directory    ${ROOT}    recursive=True
    END

9. Refactor shared state into deterministic isolation

Move file creation into Test Setup and deletion into Test Teardown, with a unique per-test filename. The suite setup may still create the guarded parent directory if that parent itself is immutable shared infrastructure. Re-run the tests together, individually, and in reversed source order. All should have the same outcome.

10. Produce a lifecycle convention for the project

Concern Convention
Mutable state Owned by the narrowest test/task/keyword scope; unique IDs for future parallelism
Suite setup Only genuinely shared/immutable prerequisite; failure intentionally blocks suite
Teardown Preserve first-failure evidence; clean exact owned resources; verify key postcondition
Timeout Domain/library timeout first; Robot timeout is outer safety fuse, never a wait strategy
Tags Stable classification/selection only; Test Tags as modern suite default
Reserved robot:* tags Use only for documented execution semantics; never invent custom robot:* metadata
Evidence Separate output directories for clean/failure experiments; never overwrite first failure before diagnosis

11. Required evidence packet

  • Robot and Python versions.
  • Exact commands for PASS, body FAIL, setup FAIL, timeout, skip, and exclude runs.
  • trace.txt from each lifecycle case.
  • output.xml, log.html, and report.html from each run.
  • Proof that each guarded scratch root is absent after execution.
  • Before/after source for the shared-state refactor.
  • A one-page lifecycle convention using the table above.

12. Production operating model added by Chapter 09

Chapter 09 adds deterministic lifecycle ownership to the course’s operating model. A production Robot suite should make resource allocation, test isolation, cleanup, tag semantics, timeout budgets, and final failure evidence explicit. That discipline makes reruns meaningful and prepares the suite for future parallel execution rather than relying on source order or a clean developer machine.

13. Knowledge check

Why must setup-failure and timeout runs be executed separately during the checkpoint?

What observation proves test teardown runs after setup failure?

What is the real defect if B passes alone but fails after A?

Why is --skip preferable to --exclude when you need evidence that a known test was intentionally not run?

What Chapter 10 capability follows naturally from this lifecycle work?

14. Checkpoint complete

You can now reason about Robot Framework lifecycle from first principle: preparation has an owner, failures change control flow, teardowns still run, tags classify/select, timeouts bound but do not synchronize, and results represent the entire lifecycle. The next chapter builds native control-flow structures on top of this deterministic execution model.

Next lesson

IF/ELSE, FOR, WHILE, TRY/EXCEPT, BREAK, CONTINUE, and Control Flow: Core Concepts and Mental Model

Continue with IF/ELSE, FOR, WHILE, TRY/EXCEPT, BREAK, CONTINUE, and Control Flow: Core Concepts and Mental Model. It builds directly on the state, evidence, and operating assumptions established here, so carry those constraints forward rather than treating the next page as an isolated topic.

Further reading

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.