WebSockets

Alle code voor dit hoofdstuk vindt je hier

In dit hoofdstuk leren we hoe we WebSockets kunnen gebruiken om onze applicatie te verbeteren.

Projectsamenvatting

We hebben twee applicaties in onze pokercodebase.

  • Command line app. Vraagt de gebruiker om het aantal spelers in een spel in te voeren. Vanaf dat moment worden de spelers geĂŻnformeerd over de waarde van de "blind bet", die in de loop van de tijd toeneemt. Op elk moment kan een gebruiker "{Playername} wins" invoeren om het spel te voltooien en de winnaar in een store te registreren.

  • Web app. Stelt gebruikers in staat om winnaars van spellen te registreren en toont een ranglijst. Deelt dezelfde store als de command line app.

Volgende stappen

De product owner is enthousiast over de command line app, maar zou het beter vinden als we die functionaliteit naar de browser zouden brengen. Ze stelt zich een webpagina voor met een tekstvak waarmee de gebruiker het aantal spelers kan invoeren. Wanneer de gebruiker het formulier verzendt, toont de pagina de blinde waarde en werkt deze automatisch bij wanneer dat nodig is. Net als bij de commandline-applicatie kan de gebruiker de winnaar aankondigen en deze wordt opgeslagen in de database.

Op het eerste gezicht klinkt het vrij eenvoudig, maar zoals altijd moeten we de nadruk leggen op een iteratieve aanpak bij het schrijven van software.

Eerst moeten we HTML aanbieden. Tot nu toe hebben al onze HTTP-eindpunten platte tekst of JSON geretourneerd. We zouden dezelfde technieken kunnen gebruiken die we kennen (aangezien het uiteindelijk allemaal strings zijn), maar we kunnen ook het pakket html/template gebruiken voor een schonere oplossing.

We moeten ook asynchroon berichten naar de gebruiker kunnen sturen met de tekst The blind is now *y* zonder de browser te hoeven vernieuwen. We kunnen WebSockets gebruiken om dit te vergemakkelijken.

WebSocket is een computercommunicatieprotocol dat full-duplex communicatiekanalen biedt via één TCP-verbinding.

Aangezien we verschillende technieken gebruiken, is het des te belangrijker dat we dit, zoals altijd, aanpakken met verschillende iteraties.

Daarom maken we eerst een webpagina met een formulier waarmee de gebruiker een winnaar kan registreren. In plaats van een standaardformulier te gebruiken, gebruiken we WebSockets om die gegevens naar onze server te sturen, zodat deze kunnen worden geregistreerd.

Daarna werken we aan de blinde meldingen, waarna we een stukje infrastructuurcode hebben opgezet.

Hoe zit het met tests voor de JavaScript?

Er zal wat JavaScript geschreven worden om dit te doen, maar ik ga niet in op het schrijven van tests.

Het is natuurlijk mogelijk, maar om het kort te houden zal ik er geen uitleg over geven.

Sorry mensen. Vraag O'Reilly om me te betalen voor het maken van een "Leer JavaScript met tests".

Schrijf eerst de test

Het eerste wat we moeten doen, is wat HTML aan gebruikers aanbieden wanneer ze op /game klikken.

Hier is een herinnering aan de relevante code op onze webserver

Het eenvoudigste wat we nu kunnen doen is controleren of we bij GET /game een 200 krijgen.

Probeer de test uit te voeren

Schrijf voldoende code om de test te laten slagen

Onze server is voorzien van een router, dus het is relatief eenvoudig op te lossen.

Voeg toe aan onze router

Schrijf vervolgens de game methode

Refactor

De servercode is al prima, omdat we heel gemakkelijk meer code in de bestaande, goed gefactoriseerde code kunnen inpassen.

We kunnen de test wat opschonen door een testhulpfunctie toe te voegen: newGameRequest, die de aanvraag naar /game stuurt. Probeer dit zelf maar eens te schrijven.

Je zult ook merken dat ik assertStatus heb aangepast om response te accepteren in plaats van response.Code, omdat ik vind dat dat beter leest.

Nu moeten we het eindpunt wat HTML laten retourneren, hier is de HTML code.

We hebben een heel eenvoudige webpagina

  • Een tekstinvoer waarmee de gebruiker de winnaar kan invoeren

  • Een knop waarop de gebruiker kan klikken om de winnaar bekend te maken.

  • Wat JavaScript om een WebSocket-verbinding met onze server te openen en het indrukken van de verzendknop te verwerken

