Bug visivi che i test automatici non colgono: testare ciò che vede l'utente

Bug visivi che i vostri test automatici non colgono: perché toBeVisible() e isDisplayed() accettano elementi coperti o illeggibili, e come testare ciò che vede l'utente.

10 min di letturaDal team di GUI Test Studio

Cosa sono i bug visivi?

I vostri test end-to-end sono verdi.Poi un cliente invia uno screenshot della pagina di pagamento: il totale dell'ordine è nascosto dietro un banner promozionale.Ogni test automatico è stato superato, perché ogni test automatico ha interrogato il codice della pagina, non lo schermo.Il test visivo serve proprio per bug visivi come questo: controlla ciò che i vostri utenti vedono davvero.

Un bug visivo è un difetto che le persone vedono sullo schermo mentre il codice che c'è dietro sembra a posto.L'elemento esiste, ha una dimensione, contiene il testo giusto.Un controllo del codice viene superato.La persona davanti allo schermo non riesce a leggerlo, a trovarlo o a premerlo.

Questo articolo mostra da dove nasce il divario, quali bug ci cadono dentro, e come costruire test end-to-end che vedono lo schermo come lo vedono i vostri utenti.

Il vostro utente chiede

  • Riesco a vederlo?
  • Riesco a leggerlo?
  • È dove dovrebbe essere?
  • Ha lo stesso aspetto di ieri?

Un controllo del codice chiede

  • L'elemento è nella pagina?
  • Ha una dimensione?
  • Il suo stile lo nasconde?
  • Contiene il testo giusto?

Cosa significa “visibile” per Playwright, Cypress e Selenium

Un test end-to-end in codice trova un elemento tramite un selettore e verifica qualcosa su di esso.L'asserzione più vicina a ciò che vive un utente è “è visibile?”.Ogni strumento risponde a modo suo, e nessuno di essi guarda lo schermo.

Playwright

toBeVisible() di Playwright dà esito positivo quando l'elemento ha un riquadro di delimitazione non vuoto e nessuno stile visibility: hidden.La sua documentazione aggiunge che un elemento con opacity: 0 conta come visibile.Non chiede se un altro elemento copre l'elemento, né di che colore è il suo testo.

Le azioni sono più severe delle asserzioni.Prima di un clic, Playwright controlla che nel punto del clic sia proprio l'elemento a ricevere l'evento, quindi un pulsante coperto fa attendere il clic fino allo scadere del tempo massimo.Playwright offre anche toBeInViewport() per un elemento che deve trovarsi all'interno del viewport, e toHaveText() legge per impostazione predefinita il textContent dell'elemento.

Cypress

Da Cypress 16, il controllo di visibilità predefinito si affida al metodo Element.checkVisibility() del browser stesso.Un elemento conta come nascosto quando non ha larghezza o altezza, quando ha display: none, visibility: hidden o, per un'asserzione, opacity: 0.Prima di un clic, Cypress controlla che il centro dell'elemento non sia coperto.

Un'asserzione è un'altra cosa.La documentazione di Cypress lo dice chiaramente: “L'algoritmo moderno non esegue l'hit test, quindi segnala come visibile l'elemento coperto”.

Selenium

Come dice la documentazione di Selenium, isDisplayed() non è definito dalla specifica W3C WebDriver per “l'impossibilità di coprire tutte le condizioni potenziali”.Selenium esegue invece una grande funzione JavaScript, che valuta lo stile dell'elemento, la sua dimensione e gli antenati che lo ritagliano.Non controlla se un altro elemento ci viene disegnato sopra, né se il suo testo si può leggere sul suo sfondo.

Un clic su un elemento coperto fallisce con un errore “element click intercepted”.Un elemento che il test si limita a leggere viene comunque segnalato come visualizzato.

9 bug visivi che superano un controllo in codice

Ognuno di questi bug lascia l'elemento nel codice della pagina, con una dimensione e il testo giusto.Un test in codice che verifica che l'elemento esista, sia visibile o contenga il suo testo viene superato.Il vostro utente vede altro.

1. Un elemento coperto da un altro

Un banner dei cookie, un widget di chat, un'intestazione fissa o una finestra di dialogo mai chiusa si trova sopra l'elemento, spesso dopo una modifica dello z-index.L'elemento resta visibile secondo tutte le definizioni viste sopra.Un clic su di esso viene rifiutato, ma un test che si limita a leggerlo, come un prezzo, un messaggio di errore o una conferma, viene superato mentre nessuno riesce a vederlo.

2. Un testo che nessuno riesce a leggere

Testo bianco su sfondo bianco, grigio su grigio dopo un cambio di tema, o un'etichetta rimasta trasparente per colpa di un'animazione difettosa.Nessun controllo di visibilità legge un colore.toBeVisible() di Playwright dà esito positivo anche con opacity: 0.

