Nordlet

← Blog

Pre-produktions-testplan for en regnskabs-API

En guide til pålidelighed for ingeniørteams: duplikerede skrivninger, genbrug af idempotens, webhook-signaturer, hændelser i uorden, decimalpenge, scopes, periodelåse og genoprettelse.

Nordlet Team · · 15 min. læsetid

En 201 Created fra en regnskabs-API fortæller dig stortsetInt ingenting. Den bekræfter blot, at serveren svarede. Den bekræfter ikke, at der findes præcis én faktura, at debet er lig med kredit, at dokumentnummeret kun er tildelt én gang, eller at et forsøg på at gentage handlingen efter en mistet forbindelse ikke bogfører en kopi mere. De fleste produktionsduplikater i regnskaber opstår i netop dette tomrum: en mutation, som blev gennemført på serveren, mens klienten sad tilbage med et ukendt udfald og i stilhed forsøgte igen med en frisk nøgle.

Denne plan er til teams, der evaluerer en regnskabs-API, før de forbinder den med rigtige regnskaber. Den fokuserer på fejlhåndtering frem for solskinshistorier. Hvert afsnit herunder beskriver, hvad der skal testes, hvad der skal tjekkes, og hvad der tæller som bestået. Implementeringskonteksten her er Nordlet, hvis API bruger scoped bearer-nøgler, beløb som decimalstrenge, idempotensnøgler og signerede webhooks. For at finde den nøjagtige syntaks for endepunkter og svarkontrakter bør du læse siderne om API-konventioner og Kom i gang i stedet for at stole på antagelser.

Hvad "bestået" egentlig betyder

En test beviser kun, at en regnskabsintegration er sikker, når den verificerer semantikken og ikke bare statuskoderne. For hvert scenarie skal testsuiten bekræfte:

  • Forretningsmæssig sideeffekt: præcis én kunde, faktura, kassekladde, nummertildeling eller betalingsovergang eksisterer.
  • Regnskabsmæssig integritet: debet er lig med kredit, og den monetære præcision overlever serialisering.
  • Genafspilningsadfærd: et nyt forsøg returnerer det oprindelige resultat i stedet for at oprette en ny post.
  • Holdbarhed: audit-poster og webhook-hændelser eksisterer, når først handlingen er gennemført.
  • Fejl uden sideeffekter: afviste forespørgsler forbruger ingen dokumentnumre og skriver ingen delvise finansposter.
  • Genoprettelse: en midlertidig fejl kan forsøges igen uden duplikering eller permanent tab.

Googles API-vejledning trækker grænsen klart op: kun handlinger, hvis gentagne udførelse efterlader den samme endelige tilstand, er sikre at gentage, og en API bør identificere, hvilke handlinger der er idempotente, i stedet for blidt at gentage ethvert fejlbehæftet kald.

Opsæt et engangs- og observerbart miljø

Brug en sandkassevirksomhed, ikke produktionsregnskabet. En Nordlet-sandkassevirksomhed bruger de samme moduler og API-adfærd som en rigtig virksomhed og er markeret som testdata, hvilket gør den sikker til store mængder af duplikat- og fejl-tests. Flaget kan ikke ændres efter oprettelsen, så rigtige regnskaber kan ikke senere omklassificeres til testdata. Bemærk, at brugen af sandkassen måles og afregnes på præcis samme måde som forbruget i en rigtig virksomhed, så afstem dine volumen-tests med den prismodel, du befinder dig på.

Før du skriver nogen test, skal du forberede:

  • En dedikeret sandkassevirksomhed med isSandbox: true.
  • En test-API-nøgle, der udelukkende er begrænset til de moduler, der testes.
  • Et webhook-endepunkt eller en lokal tunnel, der bevarer det rå forespørgselsindhold.
  • Seedede kunder, leverandører og en kendt kontoplan.
  • Mindst to regnskabsperioder: én åben og én låst.
  • Et tjek-ur eller en datofixtur, hvis implementationen understøtter det.
  • Et lokalt lager, der registrerer ethvert forsøg på forespørgsel, idempotensnøgle, svar-hash, webhook-levering og afstemningsresultat.

Kør ikke duplikat-tests mod delt staging-data. En vildfarende kunde eller faktura fra en tidligere kørsel gør senere kontroludsagn tvetydige.

