Sådan bruges Golden Master-test til dine iOS-apps

Den menneskelige opfattelse er et interessant emne. Vi opfatter ikke i absolutte værdier, i stedet ser vi tingene på en relativ måde. Har du nogensinde spekuleret på, hvorfor pirater havde øjetlapper? Dette skyldes, at øjet under plasteret har en anden relativ værdi for lys end det andet øje. Når de gik under dækket, var de stadig i stand til at se og behøvede ikke at justere deres syn. For længe siden var dette livreddende. Det er ofte lettere at se forskelle, når man opfatter farver og gråtoner i relative værdier (f.eks. En tiger i junglen). Desværre på samme tid gør det os tilbøjelige til subtile ændringer. Vi ser ikke små ændringer, f.eks. forskellen mellem 36 og 36,5% i et cirkeldiagram:

Heldigt for os fungerer computeren med absolutte værdier. Dette muliggør høj præcision, og ovenstående forskel ville være blevet opdaget uden problemer.

Under testning er vi ofte nødt til at sammenligne vores nuværende version med en slags tidligere version. Den såkaldte Golden Master-test fanger resultatet af en proces og sammenligner den med en forudgående korrekt version for at opdage uventede ændringer. En fælles implementering af denne tilgang er UI-snapshot-test. Men lad dig ikke forveksle! Kontrollering af dine backend API'er ved at sammenligne det med tidligere resultater er også en form for Golden Master-test.

Da vi arbejder med iOS-apps, skal vi se et dybere kig på UI-snapshot-test.

Grunde

Golden Master-test tester ikke din kode for rigtighed, men du kan være sikker på, at opførslen forbliver den samme. Dette i sig selv kan være vigtigere end korrekthed. Dette kan være især nyttigt, når du ikke har en nem måde at integrere en anden slags automatiserede test på. Har du nogensinde arbejdet med en enorm arvekodebase? Jeg var heldig, og mine to første job var netop sådan. Det var en smerte at indføre enhver form for test. Det kom så langt, at vi ikke var i stand til at introducere XCTest i vores iOS-App, da vi brugte libstdc ++. En mulighed ville have været at tilføje Golden Master-test. I det mindste ville vi have vidst, om vi brød noget eller ej. Desværre vidste jeg ikke om denne mulighed dengang.

På den anden side, hvis du allerede har en enorm base af enhedstests og UI-tests, kan det stadig hjælpe dig med at finde en uventet regression, som ikke er dækket af dine tests (du kan ikke teste enhver mulig sti). Desuden kan analysen være ret detaljeret. Det kan registrere små ændringer og er endda egnet, hvis din kode afhænger af resultatet af et eksternt bibliotek.

Som jeg allerede har nævnt, kan Golden Master-test hjælpe med til at visualisere opfattelsesmæssige forskelle i vores UI.

UI-snapshot-test

Lad os se mere detaljeret på visuel perception-test (også kaldet UI-snapshot-test).

Den grundlæggende idé er at tage et billede af skærmen, mens den viser de kendte korrekte data. Dette er vores gyldne mester. Hver gang vi ændrer vores software opretter vi et nyt billede af den samme skærm og sammenligner det med vores gyldne master. I tilfælde af at alt er det samme, ved vi, at vi ikke har nogen form for visuel forskel. Hvis dette ikke er tilfældet, ved vi, at der er forskel, men hvordan går vi videre? Det betyder ikke nødvendigvis, at vi brød nogle kode. Måske indeholder det forventede ændringer, måske ikke. Vi ved det ikke uden at kigge efter! Det eneste, vi ved, er, at noget er ændret. Yderligere undersøgelse er nødvendig, så UI-snapshot-test er ikke vores svar på alt.

Testdata

Jeg har oprettet en lille skærm, der viser det tyske flag som en bold, to etiketter, to tekstvisninger og en knap.

Vores gyldne mester er:

Dette er resultatet af en fejlagtig test:

Hvor mange forskelle kan du finde bare ved at se på det?

PerceptualDiff

Google har skrevet et lille værktøj, der beregner forskellen mellem to billeder.

Her er PerceptualDiff-output ved hjælp af de to billeder ovenfor:

FAIL: Billeder er synligt forskellige
1839 pixels er forskellige

Jeg antager, at du fandt fejlen i brugernavnet, men så du forskellen på det tyske flag? Det var ikke et firkant mere. I stedet var det 127,5x128 pixels. Denne ændring er næsten umulig at opdage, når du bruger det blotte øje uden et billede at sammenligne med. Som standard genererer det ikke en outputfil. Det har dog et outputflag:

pdiff -output diff.ppm testimage.png goldenMaster.png

Dette vil oprette en fil, hvor du visuelt kan se forskellene.

En dejlig forskel på funktionen, der er, er at indstille antallet af tilladte ændrede pixels. Nogle gange vil du ikke have en testfejl på grund af små ændringer, men som oftest vil jeg råde dig til at holde dig til standardindstillingen.