3. Un testo tagliato

Un'etichetta troppo lunga per il suo riquadro finisce con i puntini di sospensione, o un'altezza fissa nasconde la seconda riga.La pagina contiene ancora ogni parola, quindi un'asserzione che legge il testo viene superata.Il vostro utente legge “Conferma il tuo or...”.

4. Un elemento spinto fuori dalla vista

Una tabella più larga o un titolo più lungo spinge il pulsante Acquista oltre il bordo destro di uno schermo stretto.Il pulsante conserva la sua dimensione, quindi toBeVisible() dà ancora esito positivo.Il test lo individua solo se chiede anche toBeInViewport() per quel pulsante.

5. L'immagine o l'icona sbagliata

Un prodotto mostra la foto di un altro prodotto, un font di icone smette di funzionare e lascia un quadrato vuoto, o un aggiornamento di uno sprite scambia due icone.L'elemento immagine e la classe dell'icona non sono cambiati, quindi il codice sembra corretto.

6. Un layout rotto da una modifica CSS

Una regola cambia un margine, una direzione flex o una colonna della griglia.I riquadri si sovrappongono, una colonna scivola sotto un'altra, un modulo perde il suo allineamento.Ogni elemento è ancora nel codice, con il suo testo e la sua dimensione, quindi ogni asserzione viene superata.

7. Un'etichetta tradotta che non ci sta

Le parole tedesche o francesi sono spesso più lunghe di quelle inglesi.Un'etichetta esce dai bordi del suo pulsante, va a capo su una seconda riga o spinge via il pulsante successivo.La traduzione è corretta, quindi un'asserzione sul testo viene superata in ogni lingua.

8. Un font che non si è caricato

Quando un font web non si carica, il browser ripiega su un altro font: le righe vanno a capo in modo diverso, e le icone disegnate con un font diventano riquadri vuoti.Il testo nel codice è lo stesso, quindi nulla fallisce.

9. Un indicatore di caricamento che non si ferma mai

I dati arrivano e le righe vengono aggiunte alla pagina, ma lo strato di caricamento resta in primo piano.Il test trova le sue righe nel codice e viene superato.Il vostro utente aspetta davanti a un indicatore di caricamento.

La documentazione stessa di Cypress lo riassume in una riga: “un'applicazione può superare ogni test funzionale ed essere comunque rilasciata visibilmente difettosa”.

Il test di regressione visiva con gli screenshot può individuarli?

Sì, ed è la risposta abituale.Il test di regressione visiva confronta un'immagine dello schermo con un'immagine di riferimento acquisita in precedenza.

Playwright lo integra con toHaveScreenshot().La sua documentazione avverte che il rendering del browser può variare con il sistema operativo host, la sua versione e le sue impostazioni, l'hardware e la modalità headless.Per questo ogni browser e ogni piattaforma hanno la propria immagine di riferimento.

Cypress acquisisce screenshot, e la sua documentazione dice che “non esegue da sé il confronto delle immagini”.Il confronto lo aggiungono dei plugin o dei servizi di test visivi.

Servizi come Percy e Applitools Eyes aggiungono punti di controllo con immagini ai vostri test in codice.Percy acquisisce e confronta screenshot durante le esecuzioni dei vostri test.Applitools Eyes aggiunge una chiamata di controllo all'interno di un test.

In entrambi i casi, il vostro test in codice deve comunque raggiungere ogni schermata e dire quando acquisire l'immagine: siete voi a scrivere e mantenere quel codice, i suoi selettori e le immagini di riferimento.Un confronto grezzo dei pixel segnala inoltre differenze innocue tra una macchina e l'altra, quindi la sua tolleranza diventa un compromesso tra falsi allarmi e bug non rilevati.

Per vedere questi strumenti fianco a fianco, consultate lo studio comparativo.

Perché il test manuale non colma il divario

Una persona vede ognuno di questi bug a colpo d'occhio.Per questo molti team provano ancora a mano la loro applicazione, clic dopo clic, prima di un rilascio.Il test manuale ha però i suoi limiti.

LimiteCosa succede
TempoUn ciclo completo di test di regressione richiede ore, quindi si esegue prima di un rilascio, non a ogni build.
AttenzioneAlla ventesima schermata dello stesso ciclo, l'occhio scorre in fretta.Un piccolo cambiamento di colore o un'icona mancante passano inosservati.
RipetibilitàDue tester guardano cose diverse, e lo stesso tester guarda in modo diverso un venerdì sera.Un bug trovato una volta potrebbe non essere mai più cercato.
CoperturaOgni browser, dispositivo e lingua moltiplica il lavoro.

I test end-to-end automatici ripetono gli stessi controlli a ogni build senza stancarsi.La questione è come far loro guardare lo schermo come lo guarda una persona.