Din fixtur for enhver mutation bør indfange metode, endepunkt, fuldt indhold (body), idempotensnøgle, nøgle-scope, et klient-korrelations-id, start- og sluttidspunkter, svarstatus, headers, body, forespørgsels-id (request ID) og om forbindelsen faldt ud, før svaret nåede frem. Brug faste decimalstrenge såsom "75.0000" til pengebeløb. Nordlet repræsenterer monetære værdier som decimalstrenge med op til fire decimaler, og deres eksempelfaktura bruger netop det format.

Den anden halvdel af opsætningen er fejlinjektion. Dit testmiljø skal kunne forsinke et svar, afbryde en TCP-forbindelse, efter serveren har modtaget forespørgslen, returnere syntetiske 429/500/502/503/504-svar, returnere en ikke-2xx-status fra webhook-modtageren, levere den samme webhook to gange, ændre rækkefølgen på hændelser, korrumpere én byte i en webhook-body, ændre indholdet i en idempotensnøgle, mens selve nøglen bevares, køre to identiske forespørgsler samtidigt og låse en periode mellem opsætning og bogføring. Disse scenarier er mere værd end hundrede solskinseksempler.

Lås kontrakten fast, før du skriver logikken til nye forsøg

Generer eller hent OpenAPI-skemaet, og sammenlign det med din klient. Nordlet udgiver sin OpenAPI-specifikation i API-referencen og genererer sine typede SDK'er ud fra netop denne specifikation, så skemadrevne tests slår manuelt gætteriet.

Verificer påkrævede felter og typer, decimalstreng-felter, dato- og tidsstempelformater, tilladte handlinger og scopes, formen på fejlsvaret, webhook-hændelsesskemaer, hvilke mutationer der accepterer en idempotensnøgle, og hvilke svarsfelter der identificerer det oprettede objekt.

Beståelseskriterier. Klienten afviser ugyldige payloads lokalt, hvis skemaet tillader det. Serverens svar matcher det dokumenterede skema. Ugyldige decimaler, dårlige datoer og manglende påkrævede felter skaber strukturerede valideringsfejl. Der forsøges ikke igen ved deterministiske valideringsfejl.

Fejltype der skal fanges. En klient parser "121.0000" til et binært flydende tal (float) og serialiserer et lidt anderledes beløb senere. Hele tal går igennem; momslinjer og brøkdele slår fejl. Test penge som strenge hele vejen igennem.

Autorisering og lejer-isolering (tenant isolation)

Brug separate nøgler til læsning og skrivning. Test derefter hele matricen: manglende nøgle, ugyldig nøgle, gyldig nøgle med utilstrækkeligt modullabel (scope), gyldig nøgle med det rette scope, en nøgle, der tilhører en anden virksomhed, og et forsøg på at læse et objekt fra en anden virksomhed.

Kontroller:

  • Manglende eller ugyldige legitimationsoplysninger returnerer 401.
  • En gyldig nøgle uden den nødvendige tilladelse returnerer 403.
  • Der oprettes ingen regnskabsmæssig sideeffekt ved nogen af fejsituationerne.
  • En succesfuld forespørgsel kan ikke læse eller ændre en anden virksomheds poster.
  • Sikkerhedsfejl forsøges aldrig automatisk igen.

Beståelseskriterium. Du kan bevise både autorisationskorrekthed og lejer-isolering med efterfølgende læsetests og ikke blot ved hjælp af statuskoder.

Bevis én ren transaktion

Kør et lille, deterministisk forløb: opret eller find en testkunde, opret en faktura med decimalstrengsbeløb, udsted den, læs fakturaen og dens regnskabsmæssige virkning, læs audit-posten, og modtag webhook'en. Nordlets Kom i gang-eksempel viser, at udstedelse af en faktura tildeler et nummer uden huller, tjekker at perioden er åben og bogfører en balanceret kassekladde i samme transaktion.

Bekræft at fakturaen når den forventede tilstand, at dokumentnummeret tildeles præcis én gang, at debet er lig med kredit, at moms og linjetotaler matcher den forventede "half-up"-afrunding, at audit-posten nævner aktøren og ændringen, at webhook'en leveres i sidste ende, og at API-svaret samt en efterfølgende læsning er enige om fakturaens ID og tilstand.

