Coding

Come testare le interfacce web React nell'era moderna

Il testing web si sta evolvendo con nuovi strumenti che migliorano affidabilità, interazioni utente e accessibilità. Discutiamo una possibile strategia di testing moderna per le interfacce web, capace di prevenire efficacemente le regressioni dell'UI.

Vincenzo Guerrisi Vincenzo Guerrisi
9 maggio 2025 — 8 min

Circa un anno fa Chromatic ha introdotto una nuova funzionalità per Storybook , che consente agli sviluppatori di scrivere test per le interazioni e verificare come si comportano i componenti nelle loro storie (puoi leggere di più nel loro post ufficiale).

Essendo noi stessi utenti molto soddisfatti di Storybook, abbiamo monitorato i loro aggiornamenti, desiderosi di perfezionare la nostra strategia di testing del prodotto. Oggi quindi vorrei condividere alcuni spunti dalla nostra esperienza nel testing delle applicazioni web. Scomponiamo il tutto passo dopo passo.

La Testing Pyramid è ancora attuale?

Nessuna discussione sul testing sarebbe completa senza menzionare la ben nota Testing Pyramid.

__wf_reserved_inherit

Nel caso non la conoscessi, la Testing Pyramid è un modello che suggerisce come organizzare i test automatizzati: alla base ci sono molti test unitari che verificano le funzionalità atomiche del codice, come funzioni o componenti. Lo strato intermedio ha meno test di integrazione , che garantiscono che i componenti funzionino bene insieme. E infine, in cima, ci sono ancora meno test end-to-end (E2E) , più lenti, che verificano che l’intero sistema funzioni dall’inizio alla fine.

Ma questo modello funziona ancora nel mondo dello sviluppo web di oggi?

Se l’idea generale resta valida (dare priorità a test unitari rapidi e con ampia copertura e usare un numero ridotto di test di integrazione ed E2E, più lenti e complessi), i test unitari tradizionali di solito non riescono a verificare l’aspetto visivo di un componente quando viene renderizzato in un browser.

Unit test nel contesto delle interfacce web

Quindi, come dovrebbero essere i test unitari nel panorama dello sviluppo web moderno?

Con il crescente spostamento della logica di business sul server, per motivi di efficienza e sicurezza, le applicazioni frontend stanno diventando più “semplici”: questo significa che i test unitari tradizionali possono offrire un valore limitato. Se ha senso estrarre le logiche UI complesse (come macchine a stati intricate o hook di React) e testarle nel modo tradizionale verificando le relazioni input-output, come facciamo a garantire che questi calcoli producano il corretto output visivo?

Storicamente la tendenza è stata quella di aumentare la copertura del codice frontend introducendo strumenti di testing (come Jest + React Testing Library) che generano e verificano l’output HTML dei componenti, culminando nell’introduzione dei cosiddetti snapshot test , che verificano che l’HTML prodotto corrisponda a uno snapshot approvato in precedenza.

// A snapshot test implemented using Jest and react-test-renderer
import renderer from 'react-test-renderer';
import Link from '../Link';

it('renders correctly', () => {
  const tree = renderer
    .create(<Link page="http://www.facebook.com">Facebook</Link>)
    .toJSON();
  expect(tree).toMatchSnapshot();
});

Tuttavia questi strumenti presentano almeno due svantaggi rilevanti:

  1. Tendono a dipendere molto dalla struttura interna del componente, il che li rende fragili , perché qualsiasi modifica nell’implementazione, anche se visivamente irrilevante, fa fallire un test;
  2. Non testano realmente come il componente appare o si comporta in un ambiente di rendering reale, quindi tendono a produrre falsi positivi e a mancare le regressioni reali nell’aspetto visivo dell’interfaccia.

Quindi, cosa possiamo fare?

Il visual diffing in soccorso

Un approccio rapido e pratico per identificare le regressioni visive è il Visual Testing.

Consiste nel renderizzare un componente (o una porzione di UI) in un browser reale o simulato, catturare uno screenshot e confrontarlo visivamente con una baseline approvata in precedenza. Se le differenze superano una soglia stabilita il test fallisce, permettendo agli sviluppatori di ispezionare visivamente le modifiche.

Se già usi Storybook per mostrare i componenti, per esempio, puoi integrare facilmente Chromatic, un servizio online che distribuisce automaticamente Storybook, cattura screenshot di tutte le storie e segnala le differenze visive per la revisione.

__wf_reserved_inherit

Con questo metodo puoi individuare facilmente modifiche non intenzionali dell’UI nei componenti, con un setup minimo.

Combinato con un’architettura dei componenti ben strutturata che separa l’UI dal data fetching, questo metodo può estendersi oltre i componenti atomici fino a intere sezioni dell’applicazione in stati diversi.

