Componenten testen in Reageren met Jest de basisprincipes

Wat je gaat creëren

Testcode is voor veel ontwikkelaars een verwarrende praktijk. Dat is begrijpelijk omdat het schrijven van tests meer inspanning, tijd en de mogelijkheid vereist om mogelijke gebruikscasussen te voorzien. Startups en ontwikkelaars die aan kleinere projecten werken, geven meestal de voorkeur aan het negeren van tests vanwege het gebrek aan middelen en mankracht. 

Er zijn echter een aantal redenen waarom ik van mening ben dat u uw componenten moet testen:

  1. Het geeft je meer zelfvertrouwen over je code.
  2. Tests verbeteren uw productiviteit.

Reageren is ook niet anders. Wanneer uw hele toepassing begint te veranderen in een stapel componenten die moeilijk te onderhouden zijn, biedt testen stabiliteit en consistentie. Het schrijven van tests vanaf de eerste dag zal u helpen betere code te schrijven, bugs met gemak te herkennen en een betere ontwikkelingsworkflow te behouden. 

In dit artikel zal ik u alles vertellen dat u moet weten om tests voor uw React-componenten te schrijven. Ik zal ook enkele van de best practices en technieken behandelen terwijl we bezig zijn. Laten we beginnen!

Componenten testen in React

Testen is het proces om te verifiëren dat onze test beweringen waar zijn en dat ze gedurende de hele levensduur van de applicatie waar blijven. Een testbevestiging is een booleaanse expressie die true retourneert, tenzij er een bug in uw code voorkomt. 

Een bewering kan bijvoorbeeld zo simpel zijn als deze: "Wanneer de gebruiker navigeert naar /Log in, een modaal met het ID #Log in moet worden gerenderd. "Dus als blijkt dat je op een of andere manier de inlogcomponent hebt verknoeid, zou de bewering onjuist zijn. Beweringen zijn niet alleen beperkt tot wat wordt weergegeven - je kunt ook beweringen doen over hoe de toepassing reageert op gebruikersinteracties en andere acties. 

Er zijn veel geautomatiseerde teststrategieën die front-end ontwikkelaars gebruiken om hun code te testen. We zullen onze discussie beperken tot slechts drie softwaretestparadigma's die populair zijn bij React: unit testing, functioneel testen en integratietesten.

Testen van een eenheid

Het testen van eenheden is een van de testveteranen die nog steeds populair is in testcirkels. Zoals de naam al doet vermoeden, test u afzonderlijke stukjes code om te controleren of ze onafhankelijk werken zoals verwacht. Vanwege de componentenarchitectuur van React, zijn unit tests een natuurlijke match. Ze zijn ook sneller omdat u niet hoeft te vertrouwen op een browser.

Eenheidstests helpen u om elk onderdeel afzonderlijk te beschouwen en behandelen ze als functies. De tests van uw apparaat voor een bepaald onderdeel moeten de volgende vragen beantwoorden:

  1. Zijn er rekwisieten? Zo ja, wat doet het ermee??
  2. Welke componenten worden weergegeven? 
  3. Moet het een staat hebben? Wanneer of hoe moet het de staat bijwerken?
  4. Is er een procedure die moet worden gevolgd wanneer deze wordt geactiveerd of gedeactiveerd of wanneer de gebruiker interactie heeft??

Functioneel testen

Functionele tests worden gebruikt om het gedrag van een deel van uw toepassing te testen. Functionele tests worden meestal geschreven vanuit het perspectief van een gebruiker. Een stuk functionaliteit is meestal niet beperkt tot een enkele component. Het kan een volledig formulier zijn of een hele pagina. 

Wanneer u bijvoorbeeld een aanmeldingsformulier aan het maken bent, kan dit componenten voor de formulierelementen, de waarschuwingen en eventuele fouten bevatten. Het onderdeel dat wordt weergegeven nadat het formulier is ingediend, maakt ook deel uit van die functionaliteit. Dit vereist geen browser-renderer, omdat we een virtuele DOM in het geheugen zullen gebruiken voor onze tests.

Integratie testen

Integratietesten is een teststrategie waarbij alle afzonderlijke componenten als een groep worden getest. Geïntegreerde tests proberen de gebruikerservaring te repliceren door de tests uit te voeren op een echte browser. Dit is aanzienlijk langzamer dan functionele testen en unit tests, omdat elke testsuite wordt uitgevoerd op een live browser. 

In React zijn unit tests en functionele tests populairder dan integratietests omdat ze gemakkelijker te schrijven en te onderhouden zijn. Dat is wat we in deze tutorial zullen behandelen.

Ken je hulpmiddelen 

U hebt bepaalde hulpmiddelen en afhankelijkheden nodig om aan de slag te gaan met het testen van de eenheid en het functioneel testen van uw React-toepassing. Ik heb ze hieronder opgesomd.