Én sondring er værd at holde fast i: At en webhook ankommer, er ikke bevis for, at mutationen er gennemført. API-svaret plus en læsning er dine primære transaktionsbekræftelser. Webhook'en beviser underliggende advisering og testes separat.

Idempotens: samme nøgle, samme indhold

Generer én nøgle for hver logiske forretningshandling, ikke én nøgle pr. netværksforsøg. Send mutationen med nøgle K og indhold B, gem det oprettede ID, og send derefter præcis den samme forespørgsel igen.

Bekræft at det andet svar repræsenterer den samme handling, at objekt-ID'et er identisk, og at der kun findes ét forretningsobjekt, én bogføring, én nummertildeling og én finansiell virkning. Det genafspillede svar bør bære den dokumenterede genafspilningsheader – x-idempotent-replay: true i Nordlets tilfælde – og revisionssporet bør vise, at der ikke er sket nogen anden mutation.

To lagringsregler ændrer, hvad dit loop for nye forsøg bør forvente, så test dem direkte: Et gemt 4xx-svar genafspilles som ethvert andet svar, mens et 5xx-svar slet ikke gemmes, så et nyt forsøg efter en serverfejl udfører handlingen igen i stedet for blot at genafspille. Nøgler udløber også, hos Nordlet efter 24 timer, hvilket sætter en grænse for, hvor længe en genafspilning er tilgængelig.

Nordlets dokumentation lover, at tilføjelse af en Idempotency-Key-header forhindrer en gentaget forespørgsel i at skabe en duplikat, og selskabets API-konventioner definerer den præcise genafspilningsheader og kravet om et byte-for-byte-svar. Princippet matcher Stripes offentliggjorte model: en nøgle identificerer den logiske handling, gentagelser returnerer det gemte resultat, og en nøgle, der genbruges med andre parametre, afvises i stedet for at blive ændret i stilhed.

Beståelseskriterium. Der eksisterer præcis én finansiel tilstandsovergang, uanset hvor mange gange klienten sender den samme forespørgsel inden for genafspilningsvinduet.

Idempotens: samme nøgle, ændret indhold

Send den oprindelige forespørgsel med nøgle K og indhold B1, efterfulgt af en anden forespørgsel med nøgle K og indhold B2, hvor mindst ét beløb, én kunde, én dato eller én linje afviger.

Forventet resultat: forespørgslen afvises med den dokumenterede nøglegenbrugsfejl – Nordlet returnerer 422 idempotency_key_reuse – den oprindelige post berøres ikke, der vises ingen ny post, intet nyt nummer eller ændring i revisionen, og klienten "retter" det ikke ved at generere en ny nøgle. Hvis B2 blev accepteret i stilhed, ville nøgler til gentagne forsøg blive usikre.

Samtidige duplikerede forespørgsler

Afsend to identiske forespørgsler med den samme nøgle på nøjagtig samme tidspunkt. Afhængigt af den dokumenterede adfærd udføres den ene, mens den anden modtager en igangværende konflikt – Nordlet returnerer 409 idempotency_in_progress – eller begge observerer i sidste ende det samme resultat.

Bekræft at begge kald ikke kan skabe uafhængige finansielle virkninger, at højst én nummertildeling finder sted, at en midlertidig konflikt forsøges igen med den samme nøgle i stedet for en ny, at den endelige ressource er komplet og kan læses, og at idempotensposten ikke sidder fast permanent.

Fejltype. Et bibliotek til nye forsøg, der opretter en frisk UUID pr. forsøg, omdanner én logisk handling til flere uafhængige skrivninger og ødelægger derved idempotensen fuldstændigt.

Det usikre udfald efter en afbrudt forbindelse

Dette er den absolut vigtigste produktionśimulering. Send en mutation med nøgle K, lad serveren gennemføre den, afbryd forbindelsen før svaret når frem, registrer udfaldet som ukendt, prøv derefter igen med den samme nøgle K og afstem ved at læse ressourcen og audit-dataene.

Bekræft at det nye forsøg returnerer det oprindelige eller det dokumenterede genafspilningssvar, at der kun findes præcis én finansiel sideeffekt, at klienten først markerer handlingen som fuldført efter en succesfuld genafspilning eller afstemningslæsning, og at der ikke genereres nogen ny nøgle. En timeout betyder ikke "ingenting skete". Stripe beskriver præcist idempotens som en beskyttelse mod forbindelsesfejl, hvor serveren kan have behandlet en mutation, før klienten nåede at modtage svaret.