WebSocket is ingebouwd in de meeste moderne browsers, dus we hoeven ons geen zorgen te maken over het toevoegen van bibliotheken. De webpagina werkt niet in oudere browsers, maar voor dit scenario is dat geen probleem.

Hoe testen we of we de juiste markup retourneren?

Er zijn verschillende manieren. Zoals in het boek al benadrukt, is het belangrijk dat de tests die je schrijft voldoende waarde hebben om de kosten te rechtvaardigen.

  1. Schrijf een browsergebaseerde test met bijvoorbeeld Selenium. Deze tests zijn de meest "realistische" van alle benaderingen, omdat ze een echte webbrowser starten en een gebruiker simuleren die ermee communiceert. Deze tests kunnen je veel vertrouwen geven dat je systeem werkt, maar zijn moeilijker te schrijven dan unittests en veel langzamer om uit te voeren. Voor ons product is dit overdreven.

  2. Voer een exacte stringmatch uit. Dit kan wel goed zijn, maar dit soort tests zijn uiteindelijk erg kwetsbaar. Zodra iemand de markup wijzigt, mislukt een test, terwijl er in de praktijk niets echts kapot is.

  3. Controleer of we de juiste template aanroepen. We gebruiken een templatebibliotheek uit de standaardbibliotheek om de HTML te serveren (hierover later meer). We kunnen thing injecteren om de HTML te genereren en de aanroep ervan te controleren om te controleren of we het goed doen. Dit zou een impact hebben op het ontwerp van onze code, maar test niet veel; behalve dat we het aanroepen met het juiste templatebestand. Aangezien we maar één template in ons project zullen hebben, lijkt de kans op falen hier klein.

Dus in het boek "Leer Go met Tests" gaan we voor het eerst geen test schrijven.

Zet de markup in een bestand met de naam game.html.

Vervolgens wijzigen we het eindpunt dat we zojuist hebben geschreven naar het volgende:

html/template is een Go-pakket voor het maken van HTML. In ons geval roepen we template.ParseFiles aan, met het pad naar ons HTML-bestand. Ervan uitgaande dat er geen fout is, kun je de template uitvoeren, die deze naar een io.Writer schrijft. In ons geval willen we dat deze naar het internet schrijft, dus geven we hem onze http.ResponseWriter.

Omdat we geen test hebben geschreven, is het verstandig om onze webserver handmatig te testen om er zeker van te zijn dat alles werkt zoals we hopen. Ga naar cmd/webserver en voer het bestand main.go uit. Ga naar http://localhost:5000/game.

Je zou een foutmelding moeten krijgen dat je de template niet kon vinden. Je kunt het pad relatief maken ten opzichte van je map, of je kunt een kopie van 'game.html' in de map 'cmd/webserver' plaatsen. Ik heb ervoor gekozen om een symbolische link ('ln -s ../../game.html game.html') te maken naar het bestand in de root van het project, zodat eventuele wijzigingen worden doorgevoerd wanneer de server draait.

Als je deze wijziging aanbrengt en de server opnieuw start, zou je onze gebruikersinterface moeten zien.

Nu moeten we testen of we een string die via een WebSocket-verbinding met onze server wordt verzonden, kunnen uitroepen tot winnaar van een spel.

Schrijf eerst de test

Voor het eerst gaan we een externe bibliotheek gebruiken om met WebSockets te kunnen werken.

Voer go get github.com/gorilla/websocket uit.

Hiermee wordt de code voor de uitstekende Gorilla WebSocket-bibliotheek opgehaald. Nu kunnen we onze tests bijwerken voor onze nieuwe vereiste.

Zorg ervoor dat je een import hebt voor de websocket-bibliotheek. Mijn IDE deed dit automatisch voor me, dat zou die van jou dus ook moeten kunnen.

Om te testen wat er vanuit de browser gebeurt, moeten we onze eigen WebSocket-verbinding openen en ernaar schrijven.

Onze eerdere tests op onze server riepen alleen methoden aan op onze server, maar nu hebben we een permanente verbinding met onze server nodig. Hiervoor gebruiken we httptest.NewServer, die een http.Handler gebruikt en deze opstart en luistert naar verbindingen.

Met websocket.DefaultDialer.Dial proberen we in te bellen op onze server en vervolgens proberen we een bericht te versturen met onze winnaar.