Jest Test Framework

Jest is een testraamwerk dat een nulconfiguratie vereist en daarom eenvoudig is in te stellen. Het is populairder dan testkaders zoals Jasmine en Mocha omdat het is ontwikkeld door Facebook. Jest is ook sneller dan de rest omdat het een slimme techniek gebruikt om testruns over werknemers heen te parallelliseren. Afgezien daarvan loopt elke test in een sandbox-omgeving om conflicten tussen twee opeenvolgende tests te voorkomen. 

Als je create-react-app gebruikt, wordt deze geleverd met Jest. Als dit niet het geval is, moet u mogelijk Jest en een paar andere afhankelijkheden installeren. Je kunt er meer over lezen op de officiële Jest-documentatiepagina. 

reactie test-renderer

Zelfs als je create-react-app gebruikt, moet je dit pakket installeren om snapshots te maken. Het testen van foto's is een onderdeel van de Jest-bibliotheek. Dus in plaats van de UI van de volledige toepassing weer te geven, kunt u de testrenderer gebruiken om snel een serialiseerbare HTML-uitvoer van de virtuele DOM te genereren. U kunt het als volgt installeren:

garen voeg react-test-renderer toe

ReactTestUtils en Enzyme

reactie-dom / test-utils bestaat uit enkele van de testvoorzieningen die door het React-team worden aangeboden. Je kunt ook het Enzyme-pakket gebruiken dat is vrijgegeven door Airbnb. Enzym is een stuk beter dan ReactTestUtils omdat het eenvoudig is om de uitvoer van uw React Components te beweren, te manipuleren en te doorkruisen. We beginnen onze testen met React utils en gaan later over naar Enzyme.

Om Enzyme te installeren, voert u de volgende opdracht uit.

garen enzym enzym-adapter-react-16 toevoegen

Voeg de code toe aan src / SetupTests.js.

importeer configure van 'enzyme'; import Adapter van 'enzyme-adapter-react-16'; configureren (adapter: nieuwe adapter ());

Meer informatie hierover vindt u in het gedeelte Testcomponenten van de pagina create-react-app. 

Een demo-app opzetten en testen organiseren

We schrijven tests voor een eenvoudige demotoepassing die een hoofd- / detailweergave van een lijst met producten weergeeft. Je vindt de demotoepassing in onze GitHub-repo. De applicatie bestaat uit een containercomponent die bekend staat als ProductContainer en drie presentatiesystemen: Product lijst, Productdetails, en ProductHeader

Directorystructuur

. ├── package-lock.json ├── package.json ├── public │ ├── index.html │ └── manifest.json ├── src │ ├── componenten │ │ ├── App.js │ │ ├── ProductContainer.js │ │ ├── ProductDetails.jsx │ │ ├── ProductHeader.js │ │ ├── ProductList.jsx │ ├── index.js │ └── style.css

Deze demo is een goede kandidaat voor unit testing en functioneel testen. U kunt elk onderdeel afzonderlijk testen en / of de productvermeldingsfunctionaliteit als geheel testen. 

Nadat u de demo hebt gedownload, maakt u een map met de naam __tests__binnen / Src / components /. U kunt vervolgens alle testbestanden met betrekking tot deze functionaliteit opslaan in de __tests__ directory. Testers noemen hun testbestanden meestal ook een van beide .spec.js of .test.js-bijvoorbeeld, ProductHeader.test.js of ProductHeader.spec.js

Basistests schrijven in React

Maak een ProductHeader.test.js bestand als je dat nog niet hebt gedaan. Dit is wat onze tests er in feite als gaan uitzien:

src / components / __ testen __ / ProductList.test.js

beschrijven ('ProductHeader', () => it ('passing test', () => expect (true) .toBeTruthy ();) it ('failing test', () => expect (false) .toBeTruthy ();))

De testsuite begint met een beschrijven blok, wat een globale Jest-functie is die twee parameters accepteert. De eerste parameter is de titel van de testsuite en de tweede parameter is de daadwerkelijke implementatie. Elk het() in een testsuite komt overeen met een test of een spec. Een test bevat een of meer verwachtingen die de status van de code controleren. 

verwacht (true) .toBeTruthy (); 

In Jest is een verwachting een bewering die ofwel waar of onwaar retourneert. Als alle beweringen in een specificatie waar zijn, wordt er gezegd dat ze slagen. Anders zou de test falen.

We hebben bijvoorbeeld twee testspecificaties gemaakt. De eerste moet vanzelfsprekend voorbijgaan en de tweede moet falen. 

Notitie: toBeTruthy () is een vooraf gedefinieerde matcher. In Jest maakt elke matcher een vergelijking tussen de verwachte waarde en de werkelijke waarde en retourneert een boolean. Er zijn veel meer matchers beschikbaar, en we zullen ze in een oogwenk bekijken.

De testsuite uitvoeren

