Checkpoint Lab — Style Guides, Robocop, Documentation, Naming, and Maintainability
Checkpoint: standardize a messy multi-file Robot project with non-destructive previews, manual semantic refactoring, current Robocop policy, Libdoc, a narrow exception register, and CI-ready evidence.
Checkpoint outcomes
- Predict source, model, config, and result changes before performing them.
- Prove generated/vendor content remains unchanged while first-party source is normalized.
- Separate formatter changes from manual naming/documentation architecture improvements.
- Record a justified narrow suppression with owner and expiration/removal criteria.
- Produce a reproducible evidence packet and minimal CI-style command sequence.
Current compatibility baseline — verified 2026-09-01.
Robot Framework 7.4.2 is the stable course baseline
and requires Python 3.8+. This chapter pins
Robocop 9.0.0, released 2026-08-26, which requires
Python 3.10+ and Robot Framework 5+. The combined mandatory lab
therefore uses Python 3.10+. The Robot Framework
community Style Guide currently identifies itself as
0.10b. Modern Robocop has two modes:
robocop check for lint/static analysis and
robocop format for formatting. Standalone Robotidy is
not the recommended new workflow because its formatter functionality
was merged into Robocop 6+. Formatting is source normalization, not
proof of good architecture.
1. Scenario and safety boundary
You inherit a tiny synthetic checkout project with inconsistent formatting, vague names, missing public documentation, and one simulated legacy adapter. You must improve it without touching generated content, without using blanket suppressions, and without pretending formatting proves functional correctness.
flowchart TD A[Messy parser-valid project] --> B[Baseline dry-run + hashes] B --> C[Lint + format preview] C --> D[Apply mechanical format] D --> E[Manual semantic refactor] E --> F[Narrow documented exception] F --> G[Libdoc + style checks] G --> H[Robot dry-run/run] H --> I[Evidence ledger / CI command] B -. generated hash .-> I G -. formatter/linter exit codes .-> I
The generated-file hash bypasses Robocop and independently proves exclusion. The formatter/linter exit codes prove mechanical policy. Robot dry-run/run proves the executable model. These are intentionally separate claims.
2. Preflight and disposable root
Use a temporary or throwaway directory. The following Bash example asks Python for the platform temp directory and creates a uniquely named root:
LAB_ROOT="$(python -c 'import tempfile; print(tempfile.mkdtemp(prefix="rf27-checkpoint-"))')"
echo "$LAB_ROOT"
cd "$LAB_ROOT"
mkdir -p suites resources generated evidence
python --version | tee evidence/python-version.txt
python -m robot --version | tee evidence/robot-version.txt
robocop --version | tee evidence/robocop-version.txt
PowerShell equivalent:
$LAB_ROOT = Join-Path ([System.IO.Path]::GetTempPath()) ("rf27-checkpoint-" + [guid]::NewGuid())
New-Item -ItemType Directory -Force $LAB_ROOT | Out-Null
Set-Location $LAB_ROOT
New-Item -ItemType Directory -Force suites,resources,generated,evidence | Out-Null
python --version | Tee-Object evidence/python-version.txt
python -m robot --version | Tee-Object evidence/robot-version.txt
robocop --version | Tee-Object evidence/robocop-version.txt
Cleanup guard. Never translate this lab into a
recursive delete of an arbitrary current directory. Cleanup is
allowed only after you confirm the path basename starts with
rf27-checkpoint- and resides under the
operating-system temporary directory.
3. Build the messy project
suites/checkout.robot:
*** Settings ***
Resource ../resources/checkout_keywords.resource
*** Test Cases ***
checkout_smoke
${result}= process_checkout ORD-9 2
Should Be Equal ${result} ORD-9|2
resources/checkout_keywords.resource:
*** Keywords ***
process_checkout
[Arguments] ${order_id} ${quantity}
${summary}= Catenate SEPARATOR=| ${order_id} ${quantity}
RETURN ${summary}
legacy_adapter_ping
Log Synthetic legacy adapter only
generated/generated.resource:
*** Keywords ***
machine_generated_name
Log Generated fixture must remain byte-identical
4. Predict before acting
| Prediction | Expected state change | Independent verification |
|---|---|---|
| Formatter preview | No source bytes change. | Hash source before/after preview. |
| Formatter apply | First-party spacing/name normalization may change source. | Unified diff + formatter check. |
| Manual refactor | Keyword/test names and documentation change intentionally. | Reviewer diff + Libdoc. |
| Generated fixture | Must remain byte-identical. | SHA-256 before/after. |
| Narrow suppression | Only the declared rule/path is ignored. | Other rules still report if introduced. |
| Final style gate | Both check and format --check return 0. | Captured exit codes. |
| Robot behavior | Synthetic test remains PASS. | output.xml/log/report and return code. |
5. Preserve the baseline
python -c "from pathlib import Path; import hashlib; p=Path('generated/generated.resource'); print(hashlib.sha256(p.read_bytes()).hexdigest())" > evidence/generated-before.sha256
python -m robot --dryrun --outputdir evidence/baseline-dryrun suites
robocop check suites resources > evidence/lint-before.txt 2>&1 || true
robocop format --no-overwrite --diff suites resources > evidence/format-preview.diff
robocop format --check suites resources; echo $? > evidence/format-check-before.exit
|| true above is used only to preserve a baseline
artifact inside this disposable exercise. Do not use it in
the final CI gate. The original non-zero result must be recorded and
later removed from the authoritative gate.
6. Add current Robocop policy and exception register
[tool.robocop]
target-version = 7
exclude = ["generated", "evidence"]
force-exclude = true
[tool.robocop.lint]
extend-select = ["missing-doc-keyword", "missing-doc-test-case"]
configure = ["line-too-long.line_length=100"]
[tool.robocop.format]
space-count = 4
line-length = 100
line-ending = "unix"
Initially there is no suppression. Create
STYLE_EXCEPTIONS.md with the schema below, but do not
add an exception until you can justify it:
# Style Exceptions
For each exception record:
- Rule
- Exact path or line
- Reason
- Owner
- Review-by date
- Removal condition
7. Apply only the mechanical changes
robocop format --no-overwrite --diff suites resources > evidence/format-preview-with-config.diff
robocop format suites resources
robocop format --check suites resources
robocop check suites resources > evidence/lint-after-format.txt 2>&1 || true
Inspect the files. Spacing/statement layout should now be normalized. Missing documentation or vague semantic names may remain. That is expected and is the reason this checkpoint separates mechanical and semantic phases.
8. Manual semantic refactor
Replace suites/checkout.robot with:
*** Settings ***
Documentation Synthetic checkout contract checks with no external side effects.
Resource ../resources/checkout_keywords.resource
*** Test Cases ***
Build Synthetic Checkout Summary
[Documentation] Verifies that the reusable checkout summary preserves order ID and quantity.
${result}= Build Checkout Summary ORD-9 2
Should Be Equal ${result} ORD-9|2
Replace the resource with:
*** Settings ***
Documentation Reusable synthetic checkout keywords. No network, payment, database, or production state is used.
*** Keywords ***
Build Checkout Summary
[Documentation] Builds a deterministic checkout summary with no external side effects.
[Arguments] ${order_id} ${quantity}
${summary}= Catenate SEPARATOR=| ${order_id} ${quantity}
RETURN ${summary}
Legacy Adapter Ping
Log Synthetic legacy adapter only
Now the public names describe intent. The documentation says what matters: deterministic behavior and no external side effects. It does not narrate every line.
9. Add one narrow, justified exception
Assume Legacy Adapter Ping is generated by a pending
migration and adding keyword documentation would be overwritten next
week. Rather than disabling documentation checks for the whole file,
use a line-level rule-specific disabler:
Legacy Adapter Ping # robocop: off=missing-doc-keyword
Log Synthetic legacy adapter only
Record:
Rule: missing-doc-keyword
Path: resources/checkout_keywords.resource :: Legacy Adapter Ping only
Reason: adapter keyword is generated by legacy migration tooling; manual documentation would be overwritten
Owner: automation-platform
Review-by: 2026-11-01
Removal condition: legacy adapter generator is retired
This is still technical debt, but it is visible, bounded, and reviewable.
10. Generate Libdoc and run the authoritative gates
python -m robot.libdoc resources/checkout_keywords.resource evidence/checkout_keywords.html
robocop check suites resources
printf '%s
' "$?" > evidence/lint-final.exit
robocop format --check suites resources
printf '%s
' "$?" > evidence/format-final.exit
python -m robot --dryrun --outputdir evidence/final-dryrun suites
python -m robot --outputdir evidence/final-run suites
For PowerShell, save $LASTEXITCODE after each command
instead of $?. The authoritative CI command must allow
non-zero style statuses to fail the job; do not append
|| true.
11. Prove generated content was not touched
python -c "from pathlib import Path; import hashlib; p=Path('generated/generated.resource'); print(hashlib.sha256(p.read_bytes()).hexdigest())" > evidence/generated-after.sha256
diff evidence/generated-before.sha256 evidence/generated-after.sha256
A zero diff status proves the generated fixture
remained byte-identical. This is stronger than assuming the
exclusion “probably worked.”
12. Minimal CI-ready style gate
python --version
python -m robot --version
robocop --version
robocop check suites resources
robocop format --check suites resources
python -m robot --dryrun --outputdir evidence/ci-dryrun suites
This is intentionally provider-neutral. GitHub Actions, GitLab CI, Jenkins, containers, and Pabot add execution infrastructure, not a different style policy. Put provider-specific details in their dedicated courses.
13. Evidence packet and verification checklist
| Artifact | Required check |
|---|---|
| Version manifests | Python/Robot/Robocop match the documented baseline. |
format-preview.diff |
Preview existed before overwrite. |
| Before/after source | Mechanical and semantic changes are distinguishable. |
| Robocop config | Target version/exclusions/rules are committed and reviewable. |
| Final lint/format exit codes | Both authoritative style gates return 0. |
| Libdoc HTML | Public reusable keyword contract is visible. |
| STYLE_EXCEPTIONS.md | Every suppression has rule/path/reason/owner/review/removal. |
| Generated hashes | Before and after SHA-256 match. |
| Robot dry-run/run | Final source parses and synthetic behavior passes. |
| output.xml/log/report | Functional evidence is preserved separately from style evidence. |
14. Cleanup / rollback
Because the lab lives in a unique temporary root, rollback is
simple—but still guard it. Leave the evidence packet in place until
reviewed. When finished, move outside the root, print the path,
verify its basename begins with rf27-checkpoint-, and
only then remove that exact directory. Never generalize the cleanup
into “delete the current temp directory.”
Knowledge check
The format preview changes source bytes. What has gone wrong?
Preview was not truly non-destructive, or another process modified the files. Stop, restore the baseline, confirm the exact command/version, and rerun with --no-overwrite --diff.
The final generated-file hashes differ. Is a clean Robocop exit enough to proceed?
No. The lab contract says generated content must remain untouched. Inspect file discovery/exclusion and restore the generated artifact before accepting the change.
Why is one rule-specific legacy suppression acceptable here while a whole-file off directive is not?
The exception is bounded to a known keyword and documented with an owner/removal condition. The rest of the file remains protected by current and future rules.
The linter and formatter both return 0, but the Robot test fails. Which evidence wins?
They answer different questions. Style success does not override runtime failure; preserve output.xml/log/report and diagnose functional behavior separately.
What does Chapter 27 add to a production Robot operating model?
A reproducible source-quality layer: pinned conventions, non-destructive formatter review, static diagnostics, documented exceptions, interface docs, and machine-enforceable style gates that remain separate from semantic/runtime validation.
Summary and bridge to Chapter 28
Chapter 27 turns style into an auditable engineering process instead of personal preference. You can now normalize source safely, lint against a pinned policy, maintain clear names/docs, protect generated content, and keep suppressions narrow. Chapter 28 builds on that discipline by measuring performance, large-suite cost, output growth, and execution optimization—again separating observed bottlenecks from convenient guesses.
Current primary references
- Robocop 9.0.0 on PyPI — Pinned current stable lab version and Python requirement.
- Robocop stable documentation — Current linter/formatter commands.
- Robocop configuration reference — Current target-version, exclude, force-exclude, fix and formatter settings.
- Robocop disablers — Current narrow suppression syntax.
- Robot Framework Style Guide — Current community style baseline.
- Robot Framework 7.4.2 User Guide — Stable syntax, resources, Libdoc and execution behavior.
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.