Tot slot bevestigen we de speleropslag om te controleren of de winnaar is geregistreerd.

Probeer de test uit te voeren

We hebben onze server nog niet aangepast om WebSocket-verbindingen op /ws te accepteren, dus we schudden elkaar nog niet de hand.

Schrijf voldoende code om het te laten werken

Voeg nog een vermelding toe aan onze router

Voeg vervolgens onze nieuwe webSocket-handler toe

Om een WebSocket-verbinding te accepteren, upgraden we het verzoek. Als je de test nu opnieuw uitvoert, krijg je de volgende fout.

Nu de verbinding is geopend, willen we luisteren naar een bericht en dit vervolgens vastleggen als winnaar.

(Ja, we negeren momenteel veel fouten!)

conn.ReadMessage() blokkeert het wachten op een bericht op de verbinding. Zodra we er een ontvangen, gebruiken we het om RecordWin te gebruiken. Dit zou de WebSocket-verbinding definitief sluiten.

Als je de test probeert uit te voeren, mislukt deze nog steeds.

Het probleem zit in de timing. Er zit een vertraging tussen het moment waarop onze WebSocket-verbinding het bericht leest en de win vastlegt, en onze test is voltooid voordat dit gebeurt. Je kunt dit testen door een korte time.Sleep voor de laatste bewering te plaatsen.

Laten we dat voorlopig zo houden, maar we erkennen dat het gebruiken van willekeurige slaapstanden in tests een zeer slechte gewoonte is.

Refactor

We hebben veel fouten gemaakt om deze test te laten werken, zowel in de servercode als in de testcode, maar onthoud dat dit voor ons de makkelijkste manier is om te werken.

We hebben vervelende, vreselijke, werkende software die wordt ondersteund door een test, dus nu kunnen we het goed maken en weten we dat we niets per ongeluk kapotmaken.

Laten we beginnen met de servercode.

We kunnen de upgrader naar een privéwaarde in ons pakket verplaatsen, omdat we deze niet bij elke WebSocket-verbindingsaanvraag opnieuw hoeven te declareren.

Onze aanroep van template.ParseFiles("game.html") wordt uitgevoerd bij elke GET /game, wat betekent dat we bij elke aanvraag naar het bestandssysteem gaan, ook al hoeven we de template niet opnieuw te parsen. Laten we onze code zo aanpassen dat we de template één keer parsen in NewPlayerServer. We moeten ervoor zorgen dat deze functie nu een foutmelding kan retourneren als er problemen zijn met het ophalen van de template van schijf of het parsen ervan.

Hier zijn de relevante wijzigingen aan PlayerServer

Door de signatuur van NewPlayerServer te wijzigen, hebben we nu compilatieproblemen. Probeer ze zelf op te lossen of raadpleeg de broncode als je er moeite mee hebt.

Voor de testcode heb ik een helper gemaakt genaamd mustMakePlayerServer(t *testing.T, store PlayerStore) *PlayerServer, zodat ik de foutmeldingen kon verbergen voor de tests.

Op dezelfde manier heb ik nog een helper aangemaakt: mustDialWS, zodat ik vervelende foutmeldingen kon verbergen bij het aanmaken van de WebSocket-verbinding.

Ten slotte kunnen we in onze testcode een helper creëren om het verzenden van berichten op te ruimen

Nu de tests succesvol zijn, probeer de server te starten en een aantal winnaars te benoemen in /game. Je zou ze moeten zien in /league. Onthoud dat we elke keer dat we een winnaar hebben de verbinding sluiten. Je moet de pagina vernieuwen om de verbinding weer te openen.

We hebben een eenvoudig webformulier gemaakt waarmee gebruikers de winnaar van een spel kunnen registreren. Laten we dit itereren zodat de gebruiker een spel kan starten door een aantal spelers op te geven. De server zal dan berichten naar de client sturen met informatie over de blindwaarde naarmate de tijd verstrijkt.

Werk eerst game.html bij om onze client-side code bij te werken aan de nieuwe vereisten.

De belangrijkste veranderingen zijn de toevoeging van een sectie om het aantal spelers in te voeren en een sectie om de blindwaarde weer te geven. We hebben een beetje logica om de gebruikersinterface te tonen/verbergen, afhankelijk van de fase van het spel.

Elk bericht dat we ontvangen via conn.onmessage, nemen we aan als blinde meldingen en daarom stellen we de blindContainer.innerText dienovereenkomstig in.