En konservativ politik for nye forsøg

Beslutninger om at forsøge igen afhænger både af fejlen, og om handlingen er idempotent, ikke kun af HTTP-metoden alene.

Normalt forsøges igen, samme nøgle beholdes: forbindelsestab eller timeout efter en idempotent mutation, 408, 429 efter at have respekteret retry-after, samt 502/503/504. Et dokumenteret igangværende idempotens-svar kan forsøges igen efter en kort forsinkelse.

Forsøges ikke igen uden afstemning: 400/422-valideringsfejl, 401/403-godkendelsesfejl, 404 ved manglende ressource, forretningsmæssige 409-konflikter, der ikke relaterer sig til en igangværende nøgle, en ændret payload på en eksisterende nøgle og afvisning på grund af en låst periode.

Bekræft brugen af begrænset eksponentiel tilbagevenden (exponential backoff) med tilfældig spredning (jitter), et eksplicit maksimum af forsøg og tidsforbrug, overholdelse af retry-after for hastighedsgrænser, at den samme nøgle beholdes på tværs af forsøg for en enkelt handling, at der bruges en ny nøgle til hver ny handling, og logfiler der adskiller det oprindelige forsøg fra gentagne forsøg.

Test hastighedsbegrænsning (rate limiting) for sig selv. Overskrid den dokumenterede grænse – Nordlet tillader som standard 300 forespørgsler pr. minut pr. API-nøgle, og visse uauthentificerede endepunkter har deres egne lavere grænser pr. IP-adresse – og bekræft derefter, at serveren returnerer et svar om hastighedsbegrænsning, at klienten parser retry-after som en pause i stedet for en fejl, at den pauser i stedet for at hamre igennem, og at et begrænset mutationsforsøg genbruger den oprindelige nøgle. x-ratelimit-*-headere rapporterer det resterende budget, hvilket gør dem velegnede til forhåndskontrol. Hold hastighedsbegrænsningstests væk fra finansielle kontroller, medmindre din fixtur kan kende forskel på et begrænset forsøg og et gennemført et af slagsen.

Verificering af webhook-signaturer

Byg en modtager, der bevarer de rå bytes. For hver hændelse gælder det: indfang den rå body, aflæs x-nordlet-signature-headeren, beregn den forventede HMAC-SHA256 med abonnementshemmeligheden, sammenlign ved hjælp af en konstant-tids-funktion (constant-time function), parse JSON udelukkende efter verifikation, registrer leveringen, og returner en hurtig 2xx-status efter holdbar modtagelse. Nordlet signerer en HMAC over den rå body, sender den som sha256=<hex> og forsøger leverancer igen med eksponentiel tilbagevenden. Stripes webhook-vejledning understreger vigtigheden af at verificere den uændrede rå body med en konstant-tids-sammenligning.

Kør negative tests: korrekt body og hemmelighed, korrekt body med forkert hemmelighed, en ændring på én byte i bodyen, omserialiseret JSON med ændret hvidspace, en manglende header, en misdannet signatur, en genafspillet gammel levering, hvis systemet inkluderer et tidsstempel, og en gyldig signatur leveret til det forkerte abonnement.

Beståelseskriterier. Kun den korrekte rå body og hemmelighed accepteres. Ugyldige signaturer modtager en ikke-2xx-status. Ugyldige payloads kommer aldrig ind i regnskabskøen. Hemmeligheder holdes ude af almindelige logfiler. Håndteringen sender først en bekræftelse, når hændelsen er holdbart registreret.

Duplikerede og tidsmæssigt forkerte webhooks (out-of-order)

Leveringspålidelighed er et separat problem i forhold til API-idempotens, og modtageren skal også være idempotent. Lever den samme hændelse to gange, lever en sale_invoice.paid-hændelse før en sale_invoice.issued-hændelse, returner en 500-fejl efter vedholdende lagring, men før der svares, og genafspil en hændelse, som forbrugeren allerede har behandlet.

