Įvaldykite React komponentų testavimą su React testavimo biblioteka. Sužinokite geriausias praktikas, kaip rašyti prižiūrimus, efektyvius testus, orientuotus į vartotojo elgseną ir prieinamumą.
React testavimo biblioteka: komponentų testavimo geriausios praktikos pasaulinėms komandoms
Nuolat besikeičiančiame interneto svetainių kūrimo pasaulyje, jūsų React aplikacijų patikimumo ir kokybės užtikrinimas yra itin svarbus. Tai ypač aktualu pasaulinėms komandoms, dirbančioms su projektais, kurie turi įvairias vartotojų bazes ir prieinamumo reikalavimus. „React Testing Library“ (RTL) suteikia galingą ir į vartotoją orientuotą požiūrį į komponentų testavimą. Skirtingai nuo tradicinių testavimo metodų, kurie sutelkia dėmesį į įgyvendinimo detales, RTL skatina testuoti komponentus taip, kaip su jais sąveikautų vartotojas, o tai lemia patikimesnius ir lengviau prižiūrimus testus. Šis išsamus vadovas gilinsis į geriausias RTL naudojimo praktikas jūsų React projektuose, sutelkiant dėmesį į aplikacijų, tinkamų pasaulinei auditorijai, kūrimą.
Kodėl verta rinktis „React Testing Library“?
Prieš pradedant gilintis į geriausias praktikas, svarbu suprasti, kodėl RTL išsiskiria iš kitų testavimo bibliotekų. Štai keletas pagrindinių privalumų:
- Į vartotoją orientuotas požiūris: RTL teikia pirmenybę komponentų testavimui iš vartotojo perspektyvos. Jūs sąveikaujate su komponentu naudodami tuos pačius metodus, kuriuos naudotų vartotojas (pvz., mygtukų paspaudimas, teksto įvedimas į laukelius), užtikrindami realistiškesnę ir patikimesnę testavimo patirtį.
- Orientacija į prieinamumą: RTL skatina kurti prieinamus komponentus, ragindama juos testuoti atsižvelgiant į vartotojus su negalia. Tai atitinka pasaulinius prieinamumo standartus, tokius kaip WCAG.
- Mažesnė priežiūros našta: Vengiant testuoti įgyvendinimo detales (pvz., vidinę būseną, konkrečių funkcijų iškvietimus), RTL testai rečiau „lūžta“ refaktorizuojant kodą. Tai lemia lengviau prižiūrimus ir atsparesnius testus.
- Geresnis kodo dizainas: Į vartotoją orientuotas RTL požiūris dažnai lemia geresnį komponentų dizainą, nes esate priversti galvoti, kaip vartotojai sąveikaus su jūsų komponentais.
- Bendruomenė ir ekosistema: RTL turi didelę ir aktyvią bendruomenę, kuri teikia daugybę išteklių, pagalbą ir plėtinius.
Testavimo aplinkos paruošimas
Norėdami pradėti dirbti su RTL, turite paruošti savo testavimo aplinką. Štai pagrindinė sąranka naudojant „Create React App“ (CRA), kuri jau turi iš anksto sukonfigūruotus „Jest“ ir RTL:
npx create-react-app my-react-app
cd my-react-app
npm install --save-dev @testing-library/react @testing-library/jest-dom
Paaiškinimas:
- `npx create-react-app my-react-app`: Sukuria naują React projektą naudojant „Create React App“.
- `cd my-react-app`: Pereinama į naujai sukurto projekto katalogą.
- `npm install --save-dev @testing-library/react @testing-library/jest-dom`: Įdiegia reikiamus RTL paketus kaip kūrimo priklausomybes. `@testing-library/react` suteikia pagrindinį RTL funkcionalumą, o `@testing-library/jest-dom` suteikia naudingus „Jest“ atitikmenis (matchers) darbui su DOM.
Jei nenaudojate CRA, jums reikės atskirai įdiegti „Jest“ ir RTL bei sukonfigūruoti „Jest“, kad jis naudotų RTL.
Komponentų testavimo su „React Testing Library“ geriausios praktikos
1. Rašykite testus, kurie primena vartotojo sąveikas
Pagrindinis RTL principas yra testuoti komponentus taip, kaip tai darytų vartotojas. Tai reiškia, kad reikia sutelkti dėmesį į tai, ką vartotojas mato ir daro, o ne į vidines įgyvendinimo detales. Naudokite RTL pateiktą `screen` objektą, norėdami ieškoti elementų pagal jų tekstą, vaidmenį ar prieinamumo etiketes.
Pavyzdys: mygtuko paspaudimo testavimas
Tarkime, turite paprastą mygtuko komponentą:
// Button.js
import React from 'react';
function Button({ onClick, children }) {
return ;
}
export default Button;
Štai kaip jį testuotumėte naudojant RTL:
// Button.test.js
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import Button from './Button';
describe('Button Component', () => {
it('calls the onClick handler when clicked', () => {
const handleClick = jest.fn();
render();
const buttonElement = screen.getByText('Click Me');
fireEvent.click(buttonElement);
expect(handleClick).toHaveBeenCalledTimes(1);
});
});
Paaiškinimas:
- `render()`: Atvaizduoja mygtuko komponentą su imituotu (mock) `onClick` tvarkytuvu.
- `screen.getByText('Click Me')`: Ieško dokumente elemento, kuriame yra tekstas „Click Me“. Taip vartotojas atpažintų mygtuką.
- `fireEvent.click(buttonElement)`: Imituoja paspaudimo įvykį ant mygtuko elemento.
- `expect(handleClick).toHaveBeenCalledTimes(1)`: Patikrina, ar `onClick` tvarkytuvas buvo iškviestas vieną kartą.
Kodėl tai geriau nei testuoti įgyvendinimo detales: Įsivaizduokite, kad refaktorizuojate mygtuko komponentą, kad jis naudotų kitą įvykių tvarkytuvą ar pakeistų vidinę būseną. Jei testuotumėte konkrečią įvykių tvarkytuvo funkciją, jūsų testas „lūžtų“. Sutelkiant dėmesį į vartotojo sąveiką (mygtuko paspaudimą), testas išlieka galiojantis net ir po refaktorizavimo.
2. Teikite pirmenybę užklausoms pagal vartotojo ketinimus
RTL siūlo įvairius užklausų metodus elementams rasti. Teikite pirmenybę šioms užklausoms tokia tvarka, nes jos geriausiai atspindi, kaip vartotojai suvokia jūsų komponentus ir su jais sąveikauja:
- getByRole: Ši užklausa yra pati prieinamiausia ir turėtų būti jūsų pirmasis pasirinkimas. Ji leidžia rasti elementus pagal jų ARIA vaidmenis (pvz., mygtukas, nuoroda, antraštė).
- getByLabelText: Naudokite šią užklausą elementams, susietiems su konkrečia etikete (label), pavyzdžiui, įvesties laukams, rasti.
- getByPlaceholderText: Naudokite šią užklausą įvesties laukams pagal jų rezervuotos vietos tekstą (placeholder) rasti.
- getByText: Naudokite šią užklausą elementams pagal jų tekstinį turinį rasti. Būkite konkretūs ir venkite naudoti bendrinio teksto, kuris gali pasikartoti keliose vietose.
- getByDisplayValue: Naudokite šią užklausą įvesties laukams pagal jų esamą reikšmę rasti.
Pavyzdys: formos įvesties lauko testavimas
// Input.js
import React from 'react';
function Input({ label, placeholder, value, onChange }) {
return (
);
}
export default Input;
Štai kaip jį testuoti naudojant rekomenduojamą užklausų tvarką:
// Input.test.js
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import Input from './Input';
describe('Input Component', () => {
it('updates the value when the user types', () => {
const handleChange = jest.fn();
render();
const inputElement = screen.getByLabelText('Name');
fireEvent.change(inputElement, { target: { value: 'John Doe' } });
expect(handleChange).toHaveBeenCalledTimes(1);
expect(handleChange).toHaveBeenCalledWith(expect.objectContaining({ target: { value: 'John Doe' } }));
});
});
Paaiškinimas:
- `screen.getByLabelText('Name')`: Naudoja `getByLabelText` norint rasti įvesties lauką, susietą su etikete „Name“. Tai yra prieinamiausias ir vartotojui draugiškiausias būdas rasti įvesties lauką.
3. Venkite testuoti įgyvendinimo detales
Kaip minėta anksčiau, venkite testuoti vidinę būseną, funkcijų iškvietimus ar konkrečias CSS klases. Tai yra įgyvendinimo detalės, kurios gali keistis ir lemti trapius testus. Sutelkite dėmesį į stebimą komponento elgseną.
Pavyzdys: venkite tiesioginio būsenos testavimo
Užuot testavę, ar atnaujinamas konkretus būsenos kintamasis, testuokite, ar komponentas atvaizduoja teisingą išvestį, remdamasis ta būsena. Pavyzdžiui, jei komponentas rodo pranešimą, priklausantį nuo loginio (boolean) būsenos kintamojo, testuokite, ar pranešimas yra rodomas ar paslėptas, o ne patį būsenos kintamąjį.
4. Naudokite `data-testid` specifiniais atvejais
Nors paprastai geriausia vengti `data-testid` atributų, yra specifinių atvejų, kai jie gali būti naudingi:
- Elementai be semantinės reikšmės: Jei reikia pasirinkti elementą, kuris neturi prasmingo vaidmens, etiketės ar teksto, galite naudoti `data-testid`.
- Sudėtingos komponentų struktūros: Sudėtingose komponentų struktūrose `data-testid` gali padėti pasirinkti konkrečius elementus, nepasikliaujant trapiais selektoriais.
- Prieinamumo testavimas: `data-testid` gali būti naudojamas identifikuoti konkrečius elementus prieinamumo testavimo metu su įrankiais, tokiais kaip „Cypress“ ar „Playwright“.
Pavyzdys: `data-testid` naudojimas
// MyComponent.js
import React from 'react';
function MyComponent() {
return (
This is my component.
);
}
export default MyComponent;
// MyComponent.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';
describe('MyComponent', () => {
it('renders the component container', () => {
render( );
const containerElement = screen.getByTestId('my-component-container');
expect(containerElement).toBeInTheDocument();
});
});
Svarbu: Naudokite `data-testid` saikingai ir tik tada, kai kiti užklausų metodai nėra tinkami.
5. Rašykite prasmingus testų aprašymus
Aišūs ir glausti testų aprašymai yra labai svarbūs norint suprasti kiekvieno testo paskirtį ir derinti klaidas. Naudokite aprašomuosius pavadinimus, kurie aiškiai paaiškina, ką testas tikrina.
Pavyzdys: geri ir blogi testų aprašymai
Blogai: `it('veikia')`
Gerai: `it('rodo teisingą pasisveikinimo pranešimą')`
Dar geriau: `it('rodo pasisveikinimo pranešimą "Hello, World!", kai nepateikiamas `name` atributas')`
Geresnis pavyzdys aiškiai nurodo laukiamą komponento elgseną esant tam tikroms sąlygoms.
6. Testai turi būti maži ir koncentruoti
Kiekvienas testas turėtų būti skirtas vienam komponento elgsenos aspektui patikrinti. Venkite rašyti didelių, sudėtingų testų, apimančių kelis scenarijus. Mažus, koncentruotus testus lengviau suprasti, prižiūrėti ir derinti.
7. Tinkamai naudokite testavimo dublerius (Mocks ir Spies)
Testavimo dubleriai yra naudingi norint izoliuoti testuojamą komponentą nuo jo priklausomybių. Naudokite imitacijas (mocks) ir šnipus (spies), kad simuliuotumėte išorines paslaugas, API iškvietimus ar kitus komponentus.
Pavyzdys: API iškvietimo imitavimas
// UserList.js
import React, { useState, useEffect } from 'react';
function UserList() {
const [users, setUsers] = useState([]);
useEffect(() => {
async function fetchUsers() {
const response = await fetch('/api/users');
const data = await response.json();
setUsers(data);
}
fetchUsers();
}, []);
return (
{users.map(user => (
- {user.name}
))}
);
}
export default UserList;
// UserList.test.js
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import UserList from './UserList';
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve([
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Smith' },
]),
})
);
describe('UserList Component', () => {
it('fetches and displays a list of users', async () => {
render( );
// Wait for the data to load
await waitFor(() => screen.getByText('John Doe'));
expect(screen.getByText('John Doe')).toBeInTheDocument();
expect(screen.getByText('Jane Smith')).toBeInTheDocument();
});
});
Paaiškinimas:
- `global.fetch = jest.fn(...)`: Imituoja `fetch` funkciją, kad ji grąžintų iš anksto nustatytą vartotojų sąrašą. Tai leidžia testuoti komponentą nepasikliaujant realiu API galiniu tašku.
- `await waitFor(() => screen.getByText('John Doe'))`: Laukia, kol dokumente pasirodys tekstas „John Doe“. Tai būtina, nes duomenys gaunami asinchroniškai.
8. Testuokite kraštutinius atvejus ir klaidų apdorojimą
Netestuokite tik sėkmingo scenarijaus („happy path“). Būtinai testuokite kraštutinius atvejus, klaidų scenarijus ir ribines sąlygas. Tai padės anksti nustatyti galimas problemas ir užtikrinti, kad jūsų komponentas tinkamai tvarkytųsi su netikėtomis situacijomis.
Pavyzdys: klaidų apdorojimo testavimas
Įsivaizduokite komponentą, kuris gauna duomenis iš API ir rodo klaidos pranešimą, jei API iškvietimas nepavyksta. Turėtumėte parašyti testą, kuris patikrintų, ar klaidos pranešimas rodomas teisingai, kai API iškvietimas nepavyksta.
9. Sutelkite dėmesį į prieinamumą
Prieinamumas yra labai svarbus kuriant įtraukias interneto aplikacijas. Naudokite RTL, kad patikrintumėte savo komponentų prieinamumą ir užtikrintumėte, jog jie atitinka prieinamumo standartus, tokius kaip WCAG. Keletas pagrindinių prieinamumo aspektų:
- Semantinis HTML: Naudokite semantinius HTML elementus (pvz., `
- ARIA atributai: Naudokite ARIA atributus, kad suteiktumėte papildomos informacijos apie elementų vaidmenį, būseną ir savybes, ypač nestandartiniams komponentams.
- Navigacija klaviatūra: Užtikrinkite, kad visi interaktyvūs elementai būtų pasiekiami naudojant klaviatūrą.
- Spalvų kontrastas: Naudokite pakankamą spalvų kontrastą, kad tekstas būtų įskaitomas vartotojams su silpnu regėjimu.
- Suderinamumas su ekrano skaitytuvais: Testuokite savo komponentus su ekrano skaitytuvu, kad užtikrintumėte prasmingą ir suprantamą patirtį vartotojams su regos sutrikimais.
Pavyzdys: prieinamumo testavimas su `getByRole`
// MyAccessibleComponent.js
import React from 'react';
function MyAccessibleComponent() {
return (
);
}
export default MyAccessibleComponent;
// MyAccessibleComponent.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import MyAccessibleComponent from './MyAccessibleComponent';
describe('MyAccessibleComponent', () => {
it('renders an accessible button with the correct aria-label', () => {
render( );
const buttonElement = screen.getByRole('button', { name: 'Close' });
expect(buttonElement).toBeInTheDocument();
});
});
Paaiškinimas:
- `screen.getByRole('button', { name: 'Close' })`: Naudoja `getByRole` norint rasti mygtuko elementą su prieinamu pavadinimu „Close“. Tai užtikrina, kad mygtukas yra tinkamai paženklintas ekrano skaitytuvams.
10. Integruokite testavimą į savo kūrimo procesą
Testavimas turėtų būti neatsiejama jūsų kūrimo proceso dalis, o ne vėliau priminta užduotis. Integruokite testus į savo CI/CD procesą, kad testai būtų automatiškai paleidžiami kiekvieną kartą, kai kodas yra įkeliamas (committed) ar diegiamas (deployed). Tai padės anksti aptikti klaidas ir išvengti regresijų.
11. Atsižvelkite į lokalizaciją ir internacionalizaciją (i18n)
Pasaulinėms aplikacijoms testavimo metu labai svarbu atsižvelgti į lokalizaciją ir internacionalizaciją (i18n). Įsitikinkite, kad jūsų komponentai teisingai atvaizduojami skirtingomis kalbomis ir lokalėmis.
Pavyzdys: lokalizacijos testavimas
Jei lokalizacijai naudojate biblioteką, tokią kaip `react-intl` ar `i18next`, galite imituoti lokalizacijos kontekstą savo testuose, kad patikrintumėte, ar jūsų komponentai rodo teisingą išverstą tekstą.
12. Naudokite pasirinktines atvaizdavimo funkcijas pasikartojančiai sąrankai
Dirbant su didesniais projektais, galite pastebėti, kad kartojate tuos pačius sąrankos veiksmus keliuose testuose. Norėdami išvengti dubliavimosi, sukurkite pasirinktines atvaizdavimo funkcijas, kurios apima bendrą sąrankos logiką.
Pavyzdys: pasirinktinė atvaizdavimo funkcija
// test-utils.js
import React from 'react';
import { render } from '@testing-library/react';
import { ThemeProvider } from 'styled-components';
import theme from './theme';
const AllTheProviders = ({ children }) => {
return (
{children}
);
}
const customRender = (ui, options) =>
render(ui, { wrapper: AllTheProviders, ...options })
// re-export everything
export * from '@testing-library/react'
// override render method
export { customRender as render }
// MyComponent.test.js
import React from 'react';
import { render, screen } from './test-utils'; // Import the custom render
import MyComponent from './MyComponent';
describe('MyComponent', () => {
it('renders correctly with the theme', () => {
render( );
// Your test logic here
});
});
Šis pavyzdys sukuria pasirinktinę atvaizdavimo funkciją, kuri apgaubia komponentą su „ThemeProvider“. Tai leidžia lengvai testuoti komponentus, kurie priklauso nuo temos, nekartojant „ThemeProvider“ sąrankos kiekviename teste.
Išvada
„React Testing Library“ siūlo galingą ir į vartotoją orientuotą požiūrį į komponentų testavimą. Laikydamiesi šių geriausių praktikų, galite rašyti prižiūrimus, efektyvius testus, kurie sutelkti į vartotojo elgseną ir prieinamumą. Tai leis kurti tvirtesnes, patikimesnes ir įtraukesnes React aplikacijas, skirtas pasaulinei auditorijai. Nepamirškite teikti pirmenybės vartotojo sąveikoms, vengti testuoti įgyvendinimo detales, sutelkti dėmesį į prieinamumą ir integruoti testavimą į savo kūrimo procesą. Laikydamiesi šių principų, galite kurti aukštos kokybės React aplikacijas, atitinkančias vartotojų poreikius visame pasaulyje.
Svarbiausi akcentai:
- Dėmesys vartotojo sąveikoms: Testuokite komponentus taip, kaip su jais sąveikautų vartotojas.
- Pirmenybė prieinamumui: Užtikrinkite, kad jūsų komponentai būtų prieinami vartotojams su negalia.
- Venkite įgyvendinimo detalių: Netestuokite vidinės būsenos ar funkcijų iškvietimų.
- Rašykite aiškius ir glaustus testus: Užtikrinkite, kad jūsų testai būtų lengvai suprantami ir prižiūrimi.
- Integruokite testavimą į savo darbo eigą: Automatizuokite testus ir reguliariai juos paleiskite.
- Atsižvelkite į pasaulinę auditoriją: Užtikrinkite, kad jūsų komponentai gerai veiktų skirtingomis kalbomis ir lokalėmis.