Hoe versturen we de blinde meldingen? In het vorige hoofdstuk introduceerden we het idee van Game, zodat onze CLI-code een Game kon aanroepen en al het andere zou worden geregeld, inclusief het plannen van blinde meldingen. Dit bleek een goede scheiding van aandachtspunten te zijn.

Wanneer de gebruiker in de CLI werd gevraagd om het aantal spelers, werd het spel Start, wat de blinde waarschuwingen activeerde. Wanneer de gebruiker de winnaar bekendmaakte, werd het spel Finish. Dit zijn dezelfde vereisten als nu, alleen een andere manier om de invoer te verkrijgen; we zouden dit concept dus moeten hergebruiken als dat mogelijk is.

Onze "echte" implementatie van Game is TexasHoldem.

Door een BlindAlerter in te sturen kan TexasHoldem blinde waarschuwingen plannen die naar waar dan ook worden verzonden

En ter herinnering, hier is onze implementatie van de BlindAlerter die we gebruiken in de CLI.

Dit werkt in de CLI omdat we de waarschuwingen altijd naar os.Stdout willen sturen, maar dit werkt niet voor onze webserver. Voor elke aanvraag ontvangen we een nieuwe http.ResponseWriter, die we vervolgens upgraden naar *websocket.Conn. We kunnen dus niet weten waar onze waarschuwingen naartoe moeten tijdens het samenstellen van onze afhankelijkheden.

Daarom moeten we BlindAlerter.ScheduleAlertAt aanpassen, zodat deze een bestemming voor de waarschuwingen krijgt, zodat we deze opnieuw kunnen gebruiken op onze webserver.

Open blind_alerter.go en voeg de parameter toe aan io.Writer

Het idee van een StdoutAlerter past niet in ons nieuwe model, dus hernoemen we het gewoon naar Alerter

Als je probeert te compileren, mislukt het in TexasHoldem omdat het ScheduleAlertAt aanroept zonder bestemming. Om de boel voorlopig weer te laten compileren, hardcodeer je het naar os.Stdout.

Probeer de tests uit te voeren en ze mislukken omdat SpyBlindAlerter BlindAlerter niet meer implementeert. Los dit op door de handtekening van ScheduleAlertAt bij te werken. Voer de tests uit en we zouden nog steeds groen moeten zijn.

Het heeft geen zin dat TexasHoldem weet waar blinde waarschuwingen naartoe moeten worden gestuurd. Laten we nu Game bijwerken, zodat je bij het starten van een spel aangeeft waar de waarschuwingen naartoe moeten.

Laat de compiler je vertellen wat je moet aanpassen. De verandering is niet zo ingewikkeld:

  • Werk TexasHoldem bij zodat Game correct wordt geĂŻmplementeerd.

  • Geef in CLI, wanneer we het spel starten, onze out-eigenschap (cli.game.Start(numberOfPlayers, cli.out)) mee.

  • In de test van TexasHoldem gebruik ik game.Start(5, io.Discard) om het compilatieprobleem op te lossen en de waarschuwingsuitvoer zo in te stellen dat deze wordt verwijderd.

Als je alles goed hebt, zou alles groen moeten zijn! Nu kunnen we Game binnen Server proberen te gebruiken.

Schrijf eerst de test

De vereisten van CLI en Server zijn hetzelfde! Alleen het aflevermechanisme is anders.

Laten we ter inspiratie eens kijken naar onze CLI-test.

Het lijkt erop dat we een vergelijkbaar resultaat kunnen testen met GameSpy.

Vervang de oude websocket-test door het volgende:

  • Zoals besproken maken we een spion Game aan en geven deze door aan mustMakePlayerServer (zorg ervoor dat de helper dit ondersteunt).

  • Vervolgens sturen we de websocketberichten voor een game.

  • Ten slotte bevestigen we dat de game is gestart en voltooid met wat we verwachten.

Probeer de test uit te voeren

Je zult een aantal compilatiefouten rond mustMakePlayerServer tegenkomen in andere tests. Introduceer een niet-geëxporteerde variabele dummyGame en gebruik deze in alle tests die niet gecompileerd worden.

De laatste fout is wanneer we proberen Game door te geven aan NewPlayerServer, maar deze ondersteunt dit nog niet

Schrijf de minimale hoeveelheid code om de test uit te voeren en controleer de mislukte testuitvoer.

