Chapter 27Lesson 05240–300 min

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 labRobocop 9.0.0Style evidenceLibdocCI-ready

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.

Checkpoint evidence flow
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?

The final generated-file hashes differ. Is a clean Robocop exit enough to proceed?

Why is one rule-specific legacy suppression acceptable here while a whole-file off directive is not?

The linter and formatter both return 0, but the Robot test fails. Which evidence wins?

What does Chapter 27 add to a production Robot operating model?

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.

Next lesson

Performance, Large Suites, Output Management, and Execution Optimization: Core Concepts and Mental Model

Continue with Performance, Large Suites, Output Management, and Execution Optimization: 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.

Current primary references

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.