Bekræft at duplikerede leveringer ikke duplikerer betalinger, statusændringer eller kassekladdehandlinger, at dedubleringsnøglen bruger udbyderens leverings- eller hændelses-id, når et sådant findes (eller en dokumenteret sammensat nøgle, aldrig et vilkårligt tidsstempel), at hændelser i uorden aldrig overskriver nyere tilstand med ældre, at forbrugeren kan hente den aktuelle tilstand fra API'et, når rækkefølgen ikke er tilstrækkelig, og at mislykkede forbrugerforsøg sendes gennem en kø eller en dead-letter-sti. Stripe advarer eksplicit om, at leveringsrækkefølgen ikke er garanteret, og anbefaler, at man lagrer behandlede hændelses-id'er.

Hold endepunktet slankt: valider formen, verificer signaturen, gem eller sæt i kø, bekræft, returner 2xx. Afstemning og underretninger hører til i asynkron behandling. Test det ved at lade efterfølgende arbejde sove forbi leveringstouch-tiden; en korrekt modtager sender stadig en bekræftelse efter holdbar kø-håndtering.

Åbne og låste regnskabsperioder

Nordlet håndhæver periodelåse på bogføringstidspunktet på tværs af manuelle kassekladdeposter, dokumentflows og import, så test denne kontrol flere steder. Opret tilsvarende dokumenter dateret i en åben periode, i en låst periode, på grænsen lige før låsen, på den første dag i den næste åbne periode samt med en gyldig dokumentdato, men en ugyldig bogføringsdato, hvis API'et adskiller de to.

For tilfældet med en låst periode skal det bekræftes, at forespørgslen afvises med den dokumenterede periodelåsfejl – en 409 conflict i Nordlet – og at der ikke skrives nogen kassekladdelinjer, at der ikke forbruges noget dokumentnummer, at intet dokument skifter til bogført tilstand, og at der ikke udløses en succes-webhook. Versionen med en åben periode bør lykkes med de samme finansielle værdier.

Racetest. Start en bogføring mod en åben periode, lås perioden midt i forespørgslen, og bekræft, at gennemførelsen ikke kan omgå låsen. Det kritiske beståelseskriterium: En gennemført bogføring må aldrig lande i en periode, der var låst, før transaktionen blev gennemført.

Revisionsspor (auditability) og afstemning

For enhver succesfuld mutation skal du bekræfte, at forretningsobjektet eksisterer, at regnskabsposten eksisterer med debet lig med kredit, at audit-posten eksisterer, at webhook-hændelsen eksisterer eller kan hentes, og at din handlingspost peger på udbyderens objekt-id, hvor gentagne forsøg henviser til den samme logiske handling.

For enhver afvist mutation skal du bekræfte, at der ikke findes noget delvist dokument, at der ikke blev forbrugt nogen numre, medmindre kontrakten tillader reservation, at der ikke findes nogen finanspost, at der ikke findes nogen succes-webhook, og at fejlen bærer et forespørgsels-id til diagnosticering. Nordlets konventioner beskriver mutationsreviderbarhed og balancerede bogføringer som platformssuwænter, hvor balancen gennemtvinges af en udskudt databasetrigger på commit-tidspunktet i stedet for udelukkende af applikationskoden. Gør disse garantier til efterfølgende afstemningsforespørgsler i stedet for at stole blindt på HTTP-svaret.

Kernetestmatrix

Område Testhandling Forventet kontroludsagn Beståelseskriterium
Autorisering Ingen nøgle, ugyldig nøgle, utilstrækkeligt scope Struktureret 401/403; ingen sideeffekt Alle afviste forsøg skaber ingen regnskabspost
Skema og penge Ugyldig decimal, dato, påkrævet felt Felt-specifik valideringsfejl Intet nyt forsøg eller delvis skrivning forekommer
Normal bogføring Opret og udsted en faktura i en åben periode Én dokument, én balanceret kassekladde, én audit-post Tilstand ved læsning og kassekladde er enige
Genafspilning med samme nøgle Gentag identisk mutation, samme nøgle og indhold Oprindeligt resultat genafspilles; ingen duplikat Objekt-id, nummer, kassekladdevirkning, revision forbliver entydige
Ændret indhold, samme nøgle Genbrug nøgle med et andet beløb Dokumenteret afvisning ved nøglegenbrug Oprindelig post uændret; intet nyt skrevet
Afbrudt forbindelse Gennemfør, afbryd, prøv igen med samme nøgle Genafspillet resultat Prén præcis én finansiel sideeffekt
Låst periode Bogfør et dokument dateret i en låst periode Afvisning pga. periodelås Ingen kassekladde, intet nummer, ingen succes-webhook
Webhook-signatur Forkert hemmelighed, ændret body Ikke-2xx fra modtager Kun korrekt rå body og hemmelighed accepteres

