Practice · Acceptance testing5 min readReviewed

Testing agent purchases: Eight checks beyond the response

Stefan Hamann · English
Text

An agent announces: “Your order has been placed successfully.” It is a good moment in a demonstration. In an acceptance test, the real work starts here: Which order exists in the shop? Which payment belongs to it? Is stock correct? Can the same request be executed again after a connection failure?

A useful test checks these outcomes independently of the agent's response. The following acceptance matrix shows how to test an agent purchase systematically in a test environment.

Define a small purchase completely

Consider a fictional office supplies merchant. A test customer wants two cartons of a precisely identified label roll. The total allowed amount is €80, including shipping and tax. Delivery must go to the approved business address. Substitutions require fresh consent.

Before the test, the team records the item, variant, quantity, offer version and customer identity. It also defines when an order counts as accepted and which payment states fit that definition. Payment authorisation and actual capture are considered separately.

Use synthetic customer data, test stock and your payment provider's test mode. A real charge is neither needed for this acceptance test nor intended by this guide.

Set up three independent checks

The interface shows what the customer understands. The commerce core shows what was ordered and reserved. The payment system shows what was authorised or captured. These three views need to agree.

The team reads those states through administrative test access or defined inspection endpoints. The agent should not be the sole judge of its own success. A second language model reading the same friendly response does not replace an order check either.

The acceptance matrix

Each test starts from a known state that can be restored. For concurrency tests, the overlap in timing is an explicit part of the setup.

Case Deliberate change Expected system outcome
1. Normal purchase Confirm the unchanged offer. One matching order; amount, customer and variant agree with the approval.
2. Lost response Interrupt the connection after storage, then repeat the same request. Recover the existing transaction; no second order and no additional capture.
3. Changed payload Send the same retry identifier with a different quantity. Handle the conflict explicitly; do not silently overwrite it or execute it as an approved new purchase.
4. Expired offer Send approval after the offer has expired. Do not execute the old version; present new terms for a decision.
5. Last stock Two authorised customers order the last carton simultaneously. Where overselling is excluded, accept at most one order; give the second customer an accurate status.
6. Delayed event After confirmed payment success, deliver an older “processing” event. Do not let an outdated message blindly reset the confirmed payment state.
7. Revoked mandate Withdraw permission before the executing step. No new execution under the revoked mandate; steps already performed remain traceable.
8. Repeated refund Deliver the same approved test refund several times. One refund effect; retries refer to the same transaction.

These expectations need to fit the agreed business model. A merchant allowing backorders or partial deliveries needs a different acceptance rule for case 5. Record that rule before the test. An explanation afterwards cannot replace an expectation agreed in advance.

A timeout initially means the outcome is unresolved

The distinction between “declined” and “response missing” matters. After a timeout, the order may already exist. The next step should establish the state of the existing transaction before starting a new purchase.

The HTTP standard describes idempotency as repeated identical requests having the same intended effect. An arbitrary order submitted through an HTTP interface does not gain that property automatically. Automatic retries of nonidempotent methods require additional conditions. Check the behaviour of your specific integration. RFC 9110, section 9.2.2

Set a time limit for resolving the technical outcome. If it remains unresolved, assign the case to a responsible person with the references already available. The customer sees an accurate message: “We are checking your order status.” Count unresolved transactions as open, rather than successful or definitely declined. Report the unresolved rate alongside the success rate, both relative to all transactions started.

Save evidence another person can read

For each run, record the test case identifier, software revision, starting data, induced failure, expected state, observed state and relevant transaction references. Credentials and complete payment details do not belong in that record. Document who takes ownership of an unresolved case.

Repeat critical cases with different delays and event sequences. One successful run establishes the result of that run. Concurrency problems in particular need more than the usual click through a demo.

Assess safety boundaries separately from quality targets when deciding on release. A polished response cannot offset an unauthorised charge. Repeat the matrix after changes to offer logic, permissions and payment integration.

The next practical step: Have the business team and developers execute one test together and explain the stored state. The foundations are in Chapter 8: From the offer to the service that follows and Chapter 13: Security for agents that act.