Un modulo di pagamento che funziona per una carta andata a buon fine non è testato: è dimostrato. I difetti costosi vivono negli stati attorno a quel successo: il pagamento rifiutato e ritentato due volte, il cliente che ha chiuso la finestra di autenticazione a metà, il rimborso emesso su un ordine mai incassato. Una checklist pratica per testare un modulo di pagamento è quindi un elenco di esiti da raggiungere, non un elenco di campi da compilare.
Quello che segue è la sequenza che trova più bug per ora di lavoro, con il ragionamento dietro ogni voce e le preoccupazioni orientate allo sviluppatore che decidono se le correzioni reggeranno.
Inizia dagli stati, non dai campi
La maggior parte dei team inizia testando gli input: un numero valido, un numero non valido, una data di scadenza mancante. Questo intercetta i problemi di interfaccia e vale la pena farlo, ma lascia intatta la metà più difficile del sistema.
L’approccio produttivo è enumerare gli stati in cui può trovarsi un ordine e confermare che ciascuno sia raggiungibile, visibile e corretto. Gli stati tipici includono in attesa di pagamento, autorizzato ma non incassato, incassato, rifiutato con l’opzione di ritentare, rifiutato in via definitiva, autenticazione in sospeso, autenticazione fallita, abbandonato a metà, rimborsato in tutto, rimborsato in parte e contestato. Scrivi prima il tuo elenco; le lacune in esso sono di solito dove si annidano i bug.
Una volta che l’elenco esiste, ogni voce diventa una domanda con una risposta testabile: come rende lo storico ordini del cliente questo stato, la vista di amministrazione è d’accordo e l’esportazione contabile lo tratta correttamente?
Come dovrebbe apparire il percorso di rifiuto?
Un rifiuto non è un unico evento. L’esperienza del cliente dipende dal fatto che il rifiuto sia recuperabile, e il gateway di solito ti dice quale categoria si applica.
Un rifiuto causato da fondi insufficienti è recuperabile: il cliente può usare un’altra carta, e il modulo dovrebbe conservare tutto ciò che ha già digitato, inclusi indirizzo e dati di contatto, così che il nuovo tentativo costi pochi secondi anziché una nuova immissione completa. Un rifiuto che significa che l’emittente vuole parlare con il titolare non è recuperabile attraverso la tua interfaccia, e dire all’utente di riprovare gli fa perdere tempo. Un errore di elaborazione sta nel mezzo: spesso è transitorio, e un nuovo tentativo è ragionevole.
Testa ciascuno di questi separatamente con una carta che produca l’esito specifico, e verifica tre cose per ognuno: il messaggio che il cliente vede, lo stato registrato nel tuo database e se il pulsante di retry venga persino offerto. Un modulo che offre un nuovo tentativo per un rifiuto definitivo genera ticket di assistenza, e uno che nasconde il nuovo tentativo per un errore transitorio perde vendite.
Hai testato il percorso di retry?
I nuovi tentativi sono dove emergono i fallimenti di idempotenza, e sono facili da trascurare perché un singolo tentativo funziona perfettamente.
Gli scenari che vale la pena eseguire sono: il cliente preme due volte di seguito il pulsante di pagamento; la rete cade dopo che la richiesta è stata inviata ma prima che arrivi la risposta; il cliente abbandona la pagina e ricomincia dal carrello; e il pagamento viene autenticato, fallisce all’incasso e viene poi ritentato con una carta diversa. In ogni caso, controlla che esista un solo ordine, che venga tentato un solo addebito e che lo stato mostrato al cliente corrisponda a ciò che ha registrato il gateway.
Il caso del doppio invio è il più comune e il più dannoso. Disabilitare il pulsante dopo la prima pressione non è sufficiente da solo, perché la seconda richiesta potrebbe essere già in volo. La correzione durevole è una chiave generata una volta per ogni tentativo di pagamento e onorata dalla chiamata di pagamento, così che una ripetizione dello stesso tentativo restituisca il risultato originale anziché crearne un secondo.
Rimborsi, storni e incassi parziali
Questi percorsi vengono spesso lasciati non testati finché un cliente non ne richiede uno, che è un brutto momento per scoprire una lacuna.
Testa un rimborso completo e conferma che lo stato dell’ordine cambi, che il cliente venga avvisato e che l’importo si riconcili. Poi testa un rimborso parziale e controlla che un successivo secondo rimborso non superi l’importo originale e che lo storico dell’ordine mostri la somma correttamente. Testa uno storno, che avviene quando un’autorizzazione viene rilasciata prima di qualsiasi incasso, e conferma che il cliente veda una cancellazione anziché un addebito.
Se il tuo flusso supporta l’incasso di un importo inferiore a quello autorizzato — comune nell’ospitalità, dove il conto finale differisce dalla pre-autorizzazione — testa che il rilascio della differenza sia visibile da qualche parte. Il bug in quest’area è quasi sempre contabile: il pagamento è riuscito, il cliente è soddisfatto e il rapporto sui ricavi è sbagliato per un mese.
La checklist
Raggruppata all’incirca nell’ordine in cui dovrebbe essere eseguita:
- Un pagamento riuscito con una carta correttamente formata di ogni rete che supporti.
- Un pagamento rifiutato per fondi insufficienti, ritentato con successo con una seconda carta.
- Un pagamento rifiutato in via definitiva, senza nuovo tentativo offerto e con una spiegazione chiara.
- Un errore di elaborazione transitorio, ritentato dopo un breve ritardo.
- Doppio invio del pulsante di pagamento, controllato per ordini duplicati.
- Una connessione caduta dopo l’invio, controllata per uno stato recuperabile anziché un orfano.
- Un pagamento abbandonato, con l’ordine lasciato in uno stato che un umano può spiegare.
- Autenticazione completata, autenticazione fallita e autenticazione abbandonata.
- Una carta oltre il suo mese di scadenza, inviata al confine, il primo e l’ultimo giorno di validità.
- Un codice di sicurezza di lunghezza errata per la rete rilevata.
- L’autofill, incluso il browser che compila una carta salvata e il cliente che modifica un campo.
- Un rimborso completo, un rimborso parziale e un secondo rimborso parziale dopo il primo.
- Una sessione che scade mentre il modulo è aperto, inviato comunque.
- Una connessione molto lenta, inviata due volte con la seconda che arriva prima che la prima si completi.
- Completamento dell’intero modulo con la sola tastiera, e una verifica con screen reader sui messaggi di errore.
È deliberatamente più lunga della maggior parte delle checklist di lancio, perché gli ultimi cinque elementi sono quelli che raggiungono i clienti quando vengono saltati, e nessuno di essi richiede infrastrutture insolite per essere testato.
Per gli sviluppatori: matrice degli stati e revisione dell’idempotenza
Due artefatti rendono tutto gestibile. Il primo è una matrice degli stati: righe per ogni stato raggiungibile, colonne per la vista del cliente, la vista di amministrazione, il record nel database e la notifica inviata. Le celle vuote sono i difetti. Compilarla richiede un pomeriggio e di solito rivela che due schermate discordano su cosa significhi un pagamento in sospeso.
Il secondo è una revisione dell’idempotenza dell’endpoint di pagamento stesso. Conferma che la richiesta porti una chiave unica per tentativo di pagamento anziché per tentativo a livello di rete, che la chiave sia memorizzata con la transazione e che una richiesta ripetuta con la stessa chiave restituisca l’esito originale anziché eseguire di nuovo il lavoro. Controlla anche il percorso di timeout: se il tuo client smette di attendere, il server potrebbe comunque completare l’addebito, e al cliente non deve essere mostrato un fallimento per un pagamento riuscito.
Accanto a questi, rivedi come il modulo gestisce i dati che non dovrebbe conservare. I numeri di carta che raggiungono i tuoi server necessitano di mascheramento in ogni visualizzazione, e i codici di sicurezza non devono essere scritti nei log affatto: la guida al codice di sicurezza spiega perché quella regola è assoluta anziché una preferenza. Le date di scadenza meritano i propri test di confine, descritti nella guida alla data di scadenza, perché l’ultimo giorno del mese stampato è un fallimento classico.
Infine, decidi cosa accade quando una chiamata al gateway fallisce in un modo che non avevi previsto. Un flusso di pagamento ha bisogno di una risposta definita per il caso sconosciuto, e dovrebbe essere una che non addebiti il cliente due volte né lasci l’ordine invisibile.
Dove procurarsi i numeri per la checklist
Le carte di questa checklist ricadono in due gruppi. I casi che richiedono un esito specifico del gateway — un rifiuto, una sfida di autenticazione — richiedono i numeri di test che il tuo fornitore di pagamenti documenta per la sua sandbox, e la guida alle carte di test dei fornitori spiega come funzionano quei cataloghi. Tutto il resto, incluso ogni caso in cui il passo di pagamento è simulato, può usare dati generati.
Il generatore di numeri di carta produce numeri per una rete scelta o un lotto misto, ciascuno con una data di scadenza e un codice di sicurezza segnaposto, così un insieme di fixture può essere assemblato in un minuto. Ogni valore è strutturalmente valido e non è mai stato emesso ad alcun conto, ed è questo che rende l’insieme sicuro da conservare nel repository e inutile per chiunque lo trovi.
Passi successivi
Prendi la checklist qui sopra, segna le voci che riesci già a dimostrare e quelle che non riesci, e tratta il secondo gruppo come un blocco al lancio anziché come una backlog. Poi compila la matrice degli stati per i due stati che capisci meno, dato che è lì che di solito si nascondono i disaccordi tra le schermate.