Abbiamo trovato questo approccio incredibilmente semplice ma molto efficace. A differenza dei metodi di testing tradizionali, che richiedono la scrittura di scenari complessi, il Visual Testing può essere implementato quasi immediatamente , il che lo rende una soluzione pratica per i team che vogliono migliorare l’affidabilità dell’UI senza un overhead significativo.

Affidandosi solo a questo tipo di test, però, non si verifica come i componenti si comportano in risposta alle interazioni o agli eventi dell’utente. È qui che entra in gioco il nuovo Storybook Test.

Il nuovo Storybook Test

Come detto in precedenza, Storybook ha introdotto di recente strumenti di testing integrati, a complemento del visual testing di Chromatic.

Con questa estensione gli sviluppatori possono arricchire le proprie storie di Storybook con interazioni e asserzioni, aumentando la copertura dei test e validando non solo gli elementi statici dell’UI, ma anche gli effetti delle interazioni utente.

Esempio di story con asserzioni di test:

// Example of a Storybook test-integrated story
export const Default = () => <Button onClick={() => console.log('Clicked!')}>Click me</Button>;
Default.play = async ({ canvasElement }) => {
  const canvas = within(canvasElement);
  await userEvent.click(canvas.getByText('Click me'));
  expect(console.log).toHaveBeenCalledWith('Clicked!');
};

Questi cosiddetti Component Test sono un buon compromesso tra i test UI tradizionali e quelli E2E. Testano infatti un singolo componente in isolamento (come i test unitari tradizionali), ma lo fanno renderizzando i componenti in un ambiente browser reale, con interazioni reali, invece di basarsi su renderer Node simulati come nei test unitari tradizionali.

In questo modo garantiscono che stiamo testando non solo l’aspetto visivo, ma anche che il comportamento dei componenti sia conforme alle specifiche.

Test di accessibilità

Con le nuove normative europee sull’accessibilità , garantire che la tua web app rispetti gli standard di accessibilità è diventato più importante che mai.

Nessuno strumento automatizzato può sostituire completamente i test di accessibilità manuali, ma diversi strumenti possono fornire una solida valutazione iniziale e sono un’aggiunta ottima e semplice a qualsiasi pipeline di test.

L’add-on di testing di Storybook include ora la validazione automatica dell’accessibilità , che segnala i problemi all’interno dei componenti renderizzati. Ricorda però che l’accessibilità dipende anche da come i componenti sono assemblati in pagine complete: aspetti come l’ordine del focus , il flusso di navigazione e l’usabilità con gli screen reader.

Per una conformità completa all’accessibilità vanno considerati strumenti aggiuntivi come Axe, Lighthouse o test manuali di navigazione da tastiera. In un articolo precedente abbiamo esplorato varie soluzioni che possono aiutare a garantire che il tuo progetto rispetti gli standard di accessibilità. Trovi approfondimenti dettagliati e implementazioni pratiche qui.

Test E2E e UI con Playwright / Cypress

Nello sviluppo web, il testing E2E si costruisce sopra i test unitari e di integrazione simulando interazioni reali dell’utente in un browser reale (headless o meno), per garantire che l’applicazione si comporti come previsto dall’inizio alla fine.

I test E2E, soprattutto se scritti seguendo best practice come i Page Object o le asserzioni personalizzate , possono anche essere una preziosa risorsa di documentazione dei comportamenti attesi, grazie alla facilità con cui anche persone meno tecniche possono leggere e comprendere l’interazione testata e il comportamento previsto.

// Example of an E2E test in Playwright to test an invalid user login
test(`Given the user enters incorrect credentials,
      When they submit the form
      Then an error message should be displayed`, async () => {

  await loginForm.enterUsername('wrongUser');
  await loginForm.enterPassword('wrongPassword');

  await loginForm.submit();

  await loginForm.hasErrorMessage('Invalid username or password');
});

In un progetto recente abbiamo sperimentato la combinazione dei test E2E con il Behavior-Driven Development (BDD), per descrivere meglio interazioni utente e risultati attesi in un modo al tempo stesso strutturato e accessibile, migliorando ulteriormente chiarezza e manutenibilità dei test.

A differenza di strumenti più vecchi come Selenium o Puppeteer, i framework moderni come Playwright e Cypress migliorano l’affidabilità dei test E2E includendo meccanismi di retry integrati in ogni asserzione. Per esempio, testare elementi UI che appaiono dopo un’interazione dell’utente porta spesso a test instabili, a causa di ritardi nelle risposte del backend o di rendering lenti, e richiede di modificare i timeout per attendere che gli elementi compaiano. Playwright e Cypress risolvono il problema ritentando automaticamente le asserzioni finché gli elementi non sono presenti e interattivi (o finché non scade un timeout), migliorando notevolmente l’affidabilità dei test senza intaccarne la leggibilità.

Un’altra svolta è la capacità di ispezionare lo stato visivo dell’applicazione prima e dopo ogni passaggio di test , che rende il debug più semplice. A questo si aggiunge la possibilità di registrare lo schermo del browser durante l’esecuzione dei test, che permette agli sviluppatori di osservare il comportamento dell’applicazione in caso di errori visivi.

