Chapter 08Lesson 02180–240 min

Collections, String, DateTime, OperatingSystem, Process, and XML Libraries: Guided Hands-On Workflow

Build one disposable workflow that transforms data, creates an owned workspace, runs a harmless Python child process, parses synthetic XML, records UTC evidence, verifies outputs, and cleans up only the resources it created.

Hands-onFilesystemProcess resultXML queryCleanup

Learning objectives

  • Create a deterministic disposable workspace and verify its pre-state before writing.
  • Transform collections/strings and record explicit UTC timestamps without leaking sensitive data.
  • Run a harmless child process with separate command arguments and assert rc/stdout/stderr.
  • Parse and query synthetic XML structurally instead of using fragile raw string matching.
  • Verify every side effect and execute guarded cleanup that targets only the lab-owned directory.

Current compatibility baseline. Verified 2026-08-31: Robot Framework 7.4.2 is the current stable release and requires Python 3.8+. The six libraries in this chapter ship with Robot Framework core. BuiltIn is available automatically, while Collections, String, DateTime, OperatingSystem, Process, and XML must be imported explicitly. Robot Framework 7.4 added type hints across standard libraries, expanded bytes support, and Secret-aware arguments in relevant APIs. This chapter does not require pre-release syntax or third-party libraries.

1. Lab scenario and safety boundary

You are building a tiny local “artifact inspection” task. It receives synthetic component data, normalizes it, writes a small manifest and notes file, executes Python as a local verifier, parses the XML, and writes evidence under one disposable directory. It never calls the network, never uses real credentials, and never deletes outside the path it created.

Destructive boundary. The cleanup step uses recursive directory removal. Run it only after proving that the normalized target path is the expected ${TEMPDIR}/rf08-artifact-lab-... directory. Never reuse the cleanup keyword with an arbitrary user-supplied path.

2. Create the lab project

rf08-standard-libraries/
├── suites/
│   └── workflow.robot
└── evidence/

3. A complete runnable suite

*** Settings ***
Library    Collections
Library    String
Library    DateTime
Library    OperatingSystem
Library    Process
Library    XML

*** Variables ***
${RUN_ID}       manual-001
${PYTHON}       python
${WORKSPACE}    ${TEMPDIR}/rf08-artifact-lab-${RUN_ID}

*** Test Cases ***
Process Synthetic Artifact Safely
    [Setup]       Prepare Workspace
    [Teardown]    Cleanup Workspace

    # In-memory data: copy before mutation.
    ${source}=     Create List    api    worker
    ${expected}=   Create List    api    worker
    ${items}=      Copy List    ${source}
    Append To List    ${items}    scheduler
    Lists Should Be Equal    ${source}    ${expected}

    ${label}=     Catenate    SEPARATOR=,    @{items}
    ${label}=     Convert To Lower Case    ${label}
    Should Be Equal    ${label}    api,worker,scheduler

    # Explicit UTC evidence.
    ${now}=       Get Current Date    time_zone=UTC    result_format=%Y-%m-%dT%H:%M:%S
    ${stamp}=     Catenate    SEPARATOR=    ${now}    Z

    # Owned filesystem state.
    ${notes}=     Join Path    ${WORKSPACE}    notes.txt
    Create File    ${notes}    components=${label}\nstamp=${stamp}\n    File Should Exist    ${notes}
    ${text}=      Get File    ${notes}    encoding=UTF-8
    Should Contain    ${text}    components=api,worker,scheduler

    ${xml_path}=  Join Path    ${WORKSPACE}    manifest.xml
    Create File    ${xml_path}    <manifest><artifact id="A-1"><name>demo</name><count>3</count></artifact></manifest>

    # Structured child process; shell=False is the default.
    ${result}=    Run Process
    ...    ${PYTHON}
    ...    -c
    ...    import sys; print("verified"); print("diagnostic", file=sys.stderr)
    Should Be Equal As Integers    ${result.rc}    0
    Should Be Equal    ${result.stdout}    verified
    Should Be Equal    ${result.stderr}    diagnostic

    # Structured XML inspection.
    ${root}=      Parse XML    ${xml_path}
    ${name}=      Get Element Text    ${root}    artifact/name
    ${id}=        Get Element Attribute    ${root}    id    xpath=artifact
    Should Be Equal    ${name}    demo
    Should Be Equal    ${id}    A-1