Der er flere værktøjer til at oprette en diff til to billeder. Du kan opnå det samme diff-resultat med ImageMagick:

sammenligne testimage.png goldenMaster.png -compose src diff.png

FBSnapshotTestCase

Selvfølgelig at sidde ned, oprette skærmbilleder og derefter sammenligne dem er en ganske kedelig opgave. Vi kunne gøre det ved at bruge enten fastlane-snapshot til at oprette snapshots (eller ved hjælp af Xcode 9's nye funktions snapshot), gemme dem med et specifikt navn i et bibliotek og bruge pdiff til at sammenligne dem med vores gyldne master.

Eller vi kunne bruge FBSnapshotTestCase. Facebook frigav dette værktøj for at lette snapshot-test i iOS-udvikling. I det følgende vil jeg undersøge, hvordan man indstiller det, og hvordan man bruger det. Jeg vil beskrive brugen inden for enhedstestmål, men du kan også bruge UI-testmål.

Opsætning

Facebook beskriver på deres Github-side, hvordan man indstiller FBSnapshotTestCase via CocoaPods. Men du har også muligheden for at integrere det via Carthage. Det er ligetil som enhver anden Carthage-integration.

Tilføj endvidere følgende til dine schemaers opstartparameter, så vi kan finde vores gyldne masterbilleder i vores depot:

FB_REFERENCE_IMAGE_DIR: $ (SOURCE_ROOT) / $ (PROJECT_NAME) tests / FailureDiffs
FB_REFERENCE_IMAGE_DIR: $ (SOURCE_ROOT) / $ (PROJECT_NAME) test

Opret en ny fil i vores Unit-Test-mål og ændre import XCTest for at importere FBSnapshotTestCase. Gør det samme for superklassen i din testklasse.

Føj en test som denne til din TestCase:

Dette gør følgende:

  • øjeblikkelig en ViewController
  • start visningscyklus
  • indtast testdata
  • ved hjælp af FBSnapshotTest for at bekræfte, at det er rigtigt

For at oprette vores gyldne master skal vi tilføje recordMode = true til setUp (). Når du kører denne test, vil den mislykkes. Men hvis du læser lidt i logfilerne, står det:

mislykkedes - Test kørte i optagetilstand Referencebilledet er nu gemt. Deaktiver optagefunktion for at udføre en faktisk sammenligning af snapshot!

Din gyldne master er oprettet i det bibliotek, du har angivet ovenfor.

Fjernelse af recordMode = true vil konfigurere din test til faktisk at sammenligne testdataene med din gyldne master.

Lad os se, hvad testresultatet var for ovenstående billeder.

I testoutputet kan du finde et bibliotek, hvor du kan finde alle de oprettede billeder. Dette indeholder testImage, referenceImage og en diffImage. Jeg har brugt disse tre billeder ovenfor.

CI-proces

Desværre er FBSnapshotTestCase ikke i stand til at bedømme, om denne fejl er beregnet eller ej, så den kan ikke give dig nogen detaljer undtagen for "Test mislykkedes". Denne bedømmelse skal gøres af dig. Vi er ikke de første til at undersøge visuel perception-test. Et team hos Google gjorde dette, og heldigvis nævnte de deres CI-proces i en video. Generelt ser det sådan ud:

  1. Kør test
  2. Opret billeder
  3. Sammenlign billeder med GM
  4. Release Manager kontrollerer, om der var forventet ændringer

Jeg synes, punkt 4 er det mest interessante. Hver gang brugergrænsefladen ændrer din Release Manager kontrollerer de manglende test og beslutter for eller imod frigivelsen. De understreger det også:

"Manglende UI-snapshot-tests betyder ikke, at der er noget, der er brudt"

fælder

Selvom jeg fokuserede på UI-snapshot-test, nævnte jeg andre brugssager til Golden Master-test. Et problem opstår, når man sammenligner værdier med flydende punkter. Du ved, at de ikke burde sammenlignes med lighed, men det er præcis, hvad Golden Master-test gør. Så måske ønsker du at udelukke dette eller opstille særlige regler om dette. Et andet problem kan være tidsstempler (f.eks. Udløbsdato for kuponer). Hver gang du ikke har kontrol over disse, kan du måske ekskludere dem.

Konklusion

Golden Master-test er et virkelig nyttigt værktøj. Du ved, hvis der opstår noget uventet, men desværre er du ikke altid i stand til at vide, hvad var det. Denne type test kan let tilføjes til enhver ældre kodebase, selv når du ikke er i stand til at skrive en masse enhedsprøver på grund af stor kompleksitet. At køre disse test sikrer, at du ikke ændrer noget. Det tjekker ikke for bekræftelse. I stedet kontrollerer det for ændringer. På denne måde, hvis testene bestås, kan du være sikker på, at opførslen ikke ændrede sig.

Jeg er nysgerrig efter at kende din oplevelse med Golden Master-test. Du er velkommen til at dele din sag i kommentarerne herunder.

Yderligere læsning

  • Snapshot-test på data
  • Hvordan man ikke skriver GM-test