Voeg het voorlopig gewoon als argument toe om de test uit te voeren.

Eindelijk!

Schrijf voldoende code om het te laten slagen

We moeten Game als veld toevoegen aan PlayerServer, zodat het gebruikt kan worden wanneer het verzoeken ontvangt.

(We hebben al een methode genaamd game, dus hernoem die naar playGame)

Laten we deze vervolgens toewijzen in onze constructor

Hoe kunnen we onze Game gebruiken binnen webSocket.

Hoera! De tests zijn geslaagd.

We gaan de blinde berichten nog nergens naartoe sturen, want daar moeten we nog even over nadenken. Wanneer we game.Start aanroepen, sturen we io.Discard mee, die alle berichten die erop geschreven worden gewoon weggooit.

Start nu de webserver op. Je moet main.go bijwerken om een Game door te geven aan de PlayerServer

Afgezien van het feit dat we nog geen blinde meldingen ontvangen, werkt de app wel! We zijn erin geslaagd om Game te hergebruiken met PlayerServer en alles is tot in de puntjes geregeld. Zodra we erachter komen hoe we onze blinde meldingen naar de websockets kunnen sturen in plaats van ze te verwijderen, zou alles moeten werken.

Maar laten we eerst wat code opschonen.

Refactor

De manier waarop we WebSockets gebruiken is vrij eenvoudig en de foutafhandeling is vrij naĂŻef, dus ik wilde dat in een type vastleggen om die rommel uit de servercode te halen. We willen er later misschien nog op terugkomen, maar voor nu ruimt dit de boel wat op.

Nu is de servercode een beetje vereenvoudigd

Zodra we erachter komen hoe we de blinde berichten niet moeten weggooien, zijn we klaar.

Laten we geen test schrijven!

Soms, als we niet zeker weten hoe we iets moeten doen, is het het beste om gewoon wat te experimenteren en dingen uit te proberen! Zorg ervoor dat je werk eerst gecommit is, want zodra we een manier hebben gevonden, moeten we het door een test halen.

De problematische regel code die we hebben is

We moeten een io.Writer doorgeven aan de game om de blind alerts naartoe te schrijven.

Zou het niet handig zijn als we onze playerServerWS van voorheen konden doorgeven? Het is onze wrapper rond onze WebSocket, dus het voelt alsof we die naar onze Game zouden moeten kunnen sturen om berichten naar te sturen.

Probeer het eens:

De compiler klaagt

Het lijkt voor de hand liggend om ervoor te zorgen dat playerServerWS io.Writer implementeert. Om dit te doen gebruiken we de onderliggende *websocket.Conn om WriteMessage te gebruiken om het bericht via de websocket te versturen.

Dit lijkt te makkelijk! Probeer de applicatie te starten en kijk of het werkt.

Bewerk eerst TexasHoldem zodat de blinde incrementtijd korter is, zodat je het in actie kunt zien.

Je zou het moeten zien werken! De blinde hoeveelheid neemt als bij toverslag toe in de browser.

Laten we nu de code terugdraaien en bedenken hoe we die kunnen testen. Om het te implementeren hebben we alleen playerServerWS doorgegeven aan StartGame in plaats van io.Discard, dus je zou kunnen denken dat we de aanroep moeten bespioneren om te controleren of deze werkt.

Spioneren is geweldig en helpt ons implementatiedetails te controleren, maar we moeten altijd proberen om het echte gedrag te testen als dat mogelijk is, want wanneer je besluit te refactoren, zijn het vaak spionagetests die mislukken, omdat ze meestal implementatiedetails controleren die je probeert te wijzigen.

Onze test opent momenteel een websocketverbinding met onze actieve server en verstuurt berichten om deze te laten werken. Op dezelfde manier zouden we de berichten moeten kunnen testen die onze server via de websocketverbinding terugstuurt.

Schrijf eerst de test

We gaan onze bestaande test bewerken.

Momenteel stuurt onze GameSpy geen gegevens naar out wanneer je Start aanroept. We moeten dit aanpassen zodat we het kunnen configureren om een standaardbericht te versturen en vervolgens kunnen controleren of dat bericht naar de websocket wordt verzonden. Dit zou ons de zekerheid moeten geven dat we alles correct hebben geconfigureerd en tegelijkertijd het gewenste gedrag vertonen.

Voeg het veld BlindAlert toe.

Werk GameSpy Start bij om het standaardbericht naar out te sturen.

