Checkpoint Lab — HTTP/API Automation, JSON Validation, and Service-Level Testing
Complete a local service-level checkpoint that creates, reads, validates, corrupts, diagnoses, and removes synthetic API records while preserving safe request/response and Robot evidence.
Checkpoint objectives
- Predict source/runtime/server/result changes before each operation.
- Produce a deterministic health + CRUD-like contract suite against the loopback fixture.
- Separate transport, JSON parsing, and business assertions in the evidence packet.
- Inject malformed-response and wrong-expectation failures without changing the target or disabling trust checks.
- Prove that cleanup removes only records owned by the current test.
Current compatibility baseline — verified 2026-08-31.
Robot Framework 7.4.2 is the stable course
baseline. The mandatory HTTP layer uses
robotframework-requests 0.9.7, the latest stable
RequestsLibrary release; the 1.0a series remains prerelease. The
underlying Python Requests project is independently versioned; at
generation time its stable release is 2.34.2. The
lab uses Python 3.10+ for a single consistent environment even
though Robot Framework itself supports Python 3.8+. All required
targets are 127.0.0.1 loopback and all
records/credentials are synthetic. No public API, paid service,
browser, database, SSH target, Pabot, CI provider, or container
runtime is required.
1. Scenario and safety boundary
You are creating a release-smoke evidence packet for a synthetic
item service. The only approved target is
http://127.0.0.1:8766. You will read health,
create/read/delete one record, prove the record disappears, then
exercise a deliberately malformed JSON response. No public endpoint,
credential, database, browser, or external service is involved.
2. Exact preflight
python --version
python -m robot --version
python -m pip show robotframework-requests requests
# Confirm loopback health before test mutation:
python -c "import urllib.request; print(urllib.request.urlopen('http://127.0.0.1:8766/health', timeout=2).status)"
Record exact versions and the health status. Expected baseline: Robot 7.4.2; RequestsLibrary 0.9.7; Requests version recorded from your environment; loopback service returns 200.
3. Required project files
rf-api-lab/
├── fixture_api.py
├── resources/
│ └── api.resource
├── tests/
│ └── api_contract.robot
└── results/
Reuse the exact fixture_api.py and
api.resource from Lesson 2. This checkpoint changes the
test contract, not the service implementation.
4. Make predictions before execution
| Prediction | Verify independently after run |
|---|---|
| Health GET changes no server record | fixture log + later first created ID remains 1 |
| Create adds exactly one owned record and returns 201 + ID | POST response JSON + subsequent GET |
| Delete removes that exact ID and returns 204 | follow-up GET returns 404 |
| Malformed endpoint returns HTTP 200 but JSON decoding fails | response status/header + Robot failure/status evidence |
| Teardown does nothing after explicit successful delete |
OWNED_ITEM_ID reset to empty before teardown
|
5. Checkpoint suite
*** Settings ***
Resource ../resources/api.resource
Suite Setup Reset Local Fixture
Test Setup Initialize Ownership
Test Teardown Cleanup Owned Item
*** Test Cases ***
Health Contract Is Read Only
${headers}= Build Safe Headers rf-health-checkpoint
${response}= GET ${API_BASE}/health headers=${headers} timeout=${HTTP_TIMEOUT} expected_status=200
Response Correlation Should Be ${response} rf-health-checkpoint
Dictionary Should Contain Item ${response.json()} status ok
Create Read And Delete Owned Record
${item_id} ${created}= Create Demo Item checkpoint-alpha boundary rf-create-checkpoint
VAR ${OWNED_ITEM_ID} ${item_id} scope=TEST
Status Should Be 201 ${created}
${fetched}= Get Demo Item ${item_id} rf-get-checkpoint
Item Business Fields Should Be ${fetched} checkpoint-alpha boundary
${deleted}= Delete Demo Item ${item_id} rf-delete-checkpoint
Status Should Be 204 ${deleted}
VAR ${OWNED_ITEM_ID} ${EMPTY} scope=TEST
${missing}= Get Demo Item ${item_id} rf-confirm-delete expected=any
Status Should Be 404 ${missing}
Malformed JSON Is A Contract Failure
${headers}= Build Safe Headers rf-malformed-checkpoint
${response}= GET ${API_BASE}/malformed headers=${headers} timeout=${HTTP_TIMEOUT} expected_status=200
Response Correlation Should Be ${response} rf-malformed-checkpoint
${status} ${message}= Run Keyword And Ignore Error Parse Response JSON ${response}
Should Be Equal ${status} FAIL
Should Contain ${message} Expecting
*** Keywords ***
Initialize Ownership
VAR ${OWNED_ITEM_ID} ${EMPTY} scope=TEST
Cleanup Owned Item
IF $OWNED_ITEM_ID
Delete Demo Item ${OWNED_ITEM_ID} rf-cleanup-${OWNED_ITEM_ID} expected=any
END
The malformed-JSON test deliberately converts the parsing failure into an inspected status/message because the purpose of this checkpoint case is to prove the failure contract. It must still assert that parsing actually failed. This is different from swallowing an unknown service error and continuing.
6. Run the controlled checkpoint
# PowerShell
.\.venv\Scripts\python -m robot --outputdir results\checkpoint tests\api_contract.robot
# Bash
./.venv/bin/python -m robot --outputdir results/checkpoint tests/api_contract.robot
Expected high-level result: the suite passes because the malformed-JSON case explicitly verifies that decoding fails. This is an intentional negative contract, not a false green. Inspect the log hierarchy and fixture log to confirm request sequence and correlation identifiers.
7. Failure injection A: wrong business expectation
Change only the expected name in the GET assertion from
checkpoint-alpha to checkpoint-beta.
Predict: transport remains 200, JSON parsing succeeds, the business
assertion fails, teardown still removes the owned item, and the
original failing run remains in its own output directory.
# Run into a separate directory; do not overwrite the passing evidence.
python -m robot --outputdir results/failure-business --test "Create Read And Delete Owned Record" tests/api_contract.robot
Repair the expected value, then rerun the single test into
results/repaired-business. Compare the response status
and the failing assertion message. This proves why transport and
business evidence must be separate.
8. Failure injection B: malformed representation
Temporarily remove the negative-test wrapper around
${response.json()} so the decoding exception becomes a
normal test failure. Preserve the HTTP 200 response, Content-Type,
correlation header, safe fixture log line, and Robot exception. Then
restore the explicit negative contract.
9. Redaction and retention policy exercise
| Artifact | Retention decision | Redaction rule |
|---|---|---|
| Original output.xml | retain through review/release evidence window | never include real authorization values in source/logged args |
| log.html/report.html | retain with access control | avoid full sensitive bodies; synthetic lab data only |
| fixture stdout | retain short checkpoint excerpt | method/path/correlation only; no bodies/tokens |
| request/response samples | retain selected fields only | remove cookies/auth/PII; IDs synthetic |
| failure and repaired runs | retain both until diagnosis is signed off | do not overwrite first failure |
10. Required evidence packet
- Python, Robot Framework, RequestsLibrary, and Requests versions.
- Exact loopback base URL and test command.
- Health status/body and correlation ID.
- Create response: method/path, 201, correlation header, synthetic ID, selected JSON fields.
- Read response: 200 plus nested business assertions.
- Delete response: 204 plus follow-up 404 proving state removal.
- Malformed-response evidence: 200 transport + JSON decode failure.
- Original wrong-expectation failure and repaired run in separate directories.
- Fixture log excerpt containing only method/path/correlation.
- Cleanup proof and a short retention/redaction policy.
11. Verification checklist
- The only target is 127.0.0.1:8766.
- Every HTTP call has a bounded timeout.
- Success paths assert both transport and business outcomes.
- Negative paths assert exact intended status/error behavior.
- No TLS verification is disabled in any HTTPS example.
- No real credentials, cookies, tokens, PII, public APIs, or production data appear.
- No blanket retry, giant sleep, broad EXCEPT, or result deletion hides a failure.
- Each created record is owned and removed by the test that created it.
- First failure and repaired evidence remain separate.
12. Cleanup / rollback
- Confirm the follow-up GET returns 404 for the checkpoint record.
- Stop the specific loopback fixture with Ctrl+C.
- Keep results until review is complete.
- Delete only the disposable project directory if desired.
- If a test unexpectedly targeted anything other than loopback, stop and follow your environment's incident/data-cleanup process rather than attempting broad automated deletion.
Knowledge check
Why can the malformed-JSON checkpoint test legitimately end PASS?
Because it is a negative contract that explicitly proves decoding fails for the deliberately malformed endpoint. The failure is not ignored; it is asserted as the expected behavior of this synthetic diagnostic case.
The POST returns 201 but the follow-up GET returns the wrong name. Which layer failed?
The service/business-state contract failed. Transport for both calls may be correct; the persisted business data is wrong.
What makes cleanup safe in this lab?
The test stores the exact ID it created, deletes only that ID, and clears ownership after explicit deletion. The target is also guarded as loopback-only.
A CI run wants to log every Authorization header for debugging. What should you do?
Reject that design. Use correlation IDs and selected non-sensitive metadata; credentials are trust-boundary data and must not be copied into test artifacts.
What capability does Chapter 17 add to the Robot operating model?
A governed service-testing layer: domain API resources, explicit HTTP client/session ownership, transport + JSON business assertions, isolated server data, safe evidence, and deterministic cleanup.
13. Production operating model and Chapter 18 bridge
After Chapter 17, Robot can operate a browser layer and a service layer without confusing their state stores. Chapter 18 expands the same ownership discipline to databases, SSH, filesystem, processes, and infrastructure automation, where transaction/connection/process state must remain just as explicit.
References and version anchors
- Robot Framework 7.4.2 User Guide — execution, variables, lifecycle, status, result, and library boundaries.
- RequestsLibrary keyword documentation, RequestsLibrary 0.9.7 on PyPI, and maintainer repository — HTTP keyword signatures, session behavior, status handling, and release status.
- Python Requests documentation and Requests 2.34.2 on PyPI — underlying HTTP client semantics and current transport-library release anchor.
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.