{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["sub-heading","admonition"]},"type":"markdown"},"seo":{"title":"Testing","description":"Transform your commerce with PXP's unified platform—seamless payments, real-time insights, and global growth in one powerful integration.","lang":"en-UK","siteUrl":"https://developer.pxp.io","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"testing","__idx":0},"children":["Testing"]},{"$$mdtype":"Tag","name":"SubHeading","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Test your Drop-in integration in sandbox before going live."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"overview","__idx":1},"children":["Overview"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Test your Drop-in integration in the sandbox environment before accepting real payments. The sandbox environment allows you to test all payment methods without processing actual transactions."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"use-the-test-environment","__idx":2},"children":["Use the test environment"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Set the environment to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Test"]}," when initialising Drop-in:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"CheckoutDropInConfig(\n    environment = Environment.TEST,  // Use sandbox\n    // ... rest of config\n)\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Key points about sandbox testing:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["No real money is charged."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Use test card numbers and sandbox accounts."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["All payment methods work the same as production."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Backend verification still required using test API credentials."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"test-card-payments","__idx":3},"children":["Test card payments"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"test-card-numbers","__idx":4},"children":["Test card numbers"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use these test cards in sandbox to simulate different scenarios:"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"successful-payments","__idx":5},"children":["Successful payments"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following test cards represent successful payment scenarios:"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Card number"},"children":["Card number"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Network"},"children":["Network"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"3DS behaviour"},"children":["3DS behaviour"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["4111 1111 1111 1111"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Visa"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["No challenge"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["5555 5555 5555 4444"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Mastercard"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["No challenge"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["3782 822463 10005"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["American Express"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["No challenge"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["4000 0000 0000 0002"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Visa"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Challenge required"]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For all test cards:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Expiry date:"]}," Any future date (e.g., ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["12/25"]},")."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["CVV:"]}," Any 3 digits (e.g., ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["123"]},")."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Cardholder name:"]}," Any name."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"failed-payments","__idx":6},"children":["Failed payments"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following test cards simulate payment failures:"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Card number"},"children":["Card number"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Network"},"children":["Network"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Result"},"children":["Result"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["4000 0000 0000 0077"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Visa"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Insufficient funds"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["4000 0000 0000 0051"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Visa"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Card declined"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["4000 0000 0000 0069"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Visa"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Expired card"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["4000 0000 0000 0101"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Visa"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["CVV failure"]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"testing-3ds-authentication","__idx":7},"children":["Testing 3DS authentication"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When using the challenge test card (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["4000 0000 0000 0002"]},"), a 3D Secure authentication screen appears in the native Android UI:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["To pass:"]}," enter any code (e.g., ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["1234"]},")."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["To fail:"]}," leave empty or enter wrong code multiple times."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["To timeout:"]}," wait for authentication to timeout."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Verify that your ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onSuccess"]}," callback fires after successful authentication, and that your backend receives the transaction details."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"test-paypal","__idx":8},"children":["Test PayPal"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"paypal-sandbox-accounts","__idx":9},"children":["PayPal sandbox accounts"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You need a PayPal sandbox account for testing. Create one in the ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://developer.paypal.com/dashboard/","target":"_blank"},"children":["PayPal Developer Dashboard"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Create a personal (buyer) account for testing customer payments."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"test-paypal-payments","__idx":10},"children":["Test PayPal payments"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Tap the PayPal button in the drop-in."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Log in with your PayPal sandbox account in the web view."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Approve the payment."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify that ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onSuccess"]}," fires with transaction details."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify your backend receives the payment notification."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Test both transaction intents:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Purchase intent:"]}," Funds captured immediately."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Authorisation intent:"]}," Funds authorised but not captured (capture later via backend API)."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"test-google-pay","__idx":11},"children":["Test Google Pay"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"pre-requisites","__idx":12},"children":["Pre-requisites"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Android 7.0 (API level 24) or higher"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Google Play Services installed"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Google Account signed in"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Test card added to Google Wallet"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"test-google-pay-payments","__idx":13},"children":["Test Google Pay payments"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Open your app on an Android device or emulator."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Sign in to your Google Account."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Add a test card to Google Wallet (use test card numbers from above)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Tap the Google Pay button in Drop-in."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Select your test card in the payment sheet."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Tap ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Pay"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify that ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onSuccess"]}," fires with transaction details."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The Google Pay button only appears when the user has cards in their Google Wallet and Google Play Services is available."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"testing-on-emulator","__idx":14},"children":["Testing on emulator"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To test Google Pay on an Android emulator:"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Use an emulator with Google Play (API level 24+)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Sign in with a Google Account."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Open Google Wallet and add test cards manually."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Run your app and test Google Pay integration."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"test-error-handling","__idx":15},"children":["Test error handling"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Test that your error handling works correctly by simulating failures:"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"card-errors","__idx":16},"children":["Card errors"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use the failed payment test cards to trigger different error types:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Insufficient funds: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["4000 0000 0000 0077"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Card declined: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["4000 0000 0000 0051"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Expired card: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["4000 0000 0000 0069"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["CVV failure: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["4000 0000 0000 0101"]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Verify that your ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onError"]}," callback receives the error and displays an appropriate message to the customer."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"network-errors","__idx":17},"children":["Network errors"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Test that your error handling works correctly for network failures:"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"manual-testing","__idx":18},"children":["Manual testing"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Enable airplane mode on your device."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Try to submit a payment."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify that your ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onError"]}," callback receives the error."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify your error handling shows an appropriate network error message."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"automated-testing","__idx":19},"children":["Automated testing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Verify that your error callback handles network failures correctly:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"class NetworkErrorTest {\n    @Test\n    fun testNetworkErrorHandling() {\n        var errorReceived: BaseSdkException? = null\n        \n        val config = CheckoutDropInConfig(\n            environment = Environment.TEST,\n            session = mockSessionData(),\n            ownerType = \"MerchantGroup\",\n            ownerId = \"MERCHANT-1\",\n            transactionData = mockTransactionData(),\n            onError = { error ->\n                errorReceived = error\n            }\n        )\n        \n        // Simulate network error (SDK error code SDK0500)\n        config.onError?.invoke(mockNetworkError())\n        \n        // Verify error was received and has correct code\n        assertNotNull(errorReceived)\n        assertEquals(\"SDK0500\", errorReceived?.errorCode)\n        assertTrue(errorReceived?.message?.contains(\"network\", ignoreCase = true) == true)\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"user-cancellation","__idx":20},"children":["User cancellation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Test cancellation handling:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Card (3DS):"]}," close the 3D Secure authentication window without completing authentication."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["PayPal:"]}," close the web view without completing payment."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Google Pay:"]}," tap outside the payment sheet or press Back."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Verify that your ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onCancel"]}," callback fires (if configured in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["methodConfig.global"]},")."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"test-backend-verification","__idx":21},"children":["Test backend verification"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Always verify payments on your backend before fulfilling orders. The frontend callbacks can be manipulated by users."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"essential-backend-tests","__idx":22},"children":["Essential backend tests"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Test these critical security checks:"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Transaction exists:"]}," query the PXP API with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["systemTransactionId"]}," to verify the transaction exists."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Amount matches:"]}," verify the transaction amount matches your expected amount."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Transaction succeeded:"]}," check that the transaction state is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Authorised"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Captured"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Prevent replay attacks:"]}," ensure the same transaction can't be processed twice."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Example verification:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"// Backend verification endpoint (Node.js/Express example)\napp.post('/api/verify-payment', async (req, res) => {\n  const { systemTransactionId, merchantTransactionId } = req.body;\n  \n  // Get expected amount from your database\n  const order = await db.orders.findOne({ merchantTransactionId });\n  const expectedAmount = order.amount;\n  \n  // Query PXP API to verify transaction\n  const transaction = await unityApi.getTransaction(systemTransactionId);\n  \n  // Verify transaction is successful\n  if (transaction.state !== 'Authorised' && transaction.state !== 'Captured') {\n    return res.json({ success: false, error: 'Transaction not authorised' });\n  }\n  \n  // Verify amount matches\n  const txnAmount = transaction.amounts?.transactionValue || transaction.amount;\n  if (Math.abs(txnAmount - expectedAmount) > 0.01) {\n    return res.json({ success: false, error: 'Amount mismatch' });\n  }\n  \n  // Check for duplicate processing\n  const alreadyProcessed = await db.transactions.findOne({ systemTransactionId });\n  if (alreadyProcessed) {\n    return res.json({ success: true, orderId: alreadyProcessed.orderId });\n  }\n  \n  // Process order\n  const orderId = await fulfillOrder(order);\n  await db.transactions.create({ systemTransactionId, orderId });\n  \n  res.json({ success: true, orderId });\n});\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"test-on-physical-devices","__idx":23},"children":["Test on physical devices"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Test on real Android devices to ensure the best user experience."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"recommended-test-devices","__idx":24},"children":["Recommended test devices"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Test on devices that represent your user base:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Budget device:"]}," Samsung Galaxy A series, Motorola Moto G"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Mid-range device:"]}," Google Pixel 6a, Samsung Galaxy S22"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Premium device:"]}," Google Pixel 8, Samsung Galaxy S24"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Tablet:"]}," Samsung Galaxy Tab S9"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"device-specific-testing","__idx":25},"children":["Device-specific testing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Test the following on each device:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Card field rendering and keyboard input"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["3D Secure authentication UI"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Google Pay integration (if available)"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["PayPal web view interaction"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Screen rotation handling"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Different screen sizes and densities"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Performance and responsiveness"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"screen-size-testing","__idx":26},"children":["Screen size testing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Test your UI layout on different screen sizes using Compose previews:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"// Preview different screen sizes for layout inspection\n@Preview(name = \"Phone\", device = Devices.PHONE)\n@Preview(name = \"Foldable\", device = Devices.FOLDABLE)\n@Preview(name = \"Tablet\", device = Devices.TABLET)\n@Composable\nfun CheckoutScreenPreview() {\n    CheckoutScreen()\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Compose ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@Preview"]}," is useful for visual layout inspection during development, but it does not test runtime payment behaviour. Always run actual functional tests on emulators or physical devices to validate payment flows."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"automated-testing-1","__idx":27},"children":["Automated testing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Write automated tests for your Drop-in integration:"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"unit-tests","__idx":28},"children":["Unit tests"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Test your configuration and callback logic:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"import com.pxp.checkout.checkoutdropin.types.CheckoutDropInConfig\nimport com.pxp.checkout.models.DropInTransactionData\nimport com.pxp.checkout.models.DropInTransactionIntentData\nimport com.pxp.checkout.models.Environment\nimport com.pxp.checkout.models.EntryType\nimport com.pxp.checkout.models.IntentType\nimport org.junit.Test\nimport org.junit.Assert.*\n\nclass CheckoutConfigTest {\n    @Test\n    fun testConfigCreation() {\n        val config = CheckoutDropInConfig(\n            environment = Environment.TEST,\n            session = mockSessionData(),\n            ownerType = \"MerchantGroup\",\n            ownerId = \"MERCHANT-1\",\n            transactionData = DropInTransactionData(\n                currency = \"GBP\",\n                amount = 99.99,\n                entryType = EntryType.Ecom,\n                intent = DropInTransactionIntentData(\n                    card = IntentType.Authorisation\n                ),\n                merchant = \"Demo Store\",\n                merchantTransactionId = \"test-txn-123\",\n                merchantTransactionDate = { \"2026-05-18T12:00:00Z\" }\n            )\n        )\n        \n        assertEquals(Environment.TEST, config.environment)\n        assertEquals(\"MERCHANT-1\", config.ownerId)\n        assertEquals(\"GBP\", config.transactionData.currency)\n    }\n    \n    @Test\n    fun testCallbackExecution() {\n        var successCalled = false\n        var errorCalled = false\n        \n        val config = CheckoutDropInConfig(\n            environment = Environment.TEST,\n            session = mockSessionData(),\n            ownerType = \"MerchantGroup\",\n            ownerId = \"MERCHANT-1\",\n            transactionData = DropInTransactionData(\n                currency = \"GBP\",\n                amount = 99.99,\n                entryType = EntryType.Ecom,\n                intent = DropInTransactionIntentData(\n                    card = IntentType.Authorisation\n                ),\n                merchant = \"Demo Store\",\n                merchantTransactionId = \"test-txn-123\",\n                merchantTransactionDate = { \"2026-05-18T12:00:00Z\" }\n            ),\n            onSuccess = { result ->\n                successCalled = true\n            },\n            onError = { error ->\n                errorCalled = true\n            }\n        )\n        \n        // Test callbacks\n        config.onSuccess?.invoke(mockSuccessResult())\n        assertTrue(successCalled)\n        assertFalse(errorCalled)\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"integration-tests","__idx":29},"children":["Integration tests"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Test the full payment flow:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"kotlin","header":{"controls":{"copy":{}}},"source":"import androidx.compose.ui.test.*\nimport androidx.compose.ui.test.junit4.createComposeRule\nimport org.junit.Rule\nimport org.junit.Test\n\nclass CheckoutFlowTest {\n    @get:Rule\n    val composeTestRule = createComposeRule()\n    \n    @Test\n    fun testCardPaymentFlow() {\n        composeTestRule.setContent {\n            CheckoutScreen()\n        }\n        \n        // Wait for Drop-in to render\n        composeTestRule.waitForIdle()\n        \n        // Verify payment methods are displayed\n        composeTestRule.onNodeWithText(\"Card\").assertIsDisplayed()\n        composeTestRule.onNodeWithText(\"PayPal\").assertIsDisplayed()\n        \n        // Select card payment\n        composeTestRule.onNodeWithText(\"Card\").performClick()\n        \n        // Verify card form is displayed\n        composeTestRule.onNodeWithText(\"Card number\").assertIsDisplayed()\n        composeTestRule.onNodeWithText(\"Expiry date\").assertIsDisplayed()\n        composeTestRule.onNodeWithText(\"CVV\").assertIsDisplayed()\n    }\n    \n    @Test\n    fun testPaymentSubmission() {\n        composeTestRule.setContent {\n            CheckoutScreen()\n        }\n        \n        // Wait for Drop-in to render\n        composeTestRule.waitForIdle()\n        \n        // Fill card details and submit\n        composeTestRule.onNodeWithText(\"Card\").performClick()\n        composeTestRule.onNodeWithText(\"Card number\").performTextInput(\"4111111111111111\")\n        composeTestRule.onNodeWithText(\"Expiry date\").performTextInput(\"12/25\")\n        composeTestRule.onNodeWithText(\"CVV\").performTextInput(\"123\")\n        composeTestRule.onNodeWithText(\"Pay\").performClick()\n        \n        // Verify payment submission\n        composeTestRule.waitForIdle()\n    }\n}\n","lang":"kotlin"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"pre-production-checklist","__idx":30},"children":["Pre-production checklist"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Before going live, verify the following:"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"configuration","__idx":31},"children":["Configuration"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Change environment to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Environment.LIVE"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Use production API credentials."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify correct ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ownerId"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ownerType"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Confirm currency and amount formatting."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"testing-1","__idx":32},"children":["Testing"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Test all enabled payment methods."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Test successful payments."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Test failed payments and error handling."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Test user cancellation scenarios."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify backend verification works correctly."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Test on physical devices (not just emulators)."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"security","__idx":33},"children":["Security"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Backend verification implemented."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Replay attack prevention in place."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["HTTPS enabled on all backend endpoints."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["No sensitive data logged."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["ProGuard/R8 obfuscation enabled for production builds."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"user-experience","__idx":34},"children":["User experience"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Test on different screen sizes and orientations."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Loading states display correctly."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Success screen implemented."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Error messages are user-friendly."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Accessibility features tested (TalkBack, large text)."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"performance","__idx":35},"children":["Performance"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["App startup time is acceptable."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Payment submission is responsive."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["No memory leaks detected."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Network timeouts configured appropriately."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"code-quality","__idx":36},"children":["Code quality"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Lint checks pass."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Unit tests pass."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Integration tests pass."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Code review completed."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Documentation updated."]}]}]},"headings":[{"value":"Testing","id":"testing","depth":1},{"value":"Overview","id":"overview","depth":2},{"value":"Use the test environment","id":"use-the-test-environment","depth":2},{"value":"Test card payments","id":"test-card-payments","depth":2},{"value":"Test card numbers","id":"test-card-numbers","depth":3},{"value":"Successful payments","id":"successful-payments","depth":4},{"value":"Failed payments","id":"failed-payments","depth":4},{"value":"Testing 3DS authentication","id":"testing-3ds-authentication","depth":3},{"value":"Test PayPal","id":"test-paypal","depth":2},{"value":"PayPal sandbox accounts","id":"paypal-sandbox-accounts","depth":3},{"value":"Test PayPal payments","id":"test-paypal-payments","depth":3},{"value":"Test Google Pay","id":"test-google-pay","depth":2},{"value":"Pre-requisites","id":"pre-requisites","depth":3},{"value":"Test Google Pay payments","id":"test-google-pay-payments","depth":3},{"value":"Testing on emulator","id":"testing-on-emulator","depth":3},{"value":"Test error handling","id":"test-error-handling","depth":2},{"value":"Card errors","id":"card-errors","depth":3},{"value":"Network errors","id":"network-errors","depth":3},{"value":"Manual testing","id":"manual-testing","depth":4},{"value":"Automated testing","id":"automated-testing","depth":4},{"value":"User cancellation","id":"user-cancellation","depth":3},{"value":"Test backend verification","id":"test-backend-verification","depth":2},{"value":"Essential backend tests","id":"essential-backend-tests","depth":3},{"value":"Test on physical devices","id":"test-on-physical-devices","depth":2},{"value":"Recommended test devices","id":"recommended-test-devices","depth":3},{"value":"Device-specific testing","id":"device-specific-testing","depth":3},{"value":"Screen size testing","id":"screen-size-testing","depth":3},{"value":"Automated testing","id":"automated-testing-1","depth":2},{"value":"Unit tests","id":"unit-tests","depth":3},{"value":"Integration tests","id":"integration-tests","depth":3},{"value":"Pre-production checklist","id":"pre-production-checklist","depth":2},{"value":"Configuration","id":"configuration","depth":3},{"value":"Testing","id":"testing-1","depth":3},{"value":"Security","id":"security","depth":3},{"value":"User experience","id":"user-experience","depth":3},{"value":"Performance","id":"performance","depth":3},{"value":"Code quality","id":"code-quality","depth":3}],"frontmatter":{"seo":{"title":"Testing"}},"lastModified":"2026-05-22T10:08:35.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/checkout/drop-in/android/testing","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}