Come si costruiscono test end-to-end che vedono ciò che vedono gli utenti?

Qualunque strumento usiate, sei principi fanno vivere a un test end-to-end la vostra applicazione come la vive un utente.

  1. 1

    Pilotare l'applicazione reale

    Fare clic e digitare come fa una persona, sullo schermo reale.Un test che non riesce a premere un pulsante coperto fallisce proprio dove il vostro utente resterebbe bloccato.

  2. 2

    Controllare ciò che viene mostrato

    Controllare lo schermo in tre modi: l'immagine, perché un elemento abbia l'aspetto giusto; le parole, perché dica la cosa giusta; la disposizione, perché ogni cosa stia al suo posto.

  3. 3

    Prima trovare l'elemento, poi confrontarlo

    Una finestra che si è spostata o una pagina che è stata fatta scorrere non sono un bug.Un test dovrebbe trovare l'elemento dove si trova ora, poi giudicarne l'aspetto.

  4. 4

    Ignorare il rumore, mai un cambiamento reale

    Gli schermi differiscono leggermente da una macchina all'altra, quindi il confronto dovrebbe ignorare il rumore di rendering e cogliere comunque ogni cambiamento che una persona noterebbe.

  5. 5

    Mostrare le prove

    Un fallimento dovrebbe mostrare la schermata attesa accanto a quella trovata, con il cambiamento evidenziato, così che chiunque nel team possa leggerlo.

  6. 6

    Tenere basso il costo del cambiamento

    Quando l'applicazione cambia di proposito, accettare il nuovo aspetto dovrebbe richiedere un clic, non una riscrittura.

Come GUI Test Studio testa ciò che vedono gli utenti

GUI Test Studio costruisce test end-to-end su questi principi, senza codice.Testa app web, app desktop Windows, telefoni Android e giochi con un solo tipo di test.Scoprite di più sul test visivo e sul test GUI con questo strumento.

Registrare il flusso una volta

In GUI Test Runner-Recorder, fate clic su Registra e svolgete il flusso come fate sempre: registra il vostro mouse, la vostra tastiera e lo schermo.Potete anche descrivere il flusso in un prompt a Claude, a ChatGPT o a un modello di IA locale, uno nostro o uno vostro, che lo registra per voi.

Quando vi fermate, vi chiede cosa deve verificare il test.Con le risposte predefinite, ogni elemento su cui fate clic o in cui digitate riceve un'asserzione visiva subito prima della vostra azione.Ciò che compare da solo, come un menu, una finestra di dialogo o un messaggio, riceve un'asserzione di gruppo.

Controlli di ciò che mostra lo schermo

ControlloDi cosa si assicura
Asserzione visivaUn elemento è sullo schermo e ha l'aspetto giusto: la sua immagine, i suoi colori, la sua icona.
Asserzione visiva di assenzaQualcosa è scomparso: un indicatore di caricamento, un banner, una finestra di dialogo che deve chiudersi.
Asserzione testualeLe parole sono giuste, qualunque sia il font o il colore.
Asserzione di layoutGli elementi stanno al loro posto: nulla si è spostato, sovrapposto o è uscito dallo schermo.
Asserzione di gruppoPiù controlli di una schermata nello stesso momento e, se lo volete, la loro disposizione.

Ognuna ha la sua guida: asserzioni visive, asserzioni testuali e asserzioni di layout e di gruppo.

Trovare l'elemento, poi confrontarlo

Ogni asserzione visiva viene decisa in due fasi.La Fase di ricerca chiede se l'elemento è sullo schermo, e lo attende fino al tempo massimo del controllo.Il GTS Engine + AI trova l'elemento chiedendo prima all'applicazione, tramite le sue informazioni di accessibilità o gli elementi della pagina stessa, e a vista quando l'applicazione non lo dice.Vedete come GUI Test Studio trova ogni elemento.

La Fase di verifica confronta poi da vicino l'elemento con il suo obiettivo visivo, l'immagine che il test si aspetta.Ignora ciò che l'occhio non vede, come l'anti-aliasing e la compressione video, e coglie comunque le regressioni reali che una persona chiamerebbe un cambiamento: una parola diversa, un colore, un'icona.

Quando l'elemento viene trovato in un punto diverso da quello della registrazione, i clic che lo seguono vengono diretti dove si trova ora.E un test non fa mai clic alla cieca attraverso un banner: quando l'elemento è coperto, il suo controllo fallisce prima del clic.

Leggere cosa è cambiato

Dopo un'esecuzione, il report di affidabilità mostra ogni controllo con l'immagine attesa accanto all'immagine trovata, il cambiamento evidenziato e l'esito in una frase semplice.

A sinistra la schermata attesa, a destra quella trovata dall'esecuzione: il pulsante sembra disattivato e il titolo è diventato più grande.

