Logs, Reports, output.xml, Rebot, and Result Post-Processing: Guided Hands-On Workflow
Create two disposable executions, inspect their XML, regenerate presentations, combine independent results, rerun a controlled failure, merge it correctly, and produce xUnit evidence.
Learning objectives
- Create separate, deterministic output directories without overwriting earlier evidence.
- Inspect output.xml root/suite/test/status metadata with a small standard-library Python tool.
- Regenerate log/report from a raw output using Rebot.
- Combine independent roots and merge a failed-test rerun using the correct identity semantics.
- Generate xUnit and record artifact sizes/checksums/privacy observations.
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. The 7.4.2 result.xsd is schema version
5; default XML outputs carry a
schemaversion attribute and Robot Framework 7.x can
also read legacy output. --legacyoutput exists for
Robot Framework 6.x-compatible consumers. Rebot combines independent
outputs by creating a new parent suite; --merge is for
the same logical top-level suite, including reruns, where later
matching test results replace earlier results and later SKIP results
do not replace originals. The built-in Testdoc tool is deprecated in
7.4.2 in favor of external Testdoc and is not a result-reporting
substitute.
1. Disposable scenario and safety boundary
Create a new local directory named rf14-evidence.
Everything in this lesson is synthetic: no browser, API, database,
SSH host, cloud account, production service, credential, or external
network target is required. Results live under
results/; source files live under suites/;
a tiny read-only XML inspection helper lives under
tools/.
Do not reuse a production results directory. The
commands use separate subdirectories so the first run, rerun,
combined outputs, and derivatives remain distinguishable. Delete
only the disposable rf14-evidence directory after
verification.
2. Preflight and exact assumptions
python --version
python -m robot --version
python -m robot.rebot --version
Expected baseline for this chapter: Python 3.8+ and Robot Framework 7.4.2. If your stable version differs, re-check Rebot/output-format behavior before copying version-specific expectations such as schema version 5. The mandatory path uses only Robot Framework core/BuiltIn and Python standard library.
3. Create three tiny suites
*** Test Cases ***
Independent A Is Healthy
[Tags] evidence independent-a
Should Be Equal alpha alpha
Log run-a synthetic evidence
Save as suites/independent_a.robot.
*** Test Cases ***
Independent B Is Healthy
[Tags] evidence independent-b
Should Be Equal As Integers 2 2
Log run-b synthetic evidence
Save as suites/independent_b.robot.
*** Variables ***
${OBSERVED} broken
*** Test Cases ***
Release Gate
[Tags] evidence rerun
Should Be Equal ${OBSERVED} repaired msg=Release gate expected repaired state
Stable Check
[Tags] evidence rerun
Should Be Equal stable stable
Save as suites/rerun.robot. The variable is
intentionally overridable from the command line so the initial
failure and repaired rerun use the same source identity.
4. Build a read-only output inspector
from pathlib import Path
import sys
import xml.etree.ElementTree as ET
path = Path(sys.argv[1])
root = ET.parse(path).getroot()
suite = root.find("suite")
tests = root.findall(".//test")
print("file:", path)
print("root:", root.tag)
print("generator:", root.attrib.get("generator"))
print("generated:", root.attrib.get("generated"))
print("schemaversion:", root.attrib.get("schemaversion"))
print("rpa:", root.attrib.get("rpa"))
print("top suite:", suite.attrib.get("name") if suite is not None else None)
for test in tests:
status = test.find("status")
print("test:", test.attrib.get("name"), "status:", status.attrib.get("status") if status is not None else None)
Save as tools/inspect_output.py. It reads XML only; it
does not mutate Robot results. That makes it suitable for
before/after evidence comparisons.
5. Run two independent suites into separate directories
python -m robot --outputdir results/run-a suites/independent_a.robot
python -m robot --outputdir results/run-b suites/independent_b.robot
python tools/inspect_output.py results/run-a/output.xml
python tools/inspect_output.py results/run-b/output.xml
Expected: both runs PASS and each directory contains
output.xml, log.html, and
report.html. The inspector should show schema metadata
and different top-level suite names derived from the two files.
Nothing in this step changes external state beyond the result files
themselves.
6. Regenerate a presentation without rerunning tests
python -m robot.rebot --outputdir results/rebuilt-a --log log.html --report report.html results/run-a/output.xml
PowerShell can use the same arguments on one line, or backticks for
continuation. Rebot reads results/run-a/output.xml and
creates new HTML under results/rebuilt-a. By default
Rebot does not create a new XML output unless
--output is explicitly supplied. The test was not
re-executed.
7. Combine independent roots
python -m robot.rebot --name "Independent Evidence Bundle" --output combined.xml --outputdir results/combined results/run-a/output.xml results/run-b/output.xml
python tools/inspect_output.py results/combined/combined.xml
Expected: Rebot creates a new top-level suite named
Independent Evidence Bundle, with the original A and B
roots as children. This is correct because the inputs are
independent. The resulting report should show two passing tests. The
command also creates a new machine-readable
combined.xml because --output was
requested.
8. Create a controlled failure, rerun only the failure, then merge
python -m robot --variable OBSERVED:broken --outputdir results/rerun/original suites/rerun.robot
# Expected non-zero status because Release Gate fails.
python -m robot --rerunfailed results/rerun/original/output.xml --variable OBSERVED:repaired --outputdir results/rerun/retry suites/rerun.robot
python -m robot.rebot --merge --output merged.xml --outputdir results/rerun/merged results/rerun/original/output.xml results/rerun/retry/output.xml
python tools/inspect_output.py results/rerun/merged/merged.xml
The first run should contain one FAIL and one PASS. The rerun should
execute only the previously failed test and PASS when
OBSERVED is overridden to repaired.
--merge is valid because both files describe the same
top-level suite. The merged result should contain two tests with
final PASS status, and the replaced test message in the merged
result records that an earlier result was replaced.
Do not delete the original failure. The merged result is a corrected operational view, not a reason to destroy the first-failure artifact.
9. Generate a CI-friendly xUnit derivative
python -m robot.rebot --xunit xunit.xml --log NONE --report NONE --outputdir results/rerun/xunit results/rerun/merged/merged.xml
Expected: results/rerun/xunit/xunit.xml. xUnit is
useful for CI test dashboards, but it is a derivative summary. Keep
the Robot result needed for Robot-aware diagnosis and
post-processing.
10. Record artifact sizes and checksums
from pathlib import Path
import hashlib
for p in sorted(Path("results").rglob("*")):
if p.is_file():
digest = hashlib.sha256(p.read_bytes()).hexdigest()[:16]
print(f"{p} bytes={p.stat().st_size} sha256={digest}")
Save as tools/manifest.py and run
python tools/manifest.py. The checksum does not prove
the run was correct, but it lets a later reviewer detect whether an
artifact changed after capture.
11. Privacy/redaction check before publishing artifacts
from pathlib import Path
FORBIDDEN = ["password-FAKE_DO_NOT_USE", "token-FAKE_DO_NOT_USE", "PRIVATE_KEY"]
for p in Path("results").rglob("*"):
if not p.is_file() or p.suffix.lower() not in {".xml", ".html", ".txt", ".json"}:
continue
text = p.read_text(encoding="utf-8", errors="ignore")
hits = [value for value in FORBIDDEN if value in text]
if hits:
print("REVIEW", p, hits)
This is only a synthetic guardrail, not a complete DLP system. In production, define organization-specific patterns and access rules. If a real secret has already reached raw output, do not claim that generating a cleaner report makes the leak disappear.
12. Challenge: choose the transformation, do not copy a command
You receive three artifacts: two independent platform runs and one rerun of failed tests from only the Linux platform. Design the smallest evidence pipeline that (1) merges Linux original+rereun first, (2) leaves Windows independent, and (3) combines the corrected Linux root with Windows under one aggregate report. Explain why reversing those two operations would distort identity.
13. Verification and cleanup
- Both independent runs have separate output/log/report files.
- The rebuilt HTML is derived from the original XML without new execution.
- Combined evidence contains two independent child roots.
- The rerun result contains only the selected failed test.
- The merged rerun result contains the full logical suite with the replacement result.
- xUnit exists as a derivative, not the sole retained source.
- Artifact sizes/checksums and privacy scan were recorded.
After review, remove only the disposable
rf14-evidence directory. Preserve it if it is your
evidence packet.
14. Knowledge check
Why does rebuilding log.html with Rebot not change the system under test?
Rebot reads recorded result data and creates new result presentations; it does not execute test keywords or call the system under test.
Why must the original failed output remain after a successful rerun merge?
It is first-failure evidence. The merged result is the corrected final view, while the original preserves what failed before the rerun.
What structural change should you expect when combining run-a and run-b?
A new top-level suite is created and the two independent source roots become children beneath it.
What should be different in the rerun output compared with the original release suite?
Only tests selected by --rerunfailed should be present in the rerun result; the repaired variable/input should make the selected test pass.
Why is a forbidden-marker scan not a complete redaction solution?
It checks only known patterns. Real privacy control requires preventing sensitive logging, Secret-aware handling where appropriate, restricted access, and organization-specific review/DLP rules.
15. Summary and next step
You have executed the complete result pipeline: isolated runs, raw XML inspection, presentation regeneration, correct combining, correct rerun merging, xUnit generation, checksums, and privacy checks. Lesson 3 turns these mechanics into design policy for large CI estates.
Further reading
- Robot Framework 7.4.2 User Guide — Post-processing outputs — Rebot, combine, merge, and JSON/XML result processing.
- Robot Framework 7.4.2 User Guide — Different output files — output, log, report, xUnit, and output-directory behavior.
- Robot Framework 7.4.2 User Guide — Removing and flattening keywords — output-size and evidence trade-offs.
- Robot Framework 7.4.2 result.xsd — authoritative XML schema version and root attributes.
- Robot Framework 7.4.2 release notes — stable release details and built-in Testdoc deprecation.
- Robot Framework 7.4.2 on PyPI — pinned package metadata and Python requirement.
- Robot Framework releases — re-check stable/pre-release status when updating this chapter.
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.