Hvad jeg ville gøre først

Hvis tiden er knap, skal du køre testene i den rækkefølge, der fanger de dyreste fejl. Start med forsøget ved afbrudt forbindelse, fordi netop det enkelte scenarie frembringer de fleste virkelige duplikater. Derefter parret med samme nøgle og ændret indhold for idempotens. Dernæst låste perioder, da en bogføring i en lukket måned er et revisionsproblem, der dukker sent op. Signaturverifikation og tidsmæssigt forkerte webhooks kommer derefter, og hele skema- og autorisationsmatricen kan køre kontinuerligt i CI, når først klienten stabiliserer sig.

Alt andet i denne plan understøtter disse fem. Få dem til at lyse grønt mod en sandkassevirksomhed, hvor afstemningslæsninger bekræfter sideeffekterne, og du vil vide, at integrationen er sikker, før den rører ved et eneste rigtigt regnskab. Du kan oprette en sandkassevirksomhed og en begrænset testnøgle på få minutter fra Kom i gang, og tjekke hvilke moduler du har brug for via funktionslisten.

FAQ

Er et 2xx-svar nok til at bekræfte, at en regnskabsskrivning lykkedes?

Nej. En statuskode bekræfter blot, at serveren svarede, ikke at der findes præcis ét dokument, én nummertildeling og én balanceret kassekladde. Enhver mutationstest bør efterfølge svaret med en læsning af objektet, dets regnskabsmæssige virkning og dens audit-post. Det farlige tilfælde er den modsatte retning: en handling, der blev gennemført, uden at klienten nogensinde modtog svaret overhovedet.

Bør jeg generere en ny idempotensnøgle, når en forespørgsel får timeout?

Nej, og det er netop denne fejl, der forårsager de fleste produktionsduplikater. Nøglen identificerer den logiske forretningshandling, ikke netværksforsøget. Prøv igen med den samme nøgle, og afstem derefter ved at læse ressourcen. Et genforsøgsbibliotek, der opretter en frisk UUID pr. forsøg, omdanner én tiltænkt faktura til flere uafhængige skrivninger.

Hvad sker der, hvis jeg genbruger en idempotensnøgle med en anden payload?

En korrekt API afviser den i stedet for i stilhed at anvende det nye indhold. Nordlet returnerer 422 idempotency_key_reuse og lader den oprindelige post forblive uændret. Din klient bør betragte dette som en programmeringsfejl, der skal rettes, og ikke som en tilstand, der skal omgås ved at generere en ny nøgle.

Er webhooks en erstatning for at læse det oprettede objekt tilbage?

Nej. Webhook-levering beviser blot underliggende advisering og ikke, at transaktionen blev gennemført på den måde, du forventer, og leveringsrækkefølgen er ikke garanteret. Verificer signaturen over den rå body, dedupliker på leverings- eller hændelses-id'et, og hent den aktuelle tilstand fra API'et, når hændelsesrækkefølgen alene ikke er tilstrækkelig til at afgøre, hvad der ændrede sig.

Hvordan tester jeg bogføring i en låst regnskabsperiode?

Opret tilsvarende dokumenter i en åben periode og i en låst periode, og bekræft, at tilfældet med den låste periode afvises uden kassekladdelinjer, uden forbrugte dokumentnumre, uden tilstandsovergang og uden succes-webhook. Kør derefter race-versionen: start en bogføring mod en åben periode, og lås perioden midt i forespørgslen. En gennemført bogføring må aldrig lande i en periode, der var låst, før transaktionen blev gennemført.

Kan jeg køre højvolumen-duplikat-tests i en sandkassevirksomhed?

Ja. En sandkassevirksomhed opfører sig som en rigtig virksomhed, er markeret som testdata og slettes med det samme i stedet for efter opbevaringsperioden, hvilket gør den til det rette sted for destruktive og duplikerede tests. Sandkasseforbruget afregnes og måles stadig som rigtigt forbrug, så planlæg volumen i stedet for at køre i en uendelig løkke.