Quando l'analisi intelligente con IA è attiva, un controllo non superato riceve anche un secondo sguardo da un'IA, che dice in parole semplici cosa è cambiato.Funziona con un modello nel cloud e la vostra chiave, o con un modello di IA locale sul vostro computer: uno nostro, o uno vostro.

Quando il cambiamento è voluto, accettate il nuovo aspetto dal report, e da quel momento il test lo attende.La riga di comando, gtr-cli, esegue gli stessi test da qualsiasi pipeline CI/CD, a ogni build.

Quale controllo individua quale bug visivo

Di nuovo i nove bug, con il controllo di GUI Test Studio che individua ciascuno di essi.

Il bugIl controlloCosa dice il report
Un elemento coperto da un altroAsserzione visivaNon trovato, o diverso: lo schermo non mostra più l'immagine dell'elemento.
Un testo che nessuno riesce a leggereAsserzione visivaDiverso: i colori sono cambiati.
Un testo tagliatoAsserzione visivaDiverso: manca la fine dell'etichetta.
Un elemento spinto fuori dalla vistaAsserzione di layoutL'elemento viene indicato per nome, e di quanto si è spostato.
L'immagine o l'icona sbagliataAsserzione visivaDiverso: l'immagine è cambiata.
Un layout rotto da una modifica CSSAsserzione di layout, o un'asserzione di gruppo con il suo controllo di layoutOgni elemento che si è spostato, e di quanto.
Un'etichetta tradotta che non ci staAsserzione visiva, asserzione di layoutDiverso, o spostato.
Un font che non si è caricatoAsserzione visivaDiverso: le lettere sono cambiate.
Un indicatore di caricamento che non si ferma maiAsserzione visiva di assenzaAncora sullo schermo allo scadere del suo tempo.
Un'asserzione di layout nomina l'elemento che si è spostato e di quanto, e propone l'impostazione che la farebbe rispettare.

Dove i controlli in codice restano al loro posto

Il test visivo non sostituisce i vostri test unitari e delle API, che controllano rapidamente la logica e i dati, sotto lo schermo.Anche un controllo in codice che pone già la domanda giusta, come un hit test prima di un clic, mantiene il suo posto.Il test visivo aggiunge il livello che nessuno di essi riesce a vedere: lo schermo che guardano i vostri utenti.

Domande

Perché toBeVisible() di Playwright dà esito positivo quando un elemento è coperto?

Il controllo di visibilità di Playwright chiede solo se l'elemento ha un riquadro di delimitazione non vuoto e nessuno stile visibility: hidden.Non chiede se un altro elemento gli sta sopra.Un clic su quell'elemento invece lo controlla, quindi il bug sfugge quando il test legge l'elemento coperto invece di farci clic.

Selenium può rilevare un elemento nascosto dietro un altro elemento?

Non con isDisplayed(), che guarda lo stile, la dimensione e il ritaglio di un elemento, mai ciò che ci viene disegnato sopra.Un clic su un elemento coperto fallisce con l'errore element click intercepted.Un elemento che il test si limita a leggere viene comunque segnalato come visualizzato.

Qual è la differenza tra test visivo e test funzionale?

Il test funzionale controlla che una funzionalità si comporti correttamente: un clic porta alla pagina giusta, un modulo salva i suoi dati.Il test visivo controlla ciò che mostra lo schermo: gli elementi giusti, leggibili e al loro posto.Un test end-to-end che fa entrambe le cose individua ciò che noterebbero i vostri utenti.

Il test visivo è la stessa cosa del confronto tra screenshot?

Non proprio.Un confronto grezzo tra screenshot segnala ogni pixel cambiato, compreso il rumore di rendering che varia da una macchina all'altra.Un buon test visivo trova prima ogni elemento, ignora il rumore di rendering innocuo e coglie comunque le regressioni reali, poi mostra cosa è cambiato.

Devo scrivere codice per aggiungere asserzioni visive in GUI Test Studio?

No.Registrate il flusso una volta, e GUI Test Studio aggiunge un'asserzione visiva prima di ogni elemento su cui fate clic o in cui digitate, e controlla ciò che compare sullo schermo.Regolate i controlli su una timeline visiva.

I test visivi automatici possono sostituire il test manuale?

Sostituiscono la parte ripetitiva: ripercorrere le stesse schermate a ogni build.Una persona resta la migliore per giudicare un nuovo design o esplorare una funzionalità per la prima volta.

Selenium, Playwright, Cypress, Percy e Applitools Eyes sono marchi dei rispettivi proprietari.

Pronti a registrare il vostro primo test?

Tutte le funzionalità, per 15 giorni.

Preferite vederlo sul tipo di app che testate?Prenotate una chiamata gratuita di 30 minuti con il nostro team.

Prenota una demo