Menu

Testfixtures en identiteit: persoonsgegevens ordenen voor betrouwbare tests

Testfixtures voor identiteitsrecords moeten benoemd, stabiel en elk aan één scenario gekoppeld zijn. Dit is hoe u ze structureert zodat fouten in de loop der tijd reproduceerbaar blijven.

Gepubliceerd

  • testgegevens
  • identiteit
  • fixtures

Testfixtures met identiteitsrecords zijn de rijen die een testsuite permanent bewaart: de persoon die oud genoeg is, de persoon die dat niet is, de klant wiens adres één ononderbroken tekenreeks is, het account zonder achternaam. Ze zijn goedkoop om te maken en makkelijk om slecht te onderhouden, en een fixtuurset die uit de pas raakt met het product is erger dan helemaal geen fixtures, omdat die valse zekerheid geeft.

Deze gids behandelt hoe u identiteitsrecords binnen een fixtuurset ordent, welke randgevallen het bewaren waard zijn, en hoe u voorkomt dat de verzameling stilletjes wegrot.

Wat hoort in een fixture in plaats van een generator?

Een fixture wordt gebruikt wanneer de test op een specifieke uitkomst assert, en een generator wanneer de test op zoek is naar onbekende invoerproblemen. Het onderscheid gaat niet over grootte of formaliteit; het gaat erover of iemand de invoer vooraf moet kennen.

Dat betekent dat fixtures voor gedrag zijn: gegeven deze persoon, moet het systeem deze tak nemen. Generators zijn voor verkenning: voer het systeem veel plausibele mensen en kijk wat er breekt. Een test die op een respons assert maar zijn invoer willekeurig trekt, test niet het gedrag dat hij zegt te testen, omdat de volgende uitvoering een andere tak kan beproeven en ophoudt het geval te dekken dat de auteur voor ogen had.

De meeste suites hebben beide nodig, en de nuttige conventie is het onderscheid zichtbaar te maken. Fixtures leven in bestanden met stabiele waarden en leesbare namen. Gegenereerde records leven in een stap die tijdens de test loopt. De twee in één bestand mengen is hoe een suite zes maanden later onmogelijk te doorgronden wordt.

Waarom maakt “elke keer willekeurig” fouten onherhaalbaar?

Omdat het foutrapport geen invoer bevat. Een test die bij elke uitvoering een vers record trekt, produceert een stacktrace, een schermafbeelding en niets anders; de volgende uitvoering slaagt misschien, en de engineer blijft gissen of de oplossing werkte of dat de dobbelsteen veranderde.

Dit is de meest voorkomende bron van flaky tests in gegevensintensieve systemen, en de schade stapelt zich op. Engineers leren falende tests opnieuw te draaien tot ze groen worden, wat het hele team langzaam leert het signaal te negeren dat de suite juist hoort te geven. Reproduceerbaarheid is hier geen luxe; het is de eigenschap die de rest van de suite betekenisvol maakt.

De oplossing is de invoer vast te pinnen en de variatie ergens gecontroleerd vandaan te laten komen. Waar een record wordt gegenereerd in plaats van met de hand geschreven, levert het afleiden uit een vaste sleutel elke uitvoering dezelfde persoon op, zodat een assertie stabiel blijft en een bugmelding het exacte record kan noemen dat hij zag.

Hoe moeten fixturerecords worden benoemd en gegroepeerd?

Benoem elk record naar de situatie die het dient te testen, niet naar de waarden die het bevat. Een record met een naam als een-achttienplus-aanvrager vertelt de volgende lezer waarvoor het dient; een record vernoemd naar een achternaam vertelt niets en wordt binnen een maand voor het verkeerde doel hergebruikt.

Groepeer volgens dezelfde logica. Eén fixturebestand per functie of scenario, met alleen de mensen die dat scenario nodig heeft, houdt het bestand leesbaar en maakt het duidelijk wanneer een record ongebruikt is geworden. Eén enorm bestand met honderd records is het patroon dat suites oplevert waarin niemand kan zeggen welke fixture nog ertoe doet, dus niemand durft er een te verwijderen.

Twee kleinere praktijken betalen zichzelf terug. Zet een opmerking boven elke fixturegroep die aangeeft waarvoor de groep dient en wanneer die voor het laatst is herzien. En houd de waarden in de fixture, niet in de testcode, zodat het wijzigen van een record niet het bewerken van asserties vereist.

Welke identiteitsrandgevallen verdienen een permanente fixture?

Een korte lijst dekt een verrassende hoeveelheid risico, omdat elke vermelding een andere aanname breekt in plaats van een andere waarde.

Fixture De aanname die het breekt
Een persoon van meer dan een eeuw oud Dat geboortejaren altijd binnen een nauw bereik liggen
Een naam veel langer dan de interface toestaat Dat een voorbeeldveldbreedte representatief is
Een persoon zonder achternaam Dat er altijd twee naamdelen bestaan
Een naam in een niet-Latijns schrift of met diakritische tekens Dat het alfabet altijd het Latijnse is
Een record met een afwezige optionele identificatie Dat elk veld altijd gevuld is
Een geboortedatum op een schrikkeldag Dat elke datum elk jaar voorkomt
Een record met één bewust inconsistent paar Dat consistentieregels nog steeds worden gehandhaafd

