Med hjälp av Cypress att Skriva Tester för en Reagera Ansökan

0
59

End-to-end-tester skrivs att hävda flödet av en ansökan från början till slut. I stället för hantering av testerna själv — du vet, manuellt klicka på hela programmet — du kan skriva ett test som körs som du skapar programmet. Det är vad vi kallar för kontinuerlig integration och det är en vacker sak. Att skriva lite kod, spara det, och låt tooling göra det smutsiga arbetet att se till att det inte skadar något.

>Cypress är bara en end-to-end testing ramar som inte alla att klicka arbete för oss och det är vad vi kommer att titta på i detta inlägg. Det är verkligen för alla moderna JavaScript-bibliotek, men vi kommer att integrera det med att Reagera i exemplen.

Låt oss ställa upp en app för att testa

I denna handledning kommer vi skriva tester för att täcka en todo-applikation som jag har byggt. Du kan duplicera lagret att följa med när vi kopplar in den i Cypress.

git clone [email protected]:kinsomicrote/cypress-reagera-tutorial.git

Navigera i programmet och installera de beroenden:

cd-cypress-reagera-handledning
garn installera

Cypress är inte en del av beroenden, men kan du installera det genom att köra det här:

garn lägg till cypress –dev

Nu, kör det här kommandot för att öppna Cypress:

node_modules/.bin/cypress öppna

Att skriva det kommandot till terminalen om och om igen kan få ansträngande, men du kan lägga in detta script i paketet.json-fil i projektet root:

“cypress”: “cypress öppna”

Nu, allt du behöver göra är att göra npm köra cypress en gång och Cypress kommer att stå hela tiden. För att få en känsla av vad den ansökan som vi kommer att testa ser ut, du kan börja Reagera ansökan genom att köra garn start.

Vi kommer att börja med att skriva ett test för att bekräfta att Cypress fungerar. I cypress/integration mapp, skapa en ny fil som heter init.spec.js. Testet hävdar att sanna är lika med sant. Vi behöver bara det att bekräfta att de arbetar för att se till att Cypress är igång för hela programmet.

beskriv (“Cypress”, () = > {
det(‘arbetar’, () => {
förvänta dig(sant).till.lika(sant)
})
})

Du bör ha en förteckning över de tester öppna. Gå dit och välj init.spec.js.

Det bör orsaka testa att köra och smälla upp en skärm som visar testet att passera.

Medan vi ändå är i init.spec.js låt oss lägga till ett test för att bekräfta att vi kan besöka app genom att trycka http://localhost:3000 i webbläsaren. Detta kommer att se till att appen är igång.

