HTTP/API Automation, JSON Validation, and Service-Level Testing: Core Concepts and Mental Model
Build a precise Robot Framework service-testing mental model from domain API keyword through RequestsLibrary, HTTP transport, local server state, JSON validation, and result evidence.
Learning objectives
- Trace one service-level Robot step through a domain resource, RequestsLibrary, Python Requests, loopback server state, JSON conversion, assertions, and result evidence.
- Separate HTTP client/session state, Robot variable scope, synthetic server records, authentication/trust configuration, and output artifacts.
- Distinguish transport assertions from business assertions and explain why a 2xx response is not sufficient proof of behavior.
- Explain sessionless versus session-based request ownership and the security implications of TLS verification.
- Design API evidence that is useful for diagnosis without logging secrets or non-public payloads.
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. The problem: a green HTTP status can still describe a broken release
Browser tests from Chapter 16 exercised a user-facing interface.
Service-level tests move below the browser and speak HTTP directly.
They are usually faster and easier to isolate, but that speed can
create misleading confidence if the test only checks
200 OK. A service can return the wrong JSON shape, the
wrong record, stale data, an unexpected correlation identifier, or
even a success status for a failed business operation.
The central design rule for this chapter is therefore: transport truth and business truth are separate contracts. Transport truth covers method, URL, status, headers, timeout, TLS/authentication, and parseability. Business truth covers fields, relationships, state transitions, identity, invariants, and cleanup.
2. Read-only preflight before creating server or client state
python --version
python -m robot --version
python -m pip show robotframework-requests requests
# Verify the target is loopback before any mutation:
python -c "from urllib.parse import urlparse; u=urlparse('http://127.0.0.1:8766'); print(u.hostname, u.port)"
This inspection does not create an HTTP session or mutate server data. Record the interpreter, Robot version, RequestsLibrary version, underlying Requests version, exact target URL, expected local port, and current output directory. If the hostname is public or production-like, do not continue with the mandatory lab.
3. Mental model: five state stores, not one “Robot API state”
flowchart TD A[Robot test] --> B[Domain API resource] B --> C[RequestsLibrary] C --> D[Python Requests client/session] D --> E[HTTP request] E --> F[Loopback service] F --> G[Server record state] F --> H[HTTP response] H --> I[JSON object] I --> J[Transport + business assertions] J --> K[output.xml / log.html]
The arrows are ownership transitions. Robot resolves and executes keywords. The resource gives business names to HTTP operations. RequestsLibrary owns the Robot-to-Python bridge. Python Requests owns the concrete client/session object and TLS/socket behavior. The server owns durable fixture state. The response object is evidence returned to the caller. Robot assertions convert observations into PASS/FAIL. Result files record that execution independently of the live HTTP connection.
4. Terms and boundaries before mutation
| Term | Meaning in this chapter | Owner |
|---|---|---|
| Suite/test | Executable Robot scenario and its final status | Robot Framework |
| Domain API keyword |
Business-readable wrapper such as
Create Demo Item
|
Resource file |
| RequestsLibrary | External Robot library exposing HTTP keywords | External Python library |
| HTTP session | Reusable Requests client state such as headers/cookies/connection pools | RequestsLibrary/Python Requests |
| Server fixture state | Synthetic records held by the local service | Local AUT fixture |
| Robot variable | Reference to response, ID, or input with explicit scope | Robot runtime |
| Evidence artifact | output.xml, log/report, safe fixture log |
Robot/fixture filesystem |
| Credential/trust boundary | Authorization material, TLS CA verification, cookies | Client + environment; never source code |
5. RequestsLibrary is a transport adapter, not the service contract
RequestsLibrary wraps Python Requests and exposes Robot
keywords such as GET, POST,
DELETE, Create Session, and
Status Should Be. Starting with its 0.9 line,
sessionless request keywords are available. A sessionless call is
useful when one operation does not need persistent cookies or common
headers. A session is useful when many calls intentionally share
client configuration.
Do not let a session become hidden test state. Cookies, auth, default headers, retry adapters, TLS verification, and base URL configuration live longer than a single low-level request. Their lifetime must be explicit in the resource/lifecycle design.
Security boundary: RequestsLibrary 0.9.7 has a
legacy Create Session signature whose
verify default is false. The mandatory lab uses plain
loopback HTTP, so TLS is not involved. For HTTPS, explicitly
configure certificate verification and never teach
verify=False as a troubleshooting shortcut.
6. Status handling: implicit checks are useful, explicit negative contracts are safer
RequestsLibrary request keywords perform an implicit status check by
default. That is helpful for a straightforward success path:
expected_status=201 makes the transport expectation
visible at the call. For a deliberately negative case, use
expected_status=any to preserve the response and then
assert the exact expected status and error body yourself.
${response}= GET ${API_BASE}/items/9999 timeout=3 expected_status=any
Status Should Be 404 ${response}
${body}= Set Variable ${response.json()}
${error}= Get From Dictionary ${body} error
Dictionary Should Contain Item ${error} code not-found
The distinction prevents a common false green: “the request failed, so the negative test passed.” A negative test passes only when the intended failure contract is observed.
7. JSON is parsed data, not a formatted string
response.json() returns Python data structures. Use
Collections/BuiltIn operations to inspect semantic fields. Do not
compare pretty-printed JSON strings when order, whitespace, or
unrelated fields are not part of the contract.
${body}= Set Variable ${response.json()}
${data}= Get From Dictionary ${body} data
${attributes}= Get From Dictionary ${data} attributes
Dictionary Should Contain Item ${attributes} name alpha
Dictionary Should Contain Item ${attributes} kind demo
Focused assertions produce better diagnostics: the failure names the missing/wrong field rather than reporting a giant serialized-body difference.
8. Evidence and privacy
HTTP logs can disclose more than browser screenshots: Authorization headers, cookies, access tokens, personal fields, account IDs, request bodies, and server diagnostics. The local fixture logs only method, path, and a synthetic correlation ID. The Robot suite uses fake payloads. In production architecture, retain enough evidence to reconstruct the failed contract while redacting secrets and minimizing personal data.
| Evidence | Keep | Avoid |
|---|---|---|
| Request identity | method, loopback/service name, path template, correlation ID | real bearer tokens or session cookies |
| Response | status, selected headers, redacted business fields | unbounded full bodies with sensitive data |
| Robot result | keyword hierarchy, assertions, failure message | TRACE logging of credentials |
| Fixture log | safe request metadata and synthetic IDs | raw auth headers or secret payloads |
9. Why this matters in DevOps
Service-level Robot tests are strong release gates when they are deterministic: they are cheaper than browser flows, can target business contracts directly, and produce structured result evidence. They are weak gates when they depend on a public API, shared environment data, hidden session cookies, blanket retries, or “status code only” checks. The same suite should be reproducible from a developer machine and CI runner with the same command and isolated fixture state.
Knowledge check
A POST returns 201, but the JSON body contains the wrong customer tier. Did the service-level test prove the business outcome?
No. 201 proves only the expected transport status. The test must also assert the business fields/invariants that define success.
Is a RequestsLibrary session the same as a Robot suite variable?
No. The session is Python/HTTP client state managed by the external library. A Robot variable may reference an alias or response, but it does not own cookies, connection pooling, or TLS behavior.
Why use expected_status=any in a deliberate 404 test?
It prevents the request keyword from failing before the test can assert the exact negative contract. The test then checks 404 and the intended error payload explicitly.
What should happen if the target URL is not loopback in the mandatory lab?
Stop. The lab is designed only for a disposable local service. Never redirect failure injection or CRUD cleanup to a public/production API.
10. Summary and bridge
Service-level Robot automation is a pipeline of owned states: Robot execution, domain resource, HTTP library/client, server record state, response data, assertions, and evidence. Lesson 2 builds that pipeline end to end against a disposable loopback CRUD-like fixture.
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.