Dit betekent nu dat wanneer we PlayerServer gebruiken om het spel te Starten, er berichten via de websocket moeten worden verzonden als alles goed werkt.

Ten slotte kunnen we de test bijwerken.

  • We hebben een wantedBlindAlert toegevoegd en onze GameSpy geconfigureerd om deze naar out te sturen als Start wordt aangeroepen.

  • We hopen dat het via de websocketverbinding wordt verzonden, dus hebben we een aanroep naar ws.ReadMessage() toegevoegd om te wachten tot er een bericht is verzonden en vervolgens te controleren of het het verwachte bericht is.

Probeer de test uit te voeren

Je zou moeten zien dat de test permanent vastloopt. Dit komt doordat ws.ReadMessage() blokkeert totdat er een bericht wordt ontvangen, wat nooit gebeurt.

Schrijf de minimale hoeveelheid code voor de test om uit te voeren en controleer de mislukte testuitvoer.

We zouden nooit tests moeten hebben die vastlopen, dus laten we een manier introduceren om code af te handelen waarvan we een time-out willen.

Wat within doet, is de functie assert als argument gebruiken en deze vervolgens in een go-routine uitvoeren. Als/wanneer de functie klaar is, geeft deze via het done-kanaal aan dat dit is voltooid.

Terwijl dat gebeurt, gebruiken we een select-statement waarmee we kunnen wachten tot een kanaal een bericht verzendt. Vanaf hier is het een race tussen de assert-functie en time.After, die een signaal verzendt wanneer de duur is verstreken.

Tot slot heb ik een hulpfunctie voor onze assertie gemaakt, om het wat overzichtelijker te maken.

Dit is hoe de test er nu uitziet:

Als je de test nu uitvoert...

Schrijf voldoende code om het te laten slagen

Ten slotte kunnen we nu onze servercode aanpassen, zodat deze onze WebSocket-verbinding naar het spel stuurt wanneer het start.

Refactor

De servercode was een heel kleine wijziging, dus er valt hier niet veel te veranderen, maar de testcode heeft nog steeds een time.Sleep-aanroep omdat we moeten wachten tot onze server zijn werk asynchroon uitvoert.

We kunnen onze helpers assertGameStartedWith en assertFinishCalledWith refactoren, zodat ze hun beweringen korte tijd opnieuw kunnen proberen voordat ze mislukken.

Hieronder lees je hoe je dit kunt doen voor assertFinishCalledWith. Je kunt dezelfde aanpak gebruiken voor de andere helper.

Hier zie je hoe retryUntil is gedfinieerd

Samenvattend

Onze applicatie is nu compleet. Een pokerspel kan worden gestart via een webbrowser en gebruikers worden via WebSockets geĂŻnformeerd over de waarde van de blinde inzet. Na afloop van het spel kunnen ze de winnaar vastleggen, die wordt bijgehouden met behulp van code die we een paar hoofdstukken geleden hebben geschreven. De spelers kunnen achterhalen wie de beste (of gelukkigste) pokerspeler is met behulp van het /league-eindpunt op de website.

Tijdens de reis hebben we fouten gemaakt, maar met de TDD-flow zijn we nooit ver verwijderd geweest van werkende software. We hadden de vrijheid om te blijven itereren en experimenteren.

Het laatste hoofdstuk blikt terug op de aanpak, het ontwerp waar we toe zijn gekomen en lost een aantal losse eindjes op.

We hebben in dit hoofdstuk een aantal dingen behandeld:

WebSockets

  • Een handige manier om berichten te versturen tussen clients en servers, waarbij de client de server niet hoeft te blijven pollen. Zowel de client- als de servercode die we hebben, is heel eenvoudig.

  • Triviaal om te testen, maar je moet rekening houden met het asynchrone karakter van de tests.

Code verwerken in tests die vertraagd kan zijn of nooit kan worden voltooid.

  • Hulpfuncties creĂ«ren om beweringen opnieuw te proberen en time-outs toe te voegen.

  • We kunnen go-routines gebruiken om ervoor te zorgen dat de beweringen niets blokkeren en vervolgens kanalen gebruiken om aan te geven of ze al dan niet voltooid zijn.

  • Het time-pakket heeft een aantal handige functies die ook signalen via kanalen over gebeurtenissen in de tijd verzenden, zodat we time-outs kunnen instellen.

Laatst bijgewerkt