Β
Jestλ?
μ μ€νΈλ ν
μ€νΈ μ½λλ₯Ό μ°Ύκ³ , ν
μ€νΈλ₯Ό μ€ννκ³ , μ€ν¨μΈμ§ μ±κ³΅μΈμ§λ₯Ό νλ¨νλ ν
μ€νΈ λ¬λμ
λλ€.
facebook μμ κ°λ°νκ³ κ΄λ¦¬νκ³ μμ΅λλ€. (https://jestjs.io/)
μ μ€νΈλ§μ νΉμ§μ
Html μμλ₯Ό νμνλλ° μ κ·Όμ± λ§μ»€ μ¦, ariaλ₯Ό μ΄μ©ν©λλ€. TDD λ₯Ό μμ±ν¨μΌλ‘μ μμ°μ€λ½κ² μ κ·Όμ±μ ν₯μμν€λ μ₯μ μ΄ μμ΅λλ€. μ μ€νΈκ° μμλ₯Ό ariaλ₯Ό ν΅ν΄ μ°Ύμ μ μλ€λκ²μ μ€ν¬λ¦° 리λλ€λ μ°Ύμ μ μλ€λ μκΈ°μ
λλ€.
Β
1. μ μ€νΈλ₯Ό μ¬μ©ν΄λ³΄κ² μ΅λλ€.
- npx λͺ λ Ήμ΄λ₯Ό ν΅ν΄ 리μνΈ μ±μ μμ±ν΄λ΄ μλ€.
npx create-react-app color-button
Β
- react μ€μΉκ° μλ£λκ³ νλ‘μ νΈκ° μμ±λμμ΅λλ€. ν°λ―Έλμ ν΅ν΄ μ μμ ν΄μ£Όλκ΅°μ π
Β
- μ€μΉκ° μλ£λμμΌλ©΄ npm testλ₯Ό ν΄λ΄ μλ€.
μ μ€νΈκ° μμΉλͺ¨λλ‘ μ€νλλκ²μ νμΈ ν μ μμ΅λλ€.
μμΉλͺ¨λλ νμΌμ μμ μ¬νμ΄ κ°μ§λ κ²½μ° μλμΌλ‘ ν
μ€νΈλ₯Ό μ€νν΄μ£Όλ μνλ₯Ό μλ―Έν©λλ€.
λ§μ½ μ μ€νΈ μ€ν μ λ
Έλ λ²μ μ΄μλ‘
μ΄λ° μλ¬κ° λ°μνλ€λ©΄ μ μ€νΈμ κ΄λ ¨λ ν¨ν€μ§λ₯Ό μ€μΉ ν΄μ£Όμ
μΌ ν©λλ€.
npm i -D --exact jest-watch-typeahead@0.6.5
Β
- a λ₯Ό λλ¬ ν μ€νΈλ₯Ό μ€νν΄λ΄ λλ€.
μλ¬΄λ° ν
μ€νΈ μ½λλ₯Ό μμ±νμ§ μμμ§λ§ λκ° μ±κ³΅νμ΅λλ€! γ
γ
μΌλ¨ qλ₯Ό λλ¬ test μνμμ λΉ μ Έλκ°λλ€.
Β
Β
2. μ μ΄μ λ΄λΆμ μΌλ‘ μ΄λ»κ² ν μ€νΈκ° μ€νλμλμ§ μ΄ν΄λ³΄κ² μ΅λλ€.
Β
- μ μ€νΈκ° μ€ν μ½λλ App.test.js μ μμ΅λλ€.
import { render, screen } from '@testing-library/react'; import App from './App'; test('renders learn react link', () => { render(<App />); const linkElement = screen.getByText(/learn react/i); expect(linkElement).toBeInTheDocument(); });
- Test ν¨μ : κΈλ‘λ² ν¨μ. λ κ°μ§ μΈμλ₯Ό κ°μ§λλ€. 첫λ²μ§Έ μΈμλ λ¬Έμμ΄λ‘ ν μ€νΈμ μ€λͺ μ λλ€. μμ€λ―Όμμλ describe μ λλ€. λλ²μ§Έ μΈμλ ν μ€νΈλ₯Ό μ€ννλ ν μ€νΈ ν¨μμ λλ€.
- Render ν¨μ : μΈμλ‘ λ°λ JSXμ κ°μλμ μμ±ν©λλ€. μ¬κΈ°μλ app μ»΄ν¬λνΈλ₯Ό μ λ¬λ°μ΅λλ€.
- Screen : μμ±λ κ°μλμ μ κ·ΌνκΈ° μν μ μ κ°μ²΄μ λλ€.
renderμ screenμ λͺ¨λ import { render, screen } from '@testing-library/react'; μμ μμ΅λλ€.
- getByText ν¨μ : μΈμλ‘ μ λ¬λ ν μ€νΈλ₯Ό κ°μ§λ λ μμ μμλ₯Ό μ°Ύμ΅λλ€. μ¬κΈ°μλ μ κ·ννμμ μ¬μ©νκ΅°μ. /learn react/i λ€μ λΆμ iλ λμλ¬Έμλ₯Ό ꡬλΆνμ§ μκ² λ€λ μλ―Έμ λλ€.
Β
- expect ν¨μ : μ΅μνμ£ ? μ μ€λ―Όμλ μμμ΅λλ€. κΈ°λν κ²°κ³Όκ° μ±κ³΅μΈμ§ μ€ν¨μΈμ§ νλ¨νλ ν¨μμ λλ€.
- .toBeInTheDocument : matcher ν¨μμ λλ€. μ μ€λ―Όμ .toBe() ν¨μκ° κΈ°μ΅λμλμ? μ μ€νΈμλ μ‘΄μ¬ν©λλ€.
Β
- μ΄λ²μλ ν μ€νΈλ₯Ό μ€ν¨ ν΄λ΄ μλ€. App.js μ ν μ€νΈλ₯Ό βLearn Viewβ λ‘ λ³κ²½ν΄λ³΄κ³ npm testλ₯Ό μ€ν ν΄λ΄ λλ€.
Β
- μμ νλ μ½λλ₯Ό μμ 볡ꡬν΄μ μμΉ λͺ¨λκ° μ μλνλμ§λ νμΈν΄ λ΄ μλ€. π
Β
Β
3.κ°λ¨ν κΈ°λ₯ν μ€νΈλ₯Ό μ§μ ν΄λ΄ μλ€.
κΈ°λ³Έμ μΈ λ¬Έλ²κ³Ό λ΄μ©μ λν΄ μ΄ν΄λ΄€μ΅λλ€. μ΄μ κ°λ¨ν κΈ°λ₯μ ν
μ€νΈ ν΄λ³΄κ² μ΅λλ€!
Β
- App.js μμ return ν€μλ μμ λ΄μ©λ€κ³Ό App.test.js μμ ν μ€νΈ ν¨μ μμ λ΄μ©μ λͺ¨λ μ§μλλ€.
Β
- λλ₯΄λ©΄ μμ΄ λ°λλ λ²νΌμ λ§λ€κ³ ν μ€νΈ ν΄λ³΄κ² μ΅λλ€. App.test.js νμΌμ ν μ€νΈ μ½λλ₯Ό μΆκ°ν©λλ€.
test('λ²νΌμ΄ μ λλ‘ μ μλνκ³ μμ΅λκΉ?', () => { render(<App />); const button = screen.getByRole('button', { name: 'change to blue!' }); expect(button).toHaveStyle({ backgroundColor: 'red' }); });
- μ½λμμ μμλ₯Ό μ°Ύμ λ getByRole λ‘ μ°Ύλ κ²μ΄ 보μ λλ€. roleμ ariaμμ μ¬μ©νλ μμμ μν μ μλ―Ένλ μμ±μ λλ€. νΉμ μμλ role μ λͺ μνμ§ μμλΒ μ묡μ μΌλ‘ κ°μ§κ³ μλ κ²½μ°λ μμ΅λλ€.(https://www.w3.org/TR/html-aria/#docconformance)
- role κ°μ΄ νλ Έμ κ²½μ° μΉμ νκ² μ μ€νΈμμ μ μμ ν΄μ£ΌκΈ°λ ν©λλ€.
- μ묡μ μΈ roleμ΄ μλ μμμ κ²½μ° role μμ±μ μ§μ λͺ μν΄μ€λλ€.
roleμ μ’
λ₯μ λν΄ κΆκΈνλ€λ©΄ μ¬κΈ°λ₯Ό μ°Έκ³ ν΄λ³΄μΈμ. https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles
- getByRoleν¨μλ λλ²μ§Έ μΈμλ‘, μ°ΎμμΌν μμ μμ ν μ€νΈλ₯Ό μ§μ ν μ μμ΅λλ€.
- toHaveStyle ν¨μ : μμκ° νΉμ ν CSS μ€νμΌμ κ°μ§κ³ μλμ§ μ²΄ν¬ν©λλ€.
μ΄λ° matcher ν¨μλ€μ μ’
λ₯κ° κΆκΈνλ€λ©΄ μ¬κΈ°λ₯Ό μ°Έκ³ ν΄ λ³΄μΈμ.
Β
- μ΄μ ν μ€νΈλ₯Ό μ§νν΄ λ³΄κ² μ΅λλ€. μ΄λ€ κ²°κ³Όκ° λ³΄μ΄μλμ?
Β
- μ΄μ App.jsλ₯Ό μμ ν΄λ³΄κ² μ΅λλ€. μλ μ½λλ₯Ό μΆκ°ν΄ λ΄ μλ€.
<div> <button style={{ backgroundColor: 'red' }}>change to blue!</button> </div>
Jsx μμ λ§ν¬μ
μ ννμμ λ£κ³ μΆλ€λ©΄ μ€κ΄νΈλ₯Ό μ¬μ©ν΄μΌν©λλ€.
Β
- λ€μ ν μ€νΈλ₯Ό λλ €λ΄ μλ€.
Β
- μ΄μ κΈ°λ₯μ μΆκ°ν΄λ΄ μλ€. λ²νΌμ ν΄λ¦νμ λ μμ΄ λ³νλμ§ νμΈνλ ν μ€νΈμ λλ€.
import { render, screen, fireEvent } from '@testing-library/react';
- import ꡬ문μ fireEventλ₯Ό μΆκ°νμ΅λλ€. κ°μλκ³Όμ μνΈμμ©μ΄ κ°λ₯νλλ‘ νλ κ°μ²΄μ λλ€. κ³μν΄μ μλ μ½λλ₯Ό μΆκ°ν©λλ€.
fireEvent.click(button); expect(button).toHaveStyle({ backgroundColor: 'blue' }); expect(button.textContent).toBe('change to red!');
Β
- ν μ€νΈμ μ€ν¨ν©λλ€.
- μμ§ λ²νΌμ ν΄λ¦νμ λμ κΈ°λ₯μ μΆκ°νμ§ μμκΈ° λλ¬Έμ λλ€. useState ν¨μλ₯Ό ν΅ν΄ νμ¬μ λ²νΌ μμ μ μ₯νλλ‘ νκ² μ΅λλ€. App.js μλ¨μ import ꡬ문μ μΆκ°ν©λλ€.
import { useState } from 'react';
- useState ν¨μλ λ κ°μ§ μμλ₯Ό κ°μ§λ λ°°μ΄μ λ°νν©λλ€. 첫λ²μ§Έ μμλ stateμ κ°, λλ²μ§Έλ stateμ κ°μ μ€μ νλ ν¨μμ λλ€.
const [buttonColor, setColor] = useState('red');
- βredβ λ¬Έμμ΄μ΄ buttonColor μμμ κ°μ΄ λ©λλ€. setColor λ buttonColor μμμ κ°μ λ°κΏ μ μλ ν¨μλ₯Ό μ°Έμ‘°ν©λλ€.
Β
- μ΄μ μ΄λ²€νΈλ₯Ό λ¬μλ³΄κ² μ΅λλ€.
const [buttonColor, setColor] = useState('red'); const newColor = buttonColor === 'red' ? 'blue' : 'red'; return ( <div> <button style={{ backgroundColor: buttonColor }} onClick={() => setColor(newColor)}>change to {newColor}!</button> </div> );
Β
- ν μ€νΈλ₯Ό λλ €λ³΄κ³ κ²°κ³Όλ₯Ό νμΈν©λλ€.
Β
- μ΄μ npm startλ‘ μ€μ λ‘ μ λμνλμ§ νμΈν΄λ³Ό λ¨κ³μ λλ€.
Β