De laatste vermelding is degene die teams het vaakst weglaten, en het is de meest waardevolle. Het is de enige fixture die faalt wanneer een consistentieregel per ongeluk wordt uitgeschakeld, en consistentieregels zijn precies het soort code dat tijdens een incident wordt versoepeld en nooit meer wordt aangescherpt.

Hoe rotten fixtures weg, en wat stopt dat?

Een fixture wordt niet vanzelf verkeerd; het systeem eromheen verandert. Een drempel verschuift van de ene leeftijd naar de andere en de persoon die net oud genoeg was, is dat niet meer. Een validatieregel wordt strenger en een record dat ooit slaagde, faalt nu, wat een geslaagde test rood maakt om een reden die niets te maken heeft met de code onder test. Een wereldwijde formaatswijziging landt en de helft van het fixturebestand wordt verouderd zonder dat iemand het merkt.

Drie gewoonten vertragen dit. Datumafhankelijke fixtures moeten de datum vermelden die ze aannemen, zodat het verstrijken van de tijd zichtbaar is in het bestand in plaats van ontdekt in een rode build. Fixtures moeten regelmatig worden beproefd, niet alleen wanneer hun functie verandert, zodat breuk vroeg aan het licht komt in plaats van tijdens een ongerelateerde wijziging. En reviews moeten vragen of elk record nog zijn plek verdient, want de kosten van een fixture zijn niet het maken ervan maar de verwarring die het veroorzaakt zodra het doel vergeten is.

Het diepere punt is dat fixtures gegevens met een onderhoudscontract zijn, en een suite die ze als onveranderlijke geschiedenis behandelt, test uiteindelijk het product zoals het was, niet zoals het is.

Moeten fixtures überhaupt worden gegenereerd?

Deels, en het is de moeite waard om bewust te zijn over de splitsing. Records die bestaan om gedrag vast te pinnen, moeten worden uitgeschreven, omdat iemand ze moet kunnen inspecteren en doorgronden. Records die bestaan om volume te leveren — honderd rijen voor een importtest, duizend voor een migratierepetitie — kunnen beter worden afgeleid, omdat niemand honderd rijen kan lezen en hun exacte waarden er niet toe doen zolang de vorm dat wel doet.

De reden om volume af te leiden in plaats van vast te leggen, is reproduceerbaarheid op schaal. Een vastgelegd bestand van duizend rijen is een onderhoudslast die met elke schemawijziging groeit, terwijl een afgeleide batch opnieuw kan worden gebouwd zodra het schema verschuift, en identiek opnieuw kan worden gebouwd als die door een vaste sleutel wordt aangestuurd. Records uit de generator voor identiteits- en testgegevens werken in deze rol: per land intern consistent, reproduceerbaar uit een sleutel, en duidelijk synthetisch zodat niemand een rij voor een echte klant aanziet.

Voor de kleine met de hand geschreven set geldt het omgekeerde. Houd die klein, houd die leesbaar, en houd elk record gekoppeld aan een benoemd scenario zodat het verwijderen ervan een geïnformeerde beslissing is in plaats van een gok. Alles in beide helften van de set is verzonnen voor softwaretesten; niets ervan beschrijft een echt persoon, en niets ervan mag als iemands identiteit worden gebruikt.

Voor ontwikkelaars: de fixtuurset structureren

Behandel fixturegegevens als deel van de testcode en pas dezelfde standaarden toe. Elk record heeft een naam nodig die zijn scenario vermeldt, een korte opmerking die uitlegt waarom het bestaat, en een plek in een groep die klein genoeg is om in één keer te lezen. Waarden leven in databestanden in plaats van in asserties, zodat een record op één plek kan worden bijgewerkt.

Laat de suite dan haar eigen invoer bewijzen. Voer de consistentiecontrole uit tegen de fixtures zelf, niet alleen tegen inkomende gegevens, zodat een fixture die zichzelf tegenspreekt luid faalt in plaats van stilletjes het tolerante pad te testen. Injecteer de huidige datum in plaats van die te lezen, zodat een fixture met een grensdatum niet van de ene op de andere dag van betekenis verandert. En houd één bewust kapot record in de set, waarvan is geassert dat het wordt afgewezen, als het permanente bewijs dat de bewakers nog aanstaan.

Leg ten slotte de herkomst vast. Een notitie van één regel dat deze records synthetisch zijn en voor testen gegenereerd, beschermt de volgende lezer tegen de aanname dat ze ergens uit een database komen, en dat is precies de aanname die ertoe leidt dat op een dag een echt record aan het bestand wordt toegevoegd omdat het handig was.

Volgende stappen

Open uw grootste fixturebestand en probeer de tien records met de vaagste namen te verwijderen; alles wat u niet kunt rechtvaardigen, is een record dat niemand begrijpt. Voeg dan het bewust inconsistente record toe als het ontbreekt, assert dat het systeem het afwijst, en bevestig dat de suite rood wordt wanneer die controle wordt uitgeschakeld. De gids over veldconsistentie legt de paren uit die dat record moet breken, en een verse batch uit de identiteitsgenerator dekt de volumehelft van de set.

Verder lezen

Handleidingen over Identiteits- en testdatagenerator