Skip to main content

Run an End-to-End Test Payment

Android only, for now

The automated payment test is implemented for Android only. iOS is not driven yet

  • the simulator has no way to be tapped from outside, so it needs a generated UI test target, and that is planned. Until it lands, the builder hands the payment back to you to run by hand on iOS rather than reporting a pass it did not earn.

Once your app is open, the builder takes over and makes a payment the way a customer would. It walks the app to the screen where a payment starts, taps the control that starts it, waits for the Nuvei checkout to appear, fills in the card details, and then reads the outcome directly from the app's own records. It does this once for each payment method you have added. This is the step that proves the whole chain works together: your app, the Nuvei SDK, your backend, and the gateway itself.

It works out the route first​

The builder does not guess its way around your app. Before any payment is driven, it reads your own source to find where your code calls the payment seam, works out which screen that is, and proposes the shortest way to reach it - a deep link or a directly launchable screen where one exists, otherwise the taps that walk there from the app's first screen.

  • The route is derived from your code, not from poking at the device. Anything it could not resolve comes back marked as low confidence, naming the step it is unsure about, so it can be corrected before it is used rather than failing halfway through a run.
  • Every step is exact. A route is made of a small fixed set of moves - launch a screen, follow a deep link, tap, scroll to, type, wait for, go back - and each one names its target exactly. Nothing is matched loosely, so a route that worked once behaves the same way on the next run.
  • One route per payment method. Your methods may sit on different screens, or on two buttons of the same screen. Each method gets its own route, so the Google Pay run only ever taps the wallet button and the card run only ever opens the card checkout.
  • The route is remembered. It is saved with your project, so later runs replay it without planning again. If you add a payment method afterwards, the saved route is marked out of date and the test refuses to run until the route has been worked out again against the new code - rather than driving the new method to the old button.
Compose apps get one small change

If your app is built with Jetpack Compose and does not publish its test tags, nothing outside the app can see its buttons by name, and no route can be planned at all. The builder turns that one setting on for you. It takes effect on the next build, so the app is rebuilt before testing.

What counts as a pass​

  • A declined payment counts as a success - Reaching any answer from the gateway, approved or declined, proves every link in the chain works: your backend answered, the session token was valid, the SDK started, and the wire held end to end. Only two things count as failures - the checkout never appeared, and the app crashed.

  • Card details are handled by the tool, never by the AI - The AI is never given a card number. The builder types the card itself, using Nuvei's published sandbox test cards, stored in a fixed list built into the tool. Only cards that approve are shipped: a decline would still pass, but a deliberately provoked one produces gateway responses that look exactly like a broken integration.

  • It reads your app's own card rules first - If you have chosen to block certain card brands, those brands are left out from the start rather than being tried and rejected, so the test reflects how your app is actually configured. If your rules happen to exclude every brand, it tells you that instead of running.

  • Screenshots are kept - Each run writes its screenshots to an artifacts folder, so a failure can be looked at afterwards instead of being re-run to be seen.

  • 3-D Secure is optional - A challenge card can be included on request. It only works if your app asks for an amount of 151 or more, which is what makes the gateway ask for a challenge in the sandbox.

When a payment fails​

If a payment does not go through, the AI is allowed one attempt to diagnose the problem, correct it, rebuild, and try again. If the second attempt also fails, it stops. It then reports both attempts and what it changed between them, so you can see exactly what was tried.

This limit is deliberate and enforced by the tool itself - it refuses a third attempt outright rather than relying on the AI to hold back. Repeated automatic retries tend to produce a long trail of changes and no clear answer. Stopping after one attempt keeps the result readable and leaves the decision with you. If you want it to keep going, you can tell it to continue, and only then is another attempt allowed.

The AI is also not allowed to step in and drive the app by hand when the test fails. Tapping through the payment itself would produce a passing-looking result that proves nothing about your code, so a failed run stays failed until the cause is fixed.

Real devices​

Testing runs on an emulator by default. A real device has to be allowed explicitly, because a payment there can move real money. If both an emulator and a real device are available, you choose which one to test on before the testing process begins.

Google Pay​

Google Pay is the one payment method that cannot be tested on an emulator, because an emulator has no Google Wallet and no card in it, so there is nothing to pay with. On an emulator it is reported as skipped, with a clear explanation and what to do instead: connect a real device and run the test again.

Before Google Pay is tested, the builder stops and asks you to confirm that you have access to a real device with a Google account signed in and a card in its wallet. It also tells you to make sure it is a test card, not a real one - a Google Pay run can move real money. For that reason, the builder asks you directly, on every run. Your answer is never assumed and never remembered from last time, and the AI is not permitted to answer on your behalf. There are three answers: drive the payment, or just install and launch so you can test it by hand, or stop because no device is ready. If you answer that no device is ready, the test continues without Google Pay, and every other payment method is still tested as normal.

On a real device, the final step is yours. Google Pay asks for a fingerprint or PIN before it will approve a payment. That is Google's own security check, and nothing can complete it on your behalf. The builder handles everything leading up to it, then hands the last step to you.

When you test on a real device, the builder runs every other payment method first and leaves your app open on the phone. Google Pay is deliberately left until last, so by the time you are asked to do anything, everything else is already confirmed working. You are then told clearly what remains: tap the Google Pay screen by hand.

The tools behind this​

ToolWhat it does
plan_payment_route (read-only)Reads your source to find where a payment starts, and proposes the exact steps that reach that screen - one route per payment method. Its one change to your project is turning on Compose test tags when they are missing, because nothing can be planned without them.
run_payment_testDrives the payment: replays the route, taps the control that starts a payment, fills the checkout with a sandbox test card, and reads the gateway's answer out of the app's own log. Reports a verdict for each payment method, and where the screenshots were written.

See Tools for the rest of them.