react로 tdd 쵸큼 맛보기
TRANSCRIPT
![Page 1: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/1.jpg)
React로�TDD�쵸큼�맛보기김훈민@네이버
나는자바스크립트개발자다
![Page 2: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/2.jpg)
김코딩
스마트에디터�3.0,�프론트엔드�개발�-�@네이버�
기술�블로그(huns.me)에�아주�가끔�글�쓰기�
페이스북�커뮤니티�프론트엔드개발그룹�운영하는�척�
네이버�사내�리액트�미트업�운영하는�척�
Facebook은�React를�왜�만들었을까�-�@FBDG�2015�
Angular2�vs�React,�React�vs�Angular2�-�@Deview�2016
![Page 3: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/3.jpg)
오늘의�주제는�…
단위�테스트�어떻게�작성하나요?�
TDD,�왜�해요?�
TDD�하면�뭐가�좋아요?�
TDD�하면�설계를�잘�할�수�있나요?�
TDD�하면�클린�코드를�작성할�수�있나요?�
TDD�하는�모습이�궁금해요
![Page 4: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/4.jpg)
오늘의�주제는�…
단위�테스트�어떻게�작성하나요?�
TDD,�왜�해요?�
TDD�하면�뭐가�좋아요?�
TDD�하면�설계를�잘�할�수�있나요?�
TDD�하면�클린�코드를�작성할�수�있나요?�
TDD�하는�모습이�궁금해요
![Page 5: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/5.jpg)
오늘�만들�녀석은,�
“막막”�간단한�Spinbox
기본값은�200�
값�입력�
증가�버튼을�클릭하여�값이�1�증가�
감소�버튼을�클릭하면�값이�1�감소
![Page 6: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/6.jpg)
환경은…?
Webpack�
ES2015�with�babel�
Jest�
Enzyme
![Page 7: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/7.jpg)
들어가기�전에
테스트�설정은�잘�되어있나?
![Page 8: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/8.jpg)
구현�코드 테스트�코드
![Page 9: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/9.jpg)
![Page 10: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/10.jpg)
![Page 11: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/11.jpg)
![Page 12: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/12.jpg)
![Page 13: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/13.jpg)
![Page 14: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/14.jpg)
it('스핀박스�생성할�수�있다.', () => { // given - 어떤�조건�또는�상황일�때 // when - 어떤�행위를�하면 // then - 결과가�무엇이어야�한다});
![Page 15: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/15.jpg)
it('스핀박스를�생성할�수�있다.', () => { // given // when const spinbox = mount(<Spinbox />);
// then expect(spinbox).toBeDefined();});
![Page 16: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/16.jpg)
it('스핀박스�생성할�수�있다.', () => { // setup // exercise // verify});
![Page 17: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/17.jpg)
“어디에서�시작하지?”
기본값은�200�
값�입력�
증가�버튼을�클릭하여�값이�1�증가�
감소�버튼을�클릭하면�값이�1�감소
![Page 18: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/18.jpg)
“어디에서�시작하지?”
기본값은�200�
값�입력�
증가�버튼을�클릭하여�값이�1�증가�
감소�버튼을�클릭하면�값이�1�감소
![Page 19: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/19.jpg)
it('스핀박스를�생성할�수�있다.', () => { // given // when const spinbox = mount(<Spinbox />);
// then expect(spinbox).toBeDefined();});
it('스핀박스를�생성할�수�있다.', () => { // given // when const spinbox = mount(<Spinbox />);
// then expect(spinbox).toBeDefined();});
복사해서�붙여넣기
![Page 20: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/20.jpg)
it('스핀박스를�생성할�수�있다.', () => { // given // when const spinbox = mount(<Spinbox />);
// then expect(spinbox).toBeDefined();});
![Page 21: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/21.jpg)
it('스핀박스를�생성하면�기본값은�200이어야�한다.', () => { // given // when const spinbox = mount(<Spinbox />);
// then expect(spinbox).toBeDefined();});
![Page 22: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/22.jpg)
it('스핀박스를�생성하면�기본값은�200이어야�한다.', () => { // given // when const spinbox = mount(<Spinbox />);
// then const input = spinbox .find('input') .getDOMNode();
expect(input.value).toEqual(200);});
![Page 23: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/23.jpg)
![Page 24: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/24.jpg)
![Page 25: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/25.jpg)
import React from 'react';
const Spinbox = () => ( <div> <input type=“text" /> <button>▲</button> <button>▼</button> </div>);
Spinbox.defaultProps = {};Spinbox.propTypes = {};
export default Spinbox;
![Page 26: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/26.jpg)
import React from 'react';
const Spinbox = () => ( <div> <input type="text" defaultValue="200" /> <button>▲</button> <button>▼</button> </div>);
Spinbox.defaultProps = {};Spinbox.propTypes = {};
export default Spinbox;
![Page 27: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/27.jpg)
![Page 28: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/28.jpg)
it('스핀박스를�생성하면�기본값은�200이어야�한다.', () => { // given // when const spinbox = mount(<Spinbox />);
// then const input = spinbox .find('input') .getDOMNode();
const actualValue = Number(input.value); expect(actualValue).toEqual(200);});
![Page 29: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/29.jpg)
![Page 30: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/30.jpg)
![Page 31: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/31.jpg)
![Page 32: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/32.jpg)
import React from 'react';
const Spinbox = () => ( <div> <input type="text" defaultValue="200" /> <button>▲</button> <button>▼</button> </div>);
Spinbox.defaultProps = {};Spinbox.propTypes = {};
export default Spinbox;
넘나�신경�쓰이는�것!
![Page 33: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/33.jpg)
TDD는��테스트와�구현을�반복하면서��계단을�하나씩�쌓아가는�여정�
“테스트�코드”는��어떻게�검증해야�하지?
![Page 34: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/34.jpg)
두�번째�요구사항
기본값은�200�
값�입력�
증가�버튼을�클릭하여�값이�1�증가�
감소�버튼을�클릭하면�값이�1�감소
![Page 35: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/35.jpg)
it('스핀박스를�생성하면�기본값은�200이어야�한다.', () => { // given // when const spinbox = mount(<Spinbox />);
// then const input = spinbox .find('input') .getDOMNode();
const actualValue = Number(input.value); const defaultValue = 200;
expect(actualValue).toEqual(defaultValue);});
![Page 36: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/36.jpg)
it('입력�폼에�999를�입력할�수�있다.', () => { // given // when const spinbox = mount(<Spinbox />);
// then const input = spinbox .find('input') .getDOMNode();
const actualValue = Number(input.value); const defaultValue = 200;
expect(actualValue).toEqual(defaultValue);});
![Page 37: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/37.jpg)
it('입력�폼에�999를�입력할�수�있다.', () => { // given const spinbox = mount(<Spinbox />);
// when const input = spinbox.find('input'); input.simulate('change', { target: { value: '999' } });
// then const inputNode = input.getDOMNode(); const actualValue = Number(inputNode.value);
expect(actualValue).toEqual(999);});
![Page 38: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/38.jpg)
![Page 39: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/39.jpg)
import React from 'react';
const Spinbox = () => ( <div> <input type="text" defaultValue="200" /> <button>▲</button> <button>▼</button> </div>);
Spinbox.defaultProps = {};Spinbox.propTypes = {};
export default Spinbox;
![Page 40: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/40.jpg)
import React from 'react';
const Spinbox = () => ( <div> <input type="text" defaultValue="200" onChange={ () => { this.setState({ value: 999 }) } } /> <button>▲</button> <button>▼</button> </div>);
Spinbox.defaultProps = {};Spinbox.propTypes = {};
export default Spinbox;
아놬!�무상태�컴포넌트!
![Page 41: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/41.jpg)
![Page 42: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/42.jpg)
import React from 'react';
const Spinbox = () => ( <div> <input type="text" defaultValue="200" /> <button>▲</button> <button>▼</button> </div>);
Spinbox.defaultProps = {};Spinbox.propTypes = {};
export default Spinbox;
안전할�때�까지�되돌리기!
![Page 43: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/43.jpg)
![Page 44: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/44.jpg)
it('입력�폼에�숫자�값을�입력할�수�있다.', () => { // given const spinbox = mount(<Spinbox />);
// when const input = spinbox.find('input'); input.simulate('change', { target: { value: '999' } });
// then const inputNode = input.getDOMNode(); const actualValue = Number(inputNode.value);
expect(actualValue).toEqual(999);});
![Page 45: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/45.jpg)
it.skip('입력�폼에�숫자�값을�입력할�수�있다.', () => { // given const spinbox = mount(<Spinbox />);
// when const input = spinbox.find('input'); input.simulate('change', { target: { value: '999' } });
// then const inputNode = input.getDOMNode(); const actualValue = Number(inputNode.value);
expect(actualValue).toEqual(999);});
![Page 46: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/46.jpg)
![Page 47: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/47.jpg)
import React from 'react';
const Spinbox = () => ( <div> <input type="text" defaultValue="200" /> <button>▲</button> <button>▼</button> </div>);
Spinbox.defaultProps = {};Spinbox.propTypes = {};
export default Spinbox;
![Page 48: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/48.jpg)
import React from ‘react';
class Spinbox extends React.Component { render() { return ( <div> <input type="text" defaultValue="200" /> <button>▲</button> <button>▼</button> </div> ); }}
Spinbox.defaultProps = {};Spinbox.propTypes = {};
export default Spinbox;
![Page 49: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/49.jpg)
![Page 50: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/50.jpg)
it.skip('입력�폼에�숫자�값을�입력할�수�있다.', () => { // given const spinbox = mount(<Spinbox />);
// when const input = spinbox.find('input'); input.simulate('change', { target: { value: '999' } });
// then const inputNode = input.getDOMNode(); const actualValue = Number(inputNode.value);
expect(actualValue).toEqual(999);});
![Page 51: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/51.jpg)
it('입력�폼에�999를�입력할�수�있다.', () => { // given const spinbox = mount(<Spinbox />);
// when const input = spinbox.find('input'); input.simulate('change', { target: { value: '999' } });
// then const inputNode = input.getDOMNode(); const actualValue = Number(inputNode.value);
expect(actualValue).toEqual(999);});
![Page 52: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/52.jpg)
![Page 53: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/53.jpg)
class Spinbox extends React.Component { componentWillMount() { this.state = { value: 200 }; } render() { return ( <div> <input type="text" value={ this.state.value } onChange={ () => { this.setState({ value: 999 }) } } /> <button>▲</button> <button>▼</button> </div> ); }}// 생략 …
![Page 54: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/54.jpg)
![Page 55: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/55.jpg)
![Page 56: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/56.jpg)
class Spinbox extends React.Component { componentWillMount() { this.state = { value: 200 }; } render() { return ( <div> <input type="text" value={ this.state.value } onChange={ () => { this.setState({ value: 999 }) } } /> <button>▲</button> <button>▼</button> </div> ); }}// 생략 …
![Page 57: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/57.jpg)
class Spinbox extends React.Component { componentWillMount() { this.state = { value: 200 }; this.handleChangeInput = this.handleChangeInput.bind(this); }
render() { return ( <div> <input type="text" value={ this.state.value } onChange={ this.handleChangeInput } /> <button>▲</button> <button>▼</button> </div> ); }
handleChangeInput() { this.setState({ value: 999 }); }}
![Page 58: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/58.jpg)
it('스핀박스를�생성할�수�있다.', () => { // given // when const spinbox = mount(<Spinbox />);
// then expect(spinbox).toBeDefined();});
it('스핀박스를�생성하면�기본값은�200이어야�한다.', () => { … });
it('입력�폼에�999를�입력할�수�있다.', () => { … });
![Page 59: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/59.jpg)
it('스핀박스를�생성하면�기본값은�200이어야�한다.', () => { … });
it('입력�폼에�999를�입력할�수�있다.', () => { … });
![Page 60: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/60.jpg)
it('입력�폼에�0을�입력할�수�있다.', () => { // given const spinbox = mount(<Spinbox />);
// when const input = spinbox.find('input'); input.simulate('change', { target: { value: '0' } });
// then const inputNode = input.getDOMNode(); const actualValue = Number(inputNode.value);
expect(actualValue).toEqual(0);});
![Page 61: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/61.jpg)
![Page 62: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/62.jpg)
handleChangeInput() { this.setState({ value: 999 });}
![Page 63: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/63.jpg)
handleChangeInput(e) { this.setState({ value: e.target.value });}
![Page 64: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/64.jpg)
![Page 65: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/65.jpg)
![Page 66: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/66.jpg)
it('스핀박스를�생성하면�기본값은�200이어야�한다.', () => { // given // when const spinbox = mount(<Spinbox />); // 생략…});
it('입력�폼에�999를�입력할�수�있다.', () => { // given const spinbox = mount(<Spinbox />); // 생략…
});
it('입력�폼에�0을�입력할�수�있다.', () => { // given const spinbox = mount(<Spinbox />); // 생략…});
![Page 67: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/67.jpg)
let spinbox;
beforeEach(() => { spinbox = mount(<Spinbox />);});
it('스핀박스를�생성하면�기본값은�200이어야�한다.', () => { … });
it('입력�폼에�999를�입력할�수�있다.', () => { … });
it('입력�폼에�0을�입력할�수�있다.', () => { … });
![Page 68: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/68.jpg)
![Page 69: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/69.jpg)
it('입력�폼에�999을�입력할�수�있다.', () => { // then const inputNode = input.getDOMNode(); const actualValue = Number(inputNode.value);
expect(actualValue).toEqual(999);});
it('입력�폼에�0을�입력할�수�있다.', () => { // then const inputNode = input.getDOMNode(); const actualValue = Number(inputNode.value);
expect(actualValue).toEqual(0);});
![Page 70: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/70.jpg)
let spinbox;
beforeEach(() => { spinbox = mount(<Spinbox />);});
function getValueFromInputNode(input) { const inputNode = input.getDOMNode(); return Number(inputNode.value);}
it('입력�폼에�999를�입력할�수�있다.', () => { // …생략 // then const actualValue = getValueFromInputNode(input); expect(actualValue).toEqual(999);});
it('입력�폼에�0을�입력할�수�있다.', () => { // …생략 // then const actualValue = getValueFromInputNode(input); expect(actualValue).toEqual(0);});
![Page 71: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/71.jpg)
![Page 72: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/72.jpg)
세�번째�요구사항
기본값은 200
값 입력
증가 버튼을 클릭하여 값이 1 증가
감소 버튼을 클릭하면 값이 1 감소
![Page 73: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/73.jpg)
it('증가�버튼을�클릭하여�값을�1�증가시킬�수�있다.', () => { // given // when const input = spinbox.find('input'); input.simulate('change', { target: { value: '0' } });
// then const actualValue = getValueFromInputNode(input); expect(actualValue).toEqual(0);});
![Page 74: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/74.jpg)
it('증가�버튼을�클릭하여�값을�1�증가시킬�수�있다.', () => { // given const defaultValue = 200;
// when const incrementBtn = spinbox.find('[data-name="increment"]'); incrementBtn.simulate('click');
// then const actualValue = getValueFromInputNode(spinbox.find('input')); expect(actualValue).toEqual(defaultValue + 1);});
![Page 75: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/75.jpg)
![Page 76: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/76.jpg)
render() { return ( <div> <input type="text" value={ this.state.value } onChange={ this.handleChangeInput } /> <button data-name="increment">▲</button> <button>▼</button> </div> );}
![Page 77: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/77.jpg)
![Page 78: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/78.jpg)
render() { return ( <div> <input type="text" value={ this.state.value } onChange={ this.handleChangeInput } /> <button data-name="increment" onClick={ () => { this.setState({ value: 201 }) } }>▲</button> <button>▼</button> </div> );}
![Page 79: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/79.jpg)
![Page 80: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/80.jpg)
![Page 81: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/81.jpg)
render() { return ( <div> <input type="text" value={ this.state.value } onChange={ this.handleChangeInput } /> <button data-name="increment" onClick={ () => { this.setState({ value: 201 }) } }>▲</button> <button>▼</button> </div> );}
![Page 82: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/82.jpg)
componentWillMount() { this.state = { value: 200 }; this.handleChangeInput = this.handleChangeInput.bind(this); this.handleClickIncrement = this.handleClickIncrement.bind(this);}
render() { return ( <div> <input type="text" value={ this.state.value } onChange={ this.handleChangeInput } /> <button data-name="increment" onClick={ this.handleClickIncrement }>▲</button> <button>▼</button> </div> );}
handleClickIncrement() { this.setState({ value: 201 });}
![Page 83: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/83.jpg)
![Page 84: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/84.jpg)
it('증가�버튼을�세�번�클릭하여�값을�3�증가시킬�수�있다.', () => { // given const defaultValue = 200;
// when const incrementBtn = spinbox.find('[data-name="increment"]'); incrementBtn.simulate('click'); incrementBtn.simulate('click'); incrementBtn.simulate('click');
// then const actualValue = getValueFromInputNode(spinbox.find('input')); expect(actualValue).toEqual(defaultValue + 3);});
![Page 85: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/85.jpg)
![Page 86: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/86.jpg)
handleClickIncrement() { this.setState({ value: 201 });}
![Page 87: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/87.jpg)
handleClickIncrement() { this.setState({ value: this.state.value + 1 });}
![Page 88: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/88.jpg)
![Page 89: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/89.jpg)
![Page 90: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/90.jpg)
it('스핀박스를�생성하면�기본값은�200이어야�한다.', () => { … }); it('입력�폼에�999를�입력할�수�있다.', () => { … }); it('입력�폼에�0을�입력할�수�있다.', () => { … }); it('증가�버튼을�클릭하여�값을�1�증가시킬�수�있다.', () => { … }); it('증가�버튼을�세�번�클릭하여�값을�3�증가시킬�수�있다.', () => { … });
![Page 91: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/91.jpg)
describe('기본값�>', () => { it('스핀박스를�생성하면�기본값이�200이어야�한다.', () => { … });});
describe('값�입력�>', () => { it('입력�폼에�999를�입력할�수�있다.', () => { … }); it('입력�폼에�0을�입력할�수�있다.', () => { … });});
describe('값�증가�>', () => { it('증가�버튼을�클릭하여�값을�1�증가시킬�수�있다.', () => { … }); it('증가�버튼을�세�번�클릭하여�값을�3�증가시킬�수�있다.', () => { … });});
![Page 92: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/92.jpg)
![Page 93: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/93.jpg)
describe(‘값�입력�>', () => { it('입력�폼에�999를�입력할�수�있다.', () => { // given // when const input = spinbox.find('input'); // … 생략 });
it('입력�폼에�0을�입력할�수�있다.', () => { // given // when const input = spinbox.find('input'); // … 생략 });});
![Page 94: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/94.jpg)
describe(‘값�입력�>', () => { let input;
beforeEach(() => { input = spinbox.find('input'); });
it('입력�폼에�999를�입력할�수�있다.', () => { … }); it('입력�폼에�0을�입력할�수�있다.', () => { … });});
![Page 95: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/95.jpg)
![Page 96: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/96.jpg)
describe(‘기본값�>', () => { it('스핀박스를�생성하면�기본값이�200이어야�한다.', () => { … });});
describe('값�입력�>', () => { let input;
beforeEach(() => { input = spinbox.find('input'); });
it('입력�폼에�999를�입력할�수�있다.', () => { … }); it('입력�폼에�0을�입력할�수�있다.', () => { … });});
describe('값�증가�>', () => { const defaultValue = 200; let incrementBtn;
beforeEach(() => { incrementBtn = spinbox.find('[data-name="increment"]'); });
it('증가�버튼을�클릭하여�값을�1�증가시킬�수�있다.', () => { … }); it('증가�버튼을�세�번�클릭하여�값을�3�증가시킬�수�있다.', () => { … });});
![Page 97: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/97.jpg)
![Page 98: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/98.jpg)
얻는�것과�잃는�것
변경의�포인트는�집중�
코드는�덜�직관적
it('증가 버튼을 세 번 클릭하여 값을 3 증가시킬 수 있다.', () => { // given // when incrementBtn.simulate('click'); incrementBtn.simulate('click'); incrementBtn.simulate('click');
// then const actualValue = getValueFromInputNode(spinbox.find('input')); expect(actualValue).toEqual(defaultValue + 3);});
뭘까?
![Page 99: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/99.jpg)
네�번째�요구사항
기본값은�200�
값�입력�
증가�버튼을�클릭하여�값이�1�증가�
감소�버튼을�클릭하면�값이�1�감소
![Page 100: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/100.jpg)
describe('값�증가�>', () => { const defaultValue = 200; let incrementBtn;
beforeEach(() => { incrementBtn = spinbox.find('[data-name="increment"]'); });
it('증가�버튼을�클릭하여�값을�1�증가시킬�수�있다.', () => { // given // when incrementBtn.simulate('click');
// then const actualValue = getValueFromInputNode(spinbox.find('input')); expect(actualValue).toEqual(defaultValue + 1); });});
![Page 101: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/101.jpg)
describe('값�감소�>', () => { const defaultValue = 200; let decrementBtn;
beforeEach(() => { decrementBtn = spinbox.find('[data-name="decrement"]'); });
it('감소�버튼을�클릭하여�값을�1�감소시킬�수�있다.', () => { // given // when decrementBtn.simulate('click');
// then const actualValue = getValueFromInputNode(spinbox.find('input')); expect(actualValue).toEqual(defaultValue - 1); });});
![Page 102: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/102.jpg)
![Page 103: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/103.jpg)
class Spinbox extends React.Component { componentWillMount() { this.state = { value: 200 }; this.handleChangeInput = this.handleChangeInput.bind(this); this.handleClickIncrement = this.handleClickIncrement.bind(this); this.handleClickDecrement = this.handleClickDecrement.bind(this); }
render() { … }
handleClickDecrement() { this.setState({ value: this.state.value - 1 }); }
handleClickIncrement() { … } handleChangeInput(e) { … }}
![Page 104: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/104.jpg)
render() { return ( <div> <input type="text" value={ this.state.value } onChange={ this.handleChangeInput } /> <button data-name="increment" onClick={ this.handleClickIncrement }>▲</button> <button>▼</button> </div> );}
![Page 105: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/105.jpg)
render() { return ( <div> <input type="text" value={ this.state.value } onChange={ this.handleChangeInput } /> <button data-name="increment" onClick={ this.handleClickIncrement }>▲</button> <button data-name="decrement" onClick={ this.handleClickDecrement }>▼</button> </div> );}
![Page 106: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/106.jpg)
![Page 107: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/107.jpg)
![Page 108: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/108.jpg)
이걸로�충분할까?
불안하다면�망설이지�말고�
테스트�작성!
![Page 109: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/109.jpg)
it('감소�버튼을�세�번�클릭하여�값을�3�감소시킬�수�있다.', () => { // given // when decrementBtn.simulate('click'); decrementBtn.simulate('click'); decrementBtn.simulate('click');
// then const actualValue = getValueFromInputNode(spinbox.find('input')); expect(actualValue).toEqual(defaultValue - 3);});
![Page 110: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/110.jpg)
![Page 111: React로 TDD 쵸큼 맛보기](https://reader036.vdocuments.mx/reader036/viewer/2022081414/5aad01c17f8b9a003b8b47cb/html5/thumbnails/111.jpg)
끝!
감사합니다!