Test pixels: skærmbillede-QA for et lille team
Vores testsuite var grøn, og dropdown-menuen kunne ikke klikkes på. Unittest kan ikke se stacking-fejl, brud i mørkt tema eller overløb på mobil. Her er den lille rig, der nu kigger på hver eneste flade for os, og de visuelle fejl, den fanger, som tests aldrig vil.
Vi tog det til os på den ærlige måde: efter at have sendt visuelle regressioner ud, som ét enkelt skærmbillede ville have fanget. Et frostet panel, der kom ud blegt på mørke baggrunde. En menu, der blev tegnet, men ikke kunne klikkes på. Et søgefelt, der på telefonbredde eksisterede som en strimmel på 65 pixels. Hver eneste af dem sejlede gennem en grøn testsuite, fordi suiten testede funktioner, og fejlene boede i pixels.
Riggen er mindre, end du tror
Vores er et lokalt miljø fuldt af overbevisende opdigtede data, ét headless login hvis session gemmes på disken, så intet bremser det, og en løkke: sider gange temaer gange skærmstørrelser. Computer og telefon, lyst og mørkt, hver flade der betyder noget. Det hele er et kort script, og en fuld gennemgang laver en mappe med billeder på få minutter.
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 }); }}Skærmbilleder plus bevis
Billeder fanger det, øjne fanger. Til fejl i samspillet vil du have browseren til at vidne. To enkelte linjer klarer det meste: elementFromPoint i midten af et kontrolelement fortæller dig, hvad der i virkeligheden ville modtage klikket, og getBoundingClientRect fortæller dig, om elementet faktisk er inden for den skærm, det påstår at understøtte. Vi tjekker nu begge dele for alt, der har brændt os.
// 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;});Begge temaer, hver gang
Fejl i mørkt tema er en kategori for sig, fordi de gemmer sig for udviklere, der arbejder i ét tema. Et hårdkodet næsten hvidt fyld ser bevidst ud på en lys side og radioaktivt ud på en mørk. At vende temaattributten inde i det samme besøg koster én linje og fordobler din dækning. Vi betragter enhver flade, der ikke er fotograferet i begge temaer, som utestet.


Det, den fanger
- Fejl i stacking context: tegnet, synligt og umuligt at klikke på. Kun et hit-test ser dem.
- Temalækager: lyse flader der lyser på mørke sider, grafer der forsvinder, illustrationer med indbagte baggrunde.
- Overløb på telefon: faste bjælker der dækker indhold, felter der er klippet til strimler, overskrifter der er skåret midt i en sætning.
- Tekst i sammenhæng: afkortningen, modsigelsen, den sætning som en linter aldrig vil fange.
Intet af det erstatter unittestene. Suiten beviser regnestykket med pengene; skærmbillederne beviser, at et menneske kan nå den knap, der sætter det i gang. Et lille team har ikke en QA-afdeling, men en mappe med friske skærmbilleder gennemgået før hver udgivelse er en udmærket efterligning af en. Testen er det at kigge.
Tests består er en udtalelse om dine funktioner. Skærmbilledet er en udtalelse om dit produkt.