Chapter 17Lesson 01180–240 min

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.

RequestsLibrary 0.9.7HTTP stateJSONTransport vs businessEvidence

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”

Service-level execution ownership
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?

Is a RequestsLibrary session the same as a Robot suite variable?

Why use expected_status=any in a deliberate 404 test?

What should happen if the target URL is not loopback in the mandatory lab?

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.

Next lesson

HTTP/API Automation, JSON Validation, and Service-Level Testing: Guided Hands-On Workflow

Continue with HTTP/API Automation, JSON Validation, and Service-Level Testing: Guided Hands-On Workflow. 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.

References and version anchors

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.