Sia Playwright sia Cypress supportano anche il visual testing basato su screenshot, che consente di implementare test di visual diffing sull’intera pagina.

Infine, grazie alla loro capacità di interagire con il browser, possono intercettare ogni richiesta HTTP effettuata dall’applicazione (quelle che tipicamente si osservano dal tab Network dei Chrome DevTools, per esempio) e fornirne una risposta simulata. Questo è molto utile se vogliamo integrare i test E2E, più lenti, con “UI test” più rapidi che verificano solo il comportamento dell’interfaccia, eliminando la latenza delle richieste sottostanti.

Gestire i dati di test nei test E2E

Un problema comune nei test E2E è la gestione dei dati recuperati da API e database di terze parti.

Se i test si basano su un ambiente di test già distribuito, può essere impossibile controllare le risposte delle API per scenari specifici, perché l’ambiente sarebbe configurato per puntare a servizi reali o simulati con dati precaricati. Questo significa che tutti i casi di test devono basarsi su risposte predefinite, rendendo difficile per i singoli test modificare dinamicamente il comportamento del servizio.

Una possibile soluzione che abbiamo trovato convincente è spostare il controllo dell’ambiente sotto test ai test stessi.

Se il test runner è responsabile dell’avvio dell’ambiente sotto test (direttamente o tramite strumenti come Testcontainers), i test possono anche avviare mock server aggiuntivi (per esempio un server Express.js) prima di far partire l’ambiente di test. L’ambiente può poi essere configurato tramite variabili d’ambiente per puntare a questi mock server invece che alle API esterne reali. Questo approccio permette ai test di controllare direttamente i mock server, modificando dinamicamente gli endpoint per restituire le risposte necessarie a ciascuno scenario. Il risultato è che l’esecuzione dei test diventa più flessibile, indipendente dalle dipendenze esterne e molto affidabile.

__wf_reserved_inherit

Il futuro del testing automatizzato: l’integrazione dell’AI

Il futuro dello sviluppo web è sempre più guidato dall’AI, e questo naturalmente sta influenzando anche il mondo del testing.

Cypress, per esempio, sta sviluppando diverse funzionalità AI da integrare nel suo prodotto, Cypress Studio. Queste funzionalità aiuteranno nella scrittura dei test individuando interazioni utente non testate e suggerendo asserzioni basate sull’osservazione del comportamento della pagina dopo le interazioni.

Stagehand si presenta come l’evoluzione di Playwright, permettendo ai tester di esprimere le interazioni con il browser tramite comandi in linguaggio naturale (ad esempio “clicca sul pulsante di ordine”).

Altri strumenti, come Mabl e Testim, usano il machine learning per adattare automaticamente i test ai cambiamenti dell’applicazione, riducendo l’instabilità causata da queste variazioni nel comportamento del prodotto. Applitools sta migliorando il visual diffing usando l’AI per capire se le differenze rilevate negli screenshot sono davvero rilevanti.

L’AI può anche ottimizzare i tempi di esecuzione dando priorità ai test più critici in base, per esempio, alle ultime modifiche al codice. Alcune piattaforme CI/CD stanno già sperimentando questi approcci per velocizzare le pipeline senza sacrificare la copertura.

Seguiremo da vicino gli sviluppi in questo campo per capire come l’AI cambierà il modo in cui verifichiamo le nostre applicazioni.

Considerazioni finali

Il mondo del testing delle interfacce web sta evolvendo rapidamente. Nuovi strumenti e metodologie stanno rendendo il testing delle applicazioni web più facile, più veloce e più affidabile.

Resta però una sfida dedicare tempo sufficiente a verificare correttamente il software implementato. Dalla nostra esperienza, troppo spesso i team saltano del tutto i test o dedicano troppo poco tempo alla validazione delle proprie interfacce.

Definire una strategia di testing snella ed efficace sin dalle prime fasi di un progetto è essenziale per non trascurare questo aspetto critico durante la delivery.

In questo contesto, strumenti nuovi come il Visual Testing, i framework E2E moderni e l’automazione basata sull’AI possono essere incredibilmente utili per snellire questa fase.

Cosa ne pensi del futuro del testing web? Hai già una strategia definita o hai iniziato a usare questi nuovi strumenti e metodi? Parliamone!

Vincenzo Guerrisi
Vincenzo Guerrisi AI Productivity Engineer and Tech Lead

Vincenzo joined Buildo in 2016 as a Fullstack Engineer, with a strong focus on Frontend technologies. He pays close attention to process improvement and team dynamics, working every day to foster effective collaboration and bring out the best in each team member.

NEWSLETTER

Ehi, c'è anche una Newslettero!
Sì, proprio con la o.

Ogni mese scegliamo articoli utili ma anche idee fresche e stimolanti. Proprio quello che vorremmo trovare noi in una newsletter!