Introduction
A payment platform is one of the most sensitive parts of any FinTech product — and it often includes complex UI interactions across roles (user, admin), devices (desktop, mobile), and features (invoices, approvals, transfers).
But automating these flows isn’t just about writing tests — it’s about keeping them stable and maintainable as the platform evolves.
In this article, you’ll learn how to build a reliable, scalable UI automation suite tailored for payment systems — without drowning in flaky tests or brittle selectors.
🚧 Why UI Automation Can Break Fast in FinTech
Common issues include:
- Changing UI components (new fields, dynamic elements)
- Complex DOM states (modals, step-based flows)
- Flaky selectors tied to dynamic data
- Interactions that rely on backend sync (status changes, FX updates)
- Role-based logic affecting element visibility
This makes it critical to architect tests with flexibility and separation of concerns.
🧱 Step-by-Step Guide to Building a Maintainable UI Automation Suite
✅ 1. Define a Stable Test Architecture
Organize your suite using a layered structure:
markdownКопіюватиРедагуватиtests/
│
├── payment/
│ ├── makePayment.test.ts
│ ├── refundPayment.test.ts
│
├── invoice/
│ ├── createInvoice.test.ts
│ └── editInvoice.test.ts
│
├── utils/
│ └── auth.ts
│
└── selectors/
└── paymentSelectors.ts
Use:
tests/
: actual feature flowsutils/
: login helpers, setup/teardown scriptsselectors/
: all element references in one place
➡ Helps reduce duplication and isolate selector breakage.
✅ 2. Use Data Attributes for Stable Selectors
Avoid brittle CSS or text selectors.
Use attributes like:
htmlКопіюватиРедагувати<button data-testid="submit-payment">Pay</button>
In your test:
jsКопіюватиРедагуватиcy.get('[data-testid="submit-payment"]').click();
Why it works:
- Immune to style/layout changes
- Not dependent on UI language or text copy
- Easier to track and update across versions
✅ 3. Build Reusable Test Helpers
Abstract repeated flows into shared functions:
jsКопіюватиРедагуватиfunction loginAs(role) {
cy.visit('/login');
cy.get('[data-testid="email"]').type(role === 'admin' ? 'admin@test.com' : 'user@test.com');
cy.get('[data-testid="password"]').type('securepass');
cy.get('[data-testid="login"]').click();
}
Use in tests:
jsКопіюватиРедагуватиbeforeEach(() => {
loginAs('admin');
});
➡ Keeps test logic focused on outcomes, not steps.
✅ 4. Mock Where It Makes Sense
Mock:
- Third-party API calls (KYC, payment processor)
- Webhooks or async events
- Backend failures (simulate 500, timeouts)
Don’t mock: actual UI flows like submitting a payment or creating an invoice. These are high risk and should stay real.
Use tools like MSW (Mock Service Worker) or built-in intercepts in Cypress/Playwright.
✅ 5. Automate the Right Flows First
Focus automation on:
- Happy paths for payments, refunds, approvals
- Permission checks (e.g., finance manager can approve; user can’t)
- Regression coverage for core features
Avoid automating:
- Rarely used UI pages
- Experimental or unstable features
- Pure layout validations
✅ 6. Run UI Tests in CI/CD — But Selectively
In CI, run:
- Fast smoke tests on pull requests
- Full regression only on staging merges or nightly
- Isolated test jobs per feature (payments, invoices, reports)
Tools: GitHub Actions, GitLab CI, CircleCI, Bitbucket Pipelines
✅ 7. Log Failures Clearly and Cleanly
Use:
- Screenshots on failure
- Video recordings (e.g., in Cypress)
- Custom error messages when assertions fail
This makes debugging faster — especially for async flows where the UI doesn’t immediately reflect backend changes.
🧠 Tips Specific to FinTech Payment UIs
- Test amount precision (e.g., 2 vs 3 decimals)
- Use multiple currencies during test data generation
- Validate transaction status post-submit (not just UI confirmation)
- Run tests with multiple roles (user, approver, admin)
- Verify conditional flows (e.g., scheduled vs instant payment)
Final Thoughts
A maintainable UI automation suite isn’t built by automating everything — it’s built by automating the right things the right way.
For FinTech payment platforms:
- Start with core flows
- Use data attributes and helpers
- Avoid flake with mocks and clean environments
- Structure your suite to scale
✅ UI Automation Folder Structure Template (for FinTech Payment Platforms)
You can use this across Cypress, Playwright, or any JS/TS-based UI automation framework.
bashКопіюватиРедагуватиui-automation/
├── cypress.config.ts
├── package.json
├── /tests
│ ├── /auth
│ │ └── login.test.ts
│ ├── /payment
│ │ ├── submitPayment.test.ts
│ │ ├── refundPayment.test.ts
│ │ └── recurringPayments.test.ts
│ ├── /invoice
│ │ ├── createInvoice.test.ts
│ │ └── downloadInvoice.test.ts
│ └── smoke.test.ts
│
├── /support
│ ├── commands.ts // Custom Cypress commands
│ └── setup.ts // before/after hooks
│
├── /utils
│ ├── auth.ts // Reusable login helper
│ └── dataGenerator.ts // Generate test users, invoices, etc.
│
├── /selectors
│ ├── login.ts
│ ├── payment.ts
│ └── invoice.ts
│
└── /fixtures
└── users.json // Test data & mock responses
🧪 Cypress Starter Repo for Payment Flows (core features included)
This starter includes:
cy.loginAs(role)
helper- Tests for:
- Payment submission
- Refund flow
- Payment approval/rejection
- Support for:
- Multiple user roles
- Test data injection
- Custom command creation (
cy.submitPayment()
etc.)
- Pre-configured:
cypress.config.ts
with base URL, video/screenshots enabled- GitHub Actions setup (CI-ready)
- Simple fixture-driven testing for payment forms