create-react-app heeft alles ingesteld dat je nodig hebt om de testsuite uit te voeren. Het enige wat u hoeft te doen is het volgende commando uitvoeren:

garen test

Je zou zoiets als dit moeten zien:

Als u de test wilt laten mislukken, moet u de toBeTruthy () matcher met toBeFalsy ().

verwacht (false) .toBeFalsy ();

Dat is het!

Matchers gebruiken in Jest

Zoals eerder vermeld, gebruikt Jest matchers om waarden te vergelijken. Je kunt het gebruiken om gelijkheid te controleren, twee getallen of strings te vergelijken en de juistheid van uitdrukkingen te verifiëren. Hier is de lijst met populaire matchers beschikbaar in Jest. 

  • zijn();
  • toBeNull ()
  • worden gedefinieerd()
  • toBeUndefined ()
  • toBeTruthy ()
  • toBeFalsy ()
  • toBeGreaterThan ()
  • toBeLesserThan ()
  • toMatch ()
  • toContain ()

Dit is maar een voorproefje. U vindt alle beschikbare overeenkomsten in de referentiedocumenten.

Een reactiekomponent testen

Eerst zullen we een paar tests schrijven voor de ProductHeader component. Open de ProductHeader.js bestand als je dat nog niet hebt gedaan. 

src / components / ProductHeader.js

import Reageren, Component uit 'reageren'; class ProductHeader breidt component render () terug ( 

Pagina met productvermeldingen

); ; export standaard ProductHeader;

Ben je benieuwd waarom ik hier een klassencomponent heb gebruikt in plaats van een functionele component? De reden is dat het moeilijker is om functionele componenten te testen met ReactTestUtils. Als je nieuwsgierig bent naar waarom, heeft deze Stack Overflow-discussie het antwoord.

We zouden een test kunnen schrijven met de volgende aannames:

  1. Het onderdeel moet een h2 label.
  2. De h2 tag moet een klasse hebben met de naam titel.

Om een ​​component te renderen en om relevante DOM-knooppunten op te halen, hebben we ReactTestUtils nodig. Verwijder de dummyspecificaties en voeg de volgende code toe:

src / components / __ testen __ / ProductHeader.test.js

import Reageren van 'reageren'; import ReactTestUtils van 'react-dom / test-utils'; import Productenlijst van '... / ProductsList'; beschrijven ('ProductHeader Component', () => it ('has a h2 tag', () => // Test hier); it ('is ingepakt in een titelklasse', () => / / Test hier))

Om te controleren op het bestaan ​​van een h2 knooppunt, zullen we eerst onze React-elementen in een DOM-knooppunt in het document moeten weergeven. U kunt dat doen met behulp van enkele van de API's geëxporteerd door ReactTestUtils. Bijvoorbeeld om onze component, kunt u zoiets als dit doen:

 const component = ReactTestUtils.renderIntoDocument (); 

Vervolgens kunt u de .extra extraheren h2 tag van de component met behulp van findRenderedDOMComponentWithTag ( 'tag-naam'). Het controleert alle onderliggende knooppunten en vindt het knooppunt dat overeenkomt met de tag-naam

Hier is de hele testspecificatie.

 it ('has a h2 tag', () => const component = ReactTestUtils.renderIntoDocument (); var h2 = ReactTestUtils.findRenderedDOMComponentWithTag (component, 'h2'); );

Bewaar het en uw testrunner moet u laten zien dat de test is geslaagd. Dat is enigszins verrassend, want we hebben geen verwachten() verklaring zoals in ons vorige voorbeeld. De meeste van de methoden geëxporteerd door ReactTestUtils hebben verwachtingen ingebouwd. In dit specifieke geval, als het testhulpprogramma de fout niet kan vinden h2 tag, het zal een fout veroorzaken en de tests zullen automatisch mislukken.

Probeer nu de code te maken voor de tweede test. Je kunt gebruiken findRenderedDOMcomponentWithClass () om te controleren of er een knoop is met de klasse 'titel'.

 it ('heeft een titelklasse', () => const component = ReactTestUtils.renderIntoDocument (); var node = ReactTestUtils.findRenderedDOMComponentWithClass (component, 'title'); )

Dat is het! Als alles goed gaat, zou je de resultaten in groen moeten zien. 

Conclusie

Hoewel we net twee testspecificaties hebben geschreven, hebben we veel aandacht besteed aan het proces. In het volgende artikel zullen we enkele volwaardige tests schrijven voor onze productvermeldingspagina. We zullen ook ReactTestUtils vervangen door Enzyme. Waarom? Enzyme biedt een interface op hoog niveau die heel gemakkelijk te gebruiken en ontwikkelaarvriendelijk is. Blijf op de hoogte voor het tweede deel!

Als je op een bepaald moment het gevoel hebt dat je vastzit of hulp nodig hebt, laat het ons dan weten in de comments.