*** Keywords ***
Prepare Workspace
    ${normalized}=    Normalize Path    ${WORKSPACE}    case_normalize=True
    ${temp}=          Normalize Path    ${TEMPDIR}    case_normalize=True
    Should Start With    ${normalized}    ${temp}${/}
    Should Contain       ${normalized}    rf08-artifact-lab-
    Directory Should Not Exist    ${WORKSPACE}
    Create Directory    ${WORKSPACE}
    Directory Should Exist    ${WORKSPACE}

Cleanup Workspace
    ${normalized}=    Normalize Path    ${WORKSPACE}    case_normalize=True
    ${temp}=          Normalize Path    ${TEMPDIR}    case_normalize=True
    Should Start With    ${normalized}    ${temp}${/}
    Should Contain       ${normalized}    rf08-artifact-lab-
    Remove Directory    ${WORKSPACE}    recursive=True
    Directory Should Not Exist    ${WORKSPACE}

4. Preflight: prove interpreter and target before execution

Use an isolated environment from Chapter 02. Confirm the interpreter that ${PYTHON} should name. If your platform uses python3 or an absolute interpreter path, override the variable at the command line instead of editing the suite.

python --version
robot --version
robot --dryrun --variable RUN_ID:preflight --outputdir evidence/dryrun suites/workflow.robot

A dry run validates Robot-level syntax and keyword resolution, but it does not execute the OperatingSystem, Process, or XML side effects. It is not a substitute for the guarded real run.

5. Run with an explicit output directory and unique run ID

robot --variable RUN_ID:local-001 --variable PYTHON:python --outputdir evidence/run-001 suites/workflow.robot

Expected test status: PASS. The workspace is created during the test and removed by teardown, while Robot’s evidence remains under evidence/run-001/. This separation is deliberate: runtime scratch state is disposable; test evidence is retained for diagnosis.

6. Evidence you should inspect

Evidence Expected observation What it proves
Console 1 test, 1 passed Top-level status only
log.html Library imports, returned list/string/date/process/XML values Execution hierarchy and causality
output.xml Machine-readable keyword/result tree Post-processing source for later chapters
report.html Suite/test summary Human-readable outcome
Process result rc=0, stdout=verified, stderr=diagnostic Child-process contract
Teardown Directory no longer exists Owned scratch state was removed

7. Why copy before mutating collections

Copy List creates a new top-level list. The workflow appends only to that copy and then asserts that the original still contains two items. If the list contained nested mutable objects and both layers needed isolation, use deepcopy=True. Copying without a reason is noise; copying at an ownership boundary is defensive design.

8. Why UTC is explicit

Local time is convenient for humans but ambiguous in distributed evidence unless the time zone is also recorded. The lab requests UTC and formats it explicitly. The Z suffix is appended only because the call requested UTC. Never append Z to a LOCAL timestamp.

9. Why this child process is safe and diagnosable

The command is a known interpreter and the -c program is synthetic. It is passed as a separate argument with shell=False. stdout and stderr stay distinct, and the return code is asserted as an integer. If this child generated large output, the suite should redirect streams to workspace files instead of relying on unbounded in-memory capture.

10. Why the XML assertions are structural

The suite asks XML for the artifact/name text and artifact element’s id attribute. It does not compare the entire XML file as one string. That makes the intent resilient to harmless serialization differences such as indentation.

11. Small challenge

Change the synthetic manifest so count becomes 4. Add a structural assertion that detects the change. Then make the Python child exit with code 7 and verify that the test reports the process failure clearly while teardown still removes only the guarded workspace. Preserve the failing evidence/ directory before fixing the suite.

12. Knowledge check

Why is the Robot output directory outside the scratch workspace?

What is the benefit of keeping stdout and stderr separate?

What does dry run prove here?

Why use a unique RUN_ID?

13. Summary and next step

You have built a complete local workflow where every side effect has an owner, every important value is asserted, and cleanup is bounded. Lesson 3 generalizes these mechanics into design choices: when to use a standard library versus Python, how to avoid shell/process pitfalls, when to copy mutable data, and how to choose path/time/text/XML representations.

Next lesson

Collections, String, DateTime, OperatingSystem, Process, and XML Libraries: Configuration, Design Patterns, and Trade-Offs

Continue with Collections, String, DateTime, OperatingSystem, Process, and XML Libraries: Configuration, Design Patterns, and Trade-Offs. 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.