Now accepting guest editorial from SAP, Oracle, Workday and ServiceNow practitioners.Pitch a guide
The Sign-Off Table

Lesson 2 of 5

OData automation

19 min

Listen to this lesson

0:00 / 7:39

OData is the protocol behind SAP Fiori and most released SAP S/4HANA APIs. It is plain HTTP with conventions: resources are entity sets and entities, reads are GET, creates are POST, updates are PUT, PATCH or MERGE, deletes are DELETE. SAP S/4HANA exposes both OData V2 and V4 services; many released A2X APIs, such as the Sales Order (A2X) service API_SALES_ORDER_SRV, are OData V2. The same automation principles apply to both.

Check the version of every API you automate against. SAP keeps publishing OData V4 versions of business APIs alongside the older V2 ones, and the two differ in ways that matter to a test: V4 uses PATCH rather than MERGE, a different $batch format and JSON by default. The SAP Business Accelerator Hub shows which version is released for your product and release, and whether an API is marked as deprecated with a successor. Build factories and checks on the version your integrations actually use.

Start from the metadata

Every OData service publishes a $metadata document describing entity types, keys, properties, navigation properties and function imports or actions. Automate a metadata check first: fetch $metadata and assert that the entity sets and properties your tests depend on still exist. After an upgrade or a transport, this one call tells you whether a contract changed before twenty data tests fail for confusing reasons.

Reading: keys and query options

Single entities are addressed by key, for example an order by its sales order number. Collections are filtered and shaped with query options. SAP Gateway documentation lists which options the framework provides automatically ($select, $expand, $count, $format) and which need implementation by the service developer ($filter, $orderby, $top, $skip, $inlinecount, $skiptoken). For custom services that is a test point in itself: a filter that a developer forgot to implement can return unfiltered data with a 200 status.

  • Use $filter to find exactly your test data, for example orders with your run's customer reference.
  • Use $select to return only the fields you assert on, which keeps responses small and assertions clear.
  • Use $expand to fetch items with the header in one call when you assert on both.
  • Page with $top and $skip; never assume a collection returns everything in one response.

Writing: CSRF tokens

SAP Gateway protects all modifying requests with a CSRF (cross-site request forgery) token. SAP's documentation describes the handshake: send a non-modifying request such as a GET with the header X-CSRF-Token: Fetch; the server returns a token in the X-CSRF-Token response header and also sets an anti-XSRF cookie named sap-XSRF_<SID>_<client>. Every POST, PUT, PATCH, MERGE or DELETE must then carry the token in the same header, and the client must send the cookies back. If validation fails, the server answers 403 Forbidden and does not include a valid token. A token is only generated after authentication.

  1. AuthenticateBasic, certificate or OAuth, depending on the service configuration.
  2. Fetch tokenGET the service root or $metadata with X-CSRF-Token: Fetch; keep the token and cookies.
  3. ModifyPOST/PATCH/DELETE with X-CSRF-Token: token, the cookies and, for updates, If-Match.
  4. On 403Fetch a new token once and retry; if it fails again, fail the test with the response.
  5. AssertStatus code, then the business result: read the entity back and compare fields.
The CSRF-safe write pattern for SAP OData services.
The Sign-Off Table · thesignofftable.com/academy/sap-tau-203

Updates: ETags

Many SAP services use ETags for optimistic concurrency. When you read an entity, the response carries an ETag; when you update or delete it, you send that value in an If-Match header. SAP Gateway's documentation says that if an entity has an ETag and the client modifies it without If-Match, the server should fail the request with 412. Automate both cases: the happy update with the current ETag, and a stale-ETag update that must be rejected, which proves two users cannot silently overwrite each other.

An update must carry the current ETag; a test with a stale ETag proves the service rejects lost updates with 412.
The Sign-Off Table · thesignofftable.com/academy/sap-tau-203

Batches and errors

Fiori apps often bundle calls into $batch requests: a single multipart POST containing retrieve operations and change sets, where a change set is an atomic unit that succeeds or fails as a whole. If you replay a Fiori flow at the service level, test the batch too: a change set with one invalid item must not leave half an order behind. When a request fails, assert on the error, not just the status: the error payload carries a code and message text that should match the business rule you expected to fire. When a failure is unexplained, SAP Gateway's error log (/IWFND/ERROR_LOG on the hub, /IWBEP/ERROR_LOG in the back end) gives the context, and the SAP Gateway Client (/IWFND/GW_CLIENT) lets you replay the request, save test cases and see the response.

A $batch request can mix reads and change sets; each change set succeeds or fails as a whole, so one bad item must leave no half order.
The Sign-Off Table · thesignofftable.com/academy/sap-tau-203
  1. Did $metadata still contain the entity and fields?Yes → run data tests · No → fail fast: contract changed
  2. Did the write return 403?Yes → check token, cookies and session · No → continue
  3. Did the update return 412?Yes → expected only in the stale-ETag test · No → continue
  4. Is the business result right when read back?Yes → pass · No → defect with request, response and document number
Triage order for a failing OData test.
The Sign-Off Table · thesignofftable.com/academy/sap-tau-203

What would you do?

An automation engineer's POST to create a sales order in CMQ returns 403 Forbidden although the test user has all the roles. The GET with X-CSRF-Token: Fetch worked. What is the most likely fix?

Key points
  • Check $metadata first so contract changes fail fast and clearly.
  • Modifying requests need a CSRF token fetched with X-CSRF-Token: Fetch, plus the session cookies; failures return 403.
  • Send If-Match with the ETag for updates; test that a stale ETag is rejected.
  • Test $batch change sets for atomicity and assert on error payloads, not just status codes.
  • Use the Gateway Client and error log to replay and diagnose failures.

Check your understanding · not graded

Lesson check

  1. 1. How does a client obtain a CSRF token from an SAP Gateway OData service?

  2. 2. What does SAP Gateway return when a modifying request fails CSRF validation?

  3. 3. An update is sent without If-Match to an entity that uses ETags. What should the server do?

  4. 4. In an OData $batch request, what is a change set?