det(‘besök app’, () => {
cy.besök(‘http://localhost:3000’)
})

Vi kallar metoden besök() och vi passerar den URL: en för den appen. Vi har tillgång till ett globalt objekt som kallas cy för att anropa de metoder som finns tillgängliga för oss på Cypress.

För att undvika att behöva skriva URL-om och om igen, kan vi ställa en bas-URL som kan användas i de tester som vi skriver. Öppna cypress.json-fil i hemkatalogen för ansökan och lägg definiera WEBBADRESSEN det:

{
“baseUrl”: “http://localhost:3000”
}

Du kan ändra testa blocket för att se ut så här:

det(‘besök app’, () => {
cy.besök(‘/’)
})

…och testet bör fortsätta att passera. 🤞

Testa formulärkontroller och insatsvaror

De test vi kommer att skriva kommer att omfatta hur användare interagerar med todo-applikation. Till exempel, vi vill se till att ingången är i fokus när appen laddas så att användarna kan börja med att skriva in uppgifter omedelbart. Vi vill också se till att det finns en standard uppgift i det så att listan inte är tom som standard. När det inte finns några uppgifter, vi vill visa text som talar om för användaren så mycket.

För att börja, gå vidare och skapa en ny fil i den mapp som heter integration form.spec.js. Namnet på filen är inte så viktigt. Vi är tillagd “form”, eftersom vad vi testar är i slutändan en form ingång. Du kanske vill kalla det något olika beroende på hur du planerar att organisera tester.

Vi kommer att lägga till en beskriva block till fil:

beskriv(‘Form’, () => {
beforeEach(() => {
cy.besök(‘/’)
})

det (“det är inriktat på input’, () => {
cy.fokuserad().bör(‘have.class’, ‘form-control”)
})
})

Den beforeEach block används för att undvika onödig upprepning. För varje block av test, måste vi besöker ansökan. Det skulle vara överflödigt att upprepa den raden varje gång beforeEach säkerställer Cypress besöker ansökan i varje enskilt fall.

För test, låt oss kolla att DOM-element i fokus när ansökan först laster har en typ av form-kontroll. Om du kolla källan fil, kommer du att se att den ingående element har en typ som kallas form-kontroll ställer till det, och vi har autofokus som ett av de element attribut:

<ingång
type=”text”
autofokus
värde={detta.stat.objekt}
onChange={detta.handleInputChange}
platshållare=”Ange en uppgift”
className=”form-kontroll”
/>

När du sparar det, gå tillbaka till testet skärmen och välj form.spec.js för att köra testet.

Nästa sak vi ska göra är att testa om en användare ska kunna ange ett värde i textfältet.

det (“accepterar input’, () => {
const input = “Lära sig om Cypress”
cy.get(‘.form-control”)
.typ(ingående)
.bör (“har.värde’, ingång)
})

Vi har lagt till lite text (“Lära sig om Cypress”) till ingången. Då vi använder oss av cy.får att få DOM-element med form-kontroll-klass namn. Vi skulle också kunna göra något liknande cy.få (“input”) och få samma resultat. Efter att få elementet, cy.typ() används för att ange det värde vi tilldelade ingången, då vi hävdar att DOM-element med klassen form-kontrollen har ett värde som matchar värdet av ingående.

Med andra ord:

Vår ansökan bör också ha två todos som har skapats som standard när programmet körs. Det är viktigt att vi har ett test som kontrollerar att de verkligen visas.

Vad vill vi? I vår kod, vi använder posten i listan (<li>) element för att visa uppgifter som poster i en lista. Eftersom vi har två objekt som anges som standard, det innebär att förteckningen bör ha en längd av två på start. Så, då testet kommer att se ut ungefär så här:

det (“visar en lista av todo’, () => {
cy.get(‘li’)
.bör (“har.längd’, 2)
})

Åh! Och vad skulle denna app vara om en användare inte att lägga till en ny uppgift i listan? Att vi bättre skulle testa det också.

det (“lägger till en ny todo’, () => {
const input = “Lära sig om cypress”
cy.get(‘.form-control”)
.typ(ingående)
.typ(‘{enter}’)
.get(‘li’)
.bör (“har.längd’, 3)
})

Detta liknar vad vi skrev i de sista två proven. Vi få input och simulera att skriva ett värde i det. Då vi simulera att lämna in en uppgift som ska uppdatera status för ansökan, och därigenom öka längden från 2 till 3. Så, egentligen, vi kan bygga bort av det vi redan har!

Om du ändrar värdet från tre till två kommer att orsaka ett test för att misslyckas — det är vad vi förväntar oss eftersom listan bör ha två uppgifter som standard och skicka in när bör leda till en summa av tre.

Du kanske undrar vad som skulle hända om användaren raderar antingen (eller både och) av standard uppgifter innan du försöker att skicka in en ny uppgift. Jo, vi skulle skriva ett prov för det också, men vi försöker att inte göra det antagandet i detta exempel eftersom vi vill bara bekräfta att de uppgifter som kan lämnas in. Detta är ett enkelt sätt för oss att testa de grundläggande skicka in funktionalitet som vi utvecklas, och vi kan stå för avancerad/edge fall senare.

Den sista funktionen vi måste testa är att ta bort uppgifter. Först vill vi att ta bort en av standard uppgift objekt och sedan se om det finns en kvar när raderingen sker. Det är samma typ av affär som innan, men vi bör förvänta oss en punkt kvar i listan i stället för tre, vi förväntade oss när du lägger till en ny uppgift i listan.

det(‘tar bort en todo’, () => {
cy.get(‘li’)
.första()
.hitta(‘.btn-fara”)
.klicka på()
.get(‘li’)
.bör (“har.längd’, 1)
})

OK, så vad händer om vi tar bort både standard uppgifter i listan och listan är helt tom? Låt oss säga att vi vill visa denna text när inga fler poster i listan: “Alla dina uppgifter är fullständiga. Snyggt gjort!”

Det är inte så annorlunda från vad vi har gjort innan. Du kan prova det först för att sedan komma tillbaka för att se koden för det.

det.bara(‘tar bort alla todo’, () => {
cy.get(‘li’)
.första()
.hitta(‘.btn-fara”)
.klicka på()
.get(‘li’)
.första()
.hitta(‘.btn-fara”)
.klicka på()
.get(‘.no-uppgift”)
.bör (“har.text’, ‘Alla dina uppgifter är fullständiga. Snyggt gjort!’)
})

Båda testerna ser lika ut: vi får listan element, mål den första, och använda sig av cy.hitta() för att leta efter DOM-element med en btn-fara klass namn (vilket, återigen, är en helt godtycklig klass namn för knappen ta bort i detta exempel app). Vi simulera en click-händelse på elementet för att ta bort uppgiften artikel.

Håller jag på att kolla till “Ingen uppgift” i detta specifika test.

Testa nätverket önskemål

Förfrågningar från nätverket är typ av en stor sak eftersom det är ofta källan till uppgifter i en ansökan. Säga att vi har en komponent i vår app som gör en förfrågan till servern för att få fram data som ska visas för användaren. Låt oss säga att komponenten markup ser ut så här:

klass App sträcker sig Reagera.Komponent {
state = {
isLoading: sant,
användare: [],
fel: null
};
fetchUsers() {
hämta(`https://jsonplaceholder.typicode.com/users`)
.sedan(som svar => svar.json())
.sedan(data =>
detta.setState({
användare: data,
isLoading: false,
})
)
.catch(fel => här.setState({ error, isLoading: false }));
}
componentDidMount() {
detta.fetchUsers();
}
render() {
const { isLoading, användare, fel } = i detta.stat.
avkastning (
<Reagera.Fragment>
<h1>Slumpmässigt Användare</h1>
{fel ? <p>{fel.meddelande}</p> : null}
{!isLoading ? (
användare.karta(user => {
const { användarnamn, namn, e-post } = användarnamn;
avkastning (
<div key={användarnamn}>
<p>Namn: {name}</p>
<p>E-post Adress: {e}</p>
<hr />
</div>
);
})
) : (
<h3>Laddar…</h3>
)}
</Reagera.Fragment>
);
}
}

Vi här att använda sig av JSON Platshållare API som ett exempel. Vi kan ha ett sånt här test för att testa den respons vi får från servern:

beskriv(‘Begär’, () => {
det(‘visar slumpmässigt användare från API’, () => {
cy.begäran(‘https://jsonplaceholder.typicode.com/users’)
.bör((svar) => {
förvänta dig(svar.status).till.eq(200)
förvänta dig(svar.kroppen).till.har.längd(10)
förvänta dig(svar).till.har.egendom(‘ruberiker’)
förvänta dig(svar).till.har.egendom(‘duration’)
})
})
})

Nyttan av att testa servern (i motsats till stubbing det) är att vi är säkra på att de svar vi får är detsamma som en användare kommer att få. För att lära sig mer om förfrågningar från nätverket och hur du kan påbörjad förfrågningar från nätverket, se denna sida i Cypress dokumentation.

Tester körs från kommandoraden

Cypress tester kan köras från den terminalen utan den medföljande UI:

./node_modules/.bin/cypress kör

…eller

npx cypress kör

Låt oss köra formuläret tester skrev vi:

npx cypress run –post –spec “cypress/integration/form.spec.js”

Terminal utdata resultaten där med en sammanfattning av vad som var testade.

Det finns en hel del mer om du använder Cypress med kommandoraden i dokumentationen.

Det är en wrap!

Testerna är något som antingen får folk glada eller rädda, beroende på vem du pratar med. Förhoppningsvis vad vi har tittat på i detta inlägg blir alla glada om att genomföra tester i ett program och visar hur relativt enkelt det kan vara. Cypress är ett utmärkt verktyg och jag har hittat mig själv att nå för i mitt eget arbete, men det finns andra också. Oavsett vilka verktyg du använder (och hur du känner om tester), förhoppningsvis ser du fördelarna av tester och är mer tvingade att ge dem ett försök.

Relaterade resurser

  • Cypress: Att Skriva Din Första Test
  • GitHub: Cypress arkiv
  • CSS-Tricks: Komma Igång med att Reagera Test Bibliotek
  • CSS-Tricks: att Skriva Tester för att Reagera Applikationer med Hjälp av Skämt och Enzym
  • CSS-Tricks: Tester för Visual Regressioner med Percy