Testa i pixel: controllo qualità a screenshot per un piccolo team
La nostra suite di test era verde e il menu a tendina non si poteva cliccare. I test unitari non vedono i bug di impilamento, il tema scuro rotto o il traboccamento su mobile. Ecco la piccola macchina per screenshot che adesso guarda ogni schermata al posto nostro, e i bug visivi che i test non troveranno mai.
Ci siamo arrivati nel modo onesto: dopo aver rilasciato regressioni visive che un solo screenshot avrebbe intercettato. Un pannello smerigliato che veniva slavato sugli sfondi scuri. Un menu che si disegnava ma non si poteva cliccare. Un campo di ricerca che alla larghezza di un telefono esisteva come una scheggia da 65 pixel. Ognuno di questi è passato indenne da una suite di test verde, perché la suite testava funzioni e i bug vivevano nei pixel.
La macchina è più piccola di quanto pensi
La nostra è un ambiente locale popolato di dati finti ma credibili, un accesso headless la cui sessione è salvata su disco così niente ci rallenta, e un ciclo: pagine per temi per dimensioni dello schermo. Computer e telefono, chiaro e scuro, ogni schermata che conta. È tutto uno script breve, e una passata completa produce una cartella di immagini in pochi minuti.
import { chromium } from 'playwright'; const browser = await chromium.launch();const ctx = await browser.newContext({ storageState: 'auth.json', // login once, reuse everywhere viewport: { width: 1440, height: 900 },});const page = await ctx.newPage(); for (const [name, url] of PAGES) { await page.goto(BASE + url, { waitUntil: 'load' }); for (const theme of ['light', 'dark']) { await page.evaluate((t) => document.documentElement.setAttribute('data-theme', t), theme); await page.screenshot({ path: `shots/${name}-${theme}.png`, fullPage: true }); }}Screenshot più prove
Le immagini colgono quello che colgono gli occhi. Per i bug di interazione vuoi che sia il browser a testimoniare. Due righe fanno quasi tutto il lavoro: elementFromPoint al centro di un comando ti dice cosa riceverebbe davvero il clic, e getBoundingClientRect ti dice se quel comando entra davvero nello schermo che dichiara di supportare. Adesso li verifichiamo entrambi per qualsiasi cosa ci abbia già scottato.
// Is the menu item really clickable, or is something invisible covering it?const hit = await page.evaluate(() => { const el = document.querySelector('[role="menuitem"]'); const r = el.getBoundingClientRect(); const top = document.elementFromPoint(r.x + r.width / 2, r.y + r.height / 2); return el === top || el.contains(top);}); // Does the search input actually fit a 390px phone?const fits = await page.evaluate(() => { const r = document.querySelector('input[name="q"]').getBoundingClientRect(); return r.right <= window.innerWidth && r.width > 200;});Tutti e due i temi, ogni volta
I bug del tema scuro sono una categoria a sé, perché si nascondono agli sviluppatori che lavorano in un tema solo. Un riempimento quasi bianco scritto a mano sembra voluto su una pagina chiara e radioattivo su una scura. Cambiare l'attributo del tema durante la stessa visita alla pagina costa una riga e raddoppia la copertura. Trattiamo come non testata qualsiasi schermata che non sia stata fotografata in entrambi i temi.


Cosa intercetta
- Bug di contesto di impilamento: disegnato, visibile e non cliccabile. Solo un test sul clic li vede.
- Fughe di tema: superfici chiare che brillano su pagine scure, grafici che spariscono, illustrazioni con lo sfondo cotto dentro.
- Traboccamento sul telefono: barre fisse che coprono i contenuti, campi ridotti a schegge, titoli tagliati a metà frase.
- Il testo nel suo contesto: il troncamento, la contraddizione, la frase che nessun linter segnalerà mai.
Niente di tutto questo sostituisce la suite unitaria. La suite dimostra che i conti sul denaro tornano, gli screenshot dimostrano che una persona arriva al pulsante che li fa partire. Un piccolo team non ha un reparto di controllo qualità, ma una cartella di screenshot freschi rivisti prima di ogni rilascio è una discreta imitazione. Il test è il guardare.
I test passano è un'affermazione sulle tue funzioni. Lo screenshot è un'affermazione sul tuo prodotto.