World’s largest virtual agentic engineering & quality conference
Test cards, sandbox setup, 20+ checkout test cases, 3D Secure and PCI-DSS checks, plus how to debug flaky payment tests caused by API timeouts.

Bhawana
Author
Last Updated on: July 17, 2026
On This Page
Checkout is the least forgiving screen you ship. Every other page can degrade gracefully; this one either takes money correctly or it does not. That makes it the flow most worth testing thoroughly — and the one where a single untested decline path or a flaky assertion costs real revenue.
This guide covers the full picture: what a test payment is, the test card numbers and sandbox setup you need to run one, a checklist of 20+ checkout test cases, the types of testing a payment flow demands, and how to test 3D Secure and PCI-DSS compliance. The final section goes deep on a failure mode that catches experienced teams — checkout tests that fail intermittently because of mock API timeouts and element load race conditions.
Checkout testing verifies every step a shopper takes between the cart and the order confirmation: reviewing items, choosing guest or logged-in checkout, entering shipping and billing addresses, selecting a payment method, and receiving confirmation. Payment gateway testing is the subset that focuses on the money itself — whether the card is authorized, declined, or challenged, and whether your system records the outcome correctly.
A test payment is how you exercise this without real money. It is a transaction run against a gateway's sandbox using a published test card number rather than a real one. The full flow executes — authorization, confirmation, webhooks, receipt — but no funds move and no real card is touched. Every major provider gives you one: Stripe calls it test mode, Square calls it Sandbox, and Shopify ships a Bogus Gateway for the same purpose.
The distinction matters because the two halves fail differently. Checkout bugs tend to be visible — a broken address form, a total that does not update. Payment bugs hide in the paths nobody clicks by hand: the declined card, the expired card, the 3D Secure challenge, the webhook that arrives twice. Those are the ones that reach production.
Test cards are card numbers that only work in a gateway's sandbox. They pass the same validation checks as real cards — including the Luhn checksum — but the gateway recognizes them and returns a scripted outcome instead of contacting an issuer. Each number maps to a specific result, which is what makes decline and error paths testable at all.
The table below lists Stripe's most commonly used test cards. For all of them, supply any future expiration date, any CVV (three digits, or four for American Express), and any postal code unless you are deliberately testing address verification.
| Card number | Brand | Expected outcome |
|---|---|---|
| 4242 4242 4242 4242 | Visa | Successful authorization |
| 5555 5555 5555 4444 | Mastercard | Successful authorization |
| 3782 822463 10005 | American Express | Successful authorization (four-digit CVV) |
| 4000 0000 0000 0002 | Visa | Declined — generic decline |
| 4000 0000 0000 9995 | Visa | Declined — insufficient funds |
| 4000 0000 0000 3220 | Visa | Triggers a 3D Secure authentication challenge |
Two caveats worth internalizing. First, test cards are gateway-specific — a Stripe number will not produce a scripted decline on Square or Adyen, so always work from your own provider's published list. Second, these numbers only function in test mode; sending one to a live endpoint fails, which is a useful safety property in itself. Stripe's full matrix, including brand-specific and error-code-specific cards, is documented at docs.stripe.com/testing.
Note: Run your checkout flow against every browser and real device your shoppers use, on TestMu AI's cloud. Try it free!
Sandbox mode is a parallel environment that mirrors the live gateway's API surface while isolating it from real funds and real cards. Setting one up follows the same shape across providers:
sk_test_ and pk_test_. Keep them in environment variables so no build can accidentally point a test suite at live infrastructure.A sandbox is realistic but not identical to production. Sandboxes typically respond faster than live gateways, carry no real fraud rules, and never rate-limit you. That gap matters: a checkout that passes every sandbox test can still fail under live latency, which is exactly what the timing section later in this guide addresses.
When you need tighter control than a sandbox offers — forcing an exact 3-second delay, or a 502 on the third retry — mock the gateway API in your suite instead. That is a complementary tool rather than a replacement, and it is covered in detail below.
The checklist below covers the checkout paths that break most often, grouped by stage. Copy it into your test management tool as a starting suite and extend it with your own business rules.
| # | Stage | Test case |
|---|---|---|
| 1 | Cart review | Line items, quantities, and per-item prices match what was added to the cart. |
| 2 | Cart review | Updating quantity recalculates subtotal, tax, and total correctly. |
| 3 | Cart review | Removing the last item returns the shopper to an empty-cart state, not a broken checkout. |
| 4 | Cart review | A valid discount code applies and the total reflects it; an expired or invalid code is rejected with a clear message. |
| 5 | Cart review | An item that goes out of stock between cart and checkout is surfaced before payment is taken. |
| 6 | Guest vs. logged-in | Guest checkout completes end to end without forcing account creation. |
| 7 | Guest vs. logged-in | A logged-in shopper sees saved addresses and saved payment methods prefilled. |
| 8 | Guest vs. logged-in | Logging in mid-checkout preserves the cart rather than emptying it. |
| 9 | Guest vs. logged-in | A guest who later registers with the same email has the order associated correctly. |
| 10 | Address | Required address fields are enforced and inline validation messages are accurate. |
| 11 | Address | Invalid postal codes for the selected country are rejected. |
| 12 | Address | "Billing same as shipping" copies the address correctly and unchecking it clears the fields. |
| 13 | Address | Changing the shipping country updates available shipping methods, tax, and total. |
| 14 | Address | Addresses containing non-ASCII characters, apostrophes, or long street names are accepted and stored intact. |
| 15 | Payment | A successful card authorizes and advances to confirmation. |
| 16 | Payment | A declined card shows an actionable error and leaves the cart intact for a retry. |
| 17 | Payment | Expired date, invalid CVV, and malformed card number are each caught with a specific message. |
| 18 | Payment | A 3D Secure challenge completes and returns the shopper to confirmation; an abandoned challenge does not charge them. |
| 19 | Payment | Double-clicking "Pay now" produces exactly one charge. |
| 20 | Payment | Alternative methods in your stack — wallets, BNPL, stored cards — each complete and fail gracefully. |
| 21 | Confirmation | The confirmation page shows the correct order number, total, and delivery estimate. |
| 22 | Confirmation | The confirmation email or receipt is sent and its contents match the order. |
| 23 | Confirmation | The order reaches the backend with the correct status; the payment webhook is processed exactly once. |
| 24 | Confirmation | Refreshing or navigating back from confirmation does not resubmit the order. |
| 25 | Post-purchase | A full refund and a partial refund each process and reflect in the order record. |
| 26 | Post-purchase | A chargeback or dispute notification is ingested and updates the order state. |
| 27 | Interruption | Session timeout mid-checkout is handled without charging or losing the cart. |
| 28 | Interruption | Network loss between authorization and confirmation resolves to a single, correct final state. |
Cases 19, 23, and 28 deserve particular attention — they are concurrency problems dressed as functional tests, and they are the ones most likely to pass locally and fail in CI. Our library of ecommerce test cases expands the surrounding flows, and mobile checkout testing on real devices covers what changes on a handset.
A payment flow fails in more ways than a functional suite can catch. These are the testing types a production checkout needs, and what each one is actually looking for.
| Type | What it verifies | Representative checks |
|---|---|---|
| Functional testing | Transactions produce the right outcome and the right record. | Authorization, capture, decline handling, refunds, order state transitions. |
| Integration testing | Your system and the gateway agree, including asynchronously. | Webhook delivery and signature verification, idempotent callback handling, retry behavior, reconciliation. |
| Security testing | Card data is never exposed and the flow resists abuse. | TLS enforcement, tokenization, no PAN or CVV in logs, PCI-DSS scope, injection and tampering attempts on amount fields. |
| Performance testing | Checkout survives peak load without dropping or duplicating orders. | Flash-sale concurrency, gateway latency under load, queue depth, p95/p99 response times, timeout behavior. |
| API testing | The gateway contract holds at the request level. | Status codes, error payload shapes, schema conformance, authentication failures. |
| Compatibility testing | The flow works everywhere shoppers buy. | Browser and device matrix, wallet availability, autofill behavior, mobile keyboards. |
| Regression testing | Gateway or pricing changes do not break existing paths. | Re-run the core suite on every SDK upgrade, tax rule change, or new payment method. |
| Usability testing | Shoppers can actually complete the purchase. | Error message clarity, field labeling, form length, accessibility of the payment form. |
Integration and performance testing are where most teams under-invest. A functional suite that passes against a fast, obedient sandbox tells you very little about a gateway that is occasionally slow, occasionally down, and delivers webhooks out of order under load.
3D Secure is an authentication layer that lets a card issuer verify the shopper before authorizing a payment. 3DS2 is the current version, and it underpins Strong Customer Authentication (SCA) requirements in the EU and UK. It replaced the original protocol's clumsy full-page redirect with a risk-based flow.
That flow has two outcomes, and both need tests. In a frictionless flow, the issuer approves on the device and behavioral signals the merchant sends, and the shopper sees nothing at all. In a challenge flow, the issuer demands proof — an OTP, a banking-app confirmation, or a biometric — before authorizing. This is also the practical answer to whether a card is "2D or 3D": run it through a test transaction and watch for the challenge. A 3DS card returns a status such as requires_action and pushes the shopper into authentication; a 2D card authorizes immediately.
What to cover when testing 3DS:
On compliance: PCI-DSS governs how card data is handled, and the single most effective way to test against it is to confirm you never touch raw card data in the first place. If your checkout uses the gateway's hosted fields or SDK, the PAN and CVV go straight to the provider and never reach your servers, which keeps you in the narrowest possible compliance scope. Verify that with evidence, not assumption: assert that card numbers never appear in application logs, request bodies to your own backend, error reports, session recordings, or analytics payloads. Confirm TLS is enforced end to end, that only tokens are persisted, and that amount and currency cannot be tampered with client-side.
Treat those as automated assertions in your suite rather than a checklist someone signs off once a year — security testing covers the broader methodology.
Everything above assumes your tests fail for real reasons. Often they do not — they fail intermittently, pass on retry, and erode trust in the suite. In checkout flows the usual culprit is timing: an assertion that races ahead of an API response, or a mock timeout that pushes rendering past the wait window.
The rest of this guide walks the path from “test failed on payment checkout” to “the mock API timeout caused an element load race condition,” and then to a fix that holds.
Checkout tests are timing-sensitive by design: the UI binds to backend payment, cart, and fraud services; third-party scripts load asynchronously; and network latency varies. A race condition occurs when two or more operations act on shared state simultaneously, producing unpredictable results; a timeout occurs when a system fails to respond within a specified window. In payment end-to-end tests, these often intertwine, UI renders before API data arrives, or retries overlap with UI assertions.
What makes them hard is that the cause is usually concurrent requests and shared client storage rather than a logic error, so the code reads correctly and the failure only appears under a timing window you cannot see. Without control of timing and visibility into it, you are guessing.
Root cause analysis starts with evidence. Each failed run should automatically capture:
Aggregate these for every run in one place, so you can filter by build, test, and timestamp and drill into outliers. Artifacts scattered across CI logs, a screenshot bucket, and an APM tool are artifacts nobody correlates.
Artifact collection checklist:
| Artifact type | Purpose | Collection method |
|---|---|---|
| Test logs (runner + app console) | Rebuild sequence of actions, assertions, and errors | Enable verbose logging; pipe CI logs; capture browser console via driver |
| Screenshots / video | Verify UI state and timing of renders | Framework recorders (Playwright, Cypress); CI artifacts |
| Network HAR | Inspect endpoints, latency, errors, caching | Browser DevTools/Playwright HAR capture |
| Trace data (browser/APM) | Map spans across UI, API gateway, and services | Playwright Tracing, OpenTelemetry, APM exporters |
| Server/app logs | See server-side timeouts, retries, id collisions | Log aggregation in CI; link build ID to env logs |
For teams formalizing this discipline, see our overview of foundational software testing strategies.
A mock API is a simulated API you control during testing. It lets you inject delays, custom errors, and specific response patterns without touching production or staging systems, so you can reproduce timing bugs deterministically. Choose tooling that supports programmable delays and dynamic payloads (e.g., Mock Service Worker, Prism, Express.js stubs). To cover both typical and edge-case latency, simulate deterministic delays (fixed values) and probabilistic delays (randomized with distributions). Tools and gateways can model timeouts and jitter, including Gaussian distributions, to surface hidden races.
Static vs. dynamic mocks:
| Mock style | What it does | When to use | Trade-offs |
|---|---|---|---|
| Static (deterministic) | Fixed responses and delays (e.g., 1200 ms) | Reproducing a known timeout/race; stable CI | May miss variability-induced issues |
| Dynamic (programmatic) | Conditional logic, randomized delays, injected faults | Chaos/latency testing; edge cases; concurrency | More complex; track seeds for repeatability |
Tip: In TestMu AI, you can tag runs with the mock profile (e.g., “p95-latency” vs. “timeout-3s”) so insights correlate failures with the exact latency model used.
For teams building these latency mocks directly in their test framework, this guide to Playwright mock API testing covers page.route() interception with controlled delays, status-code injection, HAR-file mocking, and request blocking.
Instrumentation in QA means inserting diagnostic code and tools that record timing, ordering, and flow during execution. Add timestamped logs at UI boundaries (clicks, route changes, element renders) and at network edges (request dispatch, response arrival). With distributed tracing, you can follow a checkout request across the browser, API gateway, and payment provider to isolate slow legs and verify where contention appears. External performance monitors help validate whether the slowness is systemic or test-specific.
A simple flow map for checkout tests:
Correlating these timestamps with HAR and spans reveals whether the assertion raced ahead of the response, or whether a timeout pushed rendering past the test’s wait window.
Fixed waits pause for an arbitrary time regardless of app state (e.g., sleep(2000)). Condition-based waits poll for a concrete state change, an element appears, a request completes, or a route stabilizes, making tests resilient to variable latency.
Before vs. after:
| Approach | Example | Risk/Benefit |
|---|---|---|
| Fixed wait | sleep(2000) | Flaky: too short on slow CI; wastes time on fast paths |
| Wait for element | await page.waitForSelector('[data-test=confirmation]') | Stable: asserts on real UI state |
| Wait for network | | Stable: aligns assertions with API completion |
| Wait for load state | await page.waitForLoadState('networkidle') | Useful for SPA route changes |
Example (Playwright):
await page.click('[data-test=pay-now]');
await Promise.all([
page.waitForResponse(r => r.url().endsWith('/payments') && r.status() === 200),
page.waitForSelector('[data-test=spinner]', { state: 'detached' }),
]);
await page.waitForSelector('[data-test=confirmation]');
The gain is structural rather than incremental: the assertion is gated on the state transition it actually depends on, so it no longer cares whether the response took 200 ms or 2 seconds.
For a deeper look at the API used in the snippet above, this guide to Playwright waitForResponse covers predicate patterns for matching specific endpoints, the click-then-await ordering that prevents race conditions, and how to assert on response status and body to catch silent payment failures.
Beyond test hygiene, harden the system against concurrency. An idempotency key is a unique value sent with a request so repeated submissions have no additional effect, critical for safe retries in payment flows. Combine this with proven concurrency patterns such as optimistic or pessimistic locking, serialized queues for side-effecting work, and robust client retry logic with backoff and jitter. To catch timing issues early, run targeted chaos/latency tests and load scenarios with tools like k6 or Locust; this is especially valuable in payments where gateways and 3DS add unpredictable hops.
Side-by-side summary:
| Code strategies (runtime) | Test strategies (automation) |
|---|---|
| Idempotency keys on payment actions | Replace sleeps with condition-based waits |
| Optimistic/pessimistic locking around critical updates | Mock APIs with deterministic and probabilistic delays |
| Serialized queues for side-effectful tasks | Timestamped logs and cross-layer tracing |
| Retry with backoff + circuit breaking | Capture HAR + videos + traces on every run |
| Guardrails for duplicate submission UI | Synthetic scenarios for p95/p99 latency and timeouts |
For deeper coverage of eCommerce edge cases, explore our library of ecommerce test cases.
To stop these failures reaching shoppers in the first place, run the purchase flow on every browser with our guide to cross-browser testing of checkout and payment flows.
After you fix the issue, keep it fixed. Combine real-time API monitoring with synthetic checks and anomaly detection to spot recurring timeout patterns or rising flakiness before they reach shoppers. Practical alerting stacks pair service metrics (Prometheus, APM) with CI signals (test retry counts, failure hotspots) so owners are paged early.
Key observability metrics:
TestMu AI’s insights boards trend these metrics across builds and environments, utilizing explainable AI to surface which mocks, routes, or elements correlate most strongly with failures, so you can preemptively tune waits, mocks, or code paths.
Testing a checkout well is mostly about refusing to trust the happy path. A test card that authorizes on the first try proves very little; the coverage that protects revenue lives in the declines, the 3D Secure challenges, the double-clicks, the webhooks that arrive twice, and the shopper whose connection drops between authorization and confirmation.
Start with your gateway's sandbox and its published test cards, work through the checklist above until every decline path has an assertion behind it, and layer in the integration, security, and performance checks that a functional suite cannot reach. When those tests start failing intermittently — and on a flow this timing-sensitive they will — treat it as a diagnostic problem rather than a retry problem: capture artifacts on every run, correlate API timing with UI state, and replace fixed sleeps with condition-based waits.
A checkout suite you trust is what lets you ship pricing changes, new payment methods, and gateway upgrades without holding your breath.
Author
Bhawana is a Community Evangelist at TestMu AI with over 3 years of experience creating technically accurate, strategy-driven content in software testing. She has authored 50+ blogs on test automation, cross-browser testing, mobile testing, and real device testing. She also serves as Product Marketing Manager for Kane CLI, the command-line tool that runs browser automation from the terminal using natural-language flows in a real Chrome browser. Bhawana is certified in KaneAI, Selenium, Appium, Playwright, and Cypress, reflecting her hands-on knowledge of modern automation practices. On LinkedIn, she is followed by 6000+ QA engineers, testers, AI automation testers, and tech leaders.
Did you find this page helpful?
More Related Blogs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance