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.
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?
The scratch workspace is intentionally deleted in teardown, while output.xml/log/report are diagnostic evidence that should survive the run.
What is the benefit of keeping stdout and stderr separate?
It preserves the child process contract and makes diagnostics clearer than merging all output into one stream.
What does dry run prove here?
Robot parsing, imports and keyword/argument structure. It does not execute the external filesystem/process/XML side effects.
Why use a unique RUN_ID?
It prevents accidental workspace collisions, especially when humans or parallel workers run the same suite concurrently.
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.
Further reading
- Robot Framework 7.4.2 Collections — list/dictionary mutation, copying, comparison, and current type-conversion behavior.
- Robot Framework 7.4.2 String — text/bytes transformation and encoding-related keywords.
- Robot Framework 7.4.2 DateTime — timestamps, time intervals, conversion, LOCAL/UTC handling, and result formats.
- Robot Framework 7.4.2 OperatingSystem — portable file/directory/environment operations and deprecated process-running keywords.
- Robot Framework 7.4.2 Process — structured process invocation, result objects, output redirection, timeouts, and cleanup.
- Robot Framework 7.4.2 XML — parsing, XPath-style element lookup, verification, mutation, and explicit save semantics.
- Robot Framework 7.4.2 release — stable